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;
1951#[cfg(target_arch = "aarch64")]
1952pub const MINSIGSTKSZ: usize = 6144;
1953#[cfg(target_arch = "aarch64")]
1954pub const SIGSTKSZ: usize = 12288;
1955#[cfg(not(target_arch = "aarch64"))]
1956pub const MINSIGSTKSZ: usize = 2048;
1957#[cfg(not(target_arch = "aarch64"))]
1958pub const SIGSTKSZ: usize = 8192;
1959
1960pub const SI_USER: c_int = 0;
1961pub const SI_TKILL: c_int = -6;
1962
1963#[repr(C)]
1964pub struct timespec {
1965 pub tv_sec: c_long,
1966 pub tv_nsec: c_long,
1967}
1968
1969#[repr(C)]
1970pub struct siginfo_t {
1971 pub si_signo: c_int,
1972 pub si_errno: c_int,
1973 pub si_code: c_int,
1974 _pad: [u8; 128 - 3 * core::mem::size_of::<c_int>()],
1976}
1977
1978#[repr(C)]
1979pub struct stack_t {
1980 pub ss_sp: *mut c_void,
1981 pub ss_flags: c_int,
1982 pub ss_size: usize,
1983}
1984
1985#[repr(C)]
1988pub struct KSigAction {
1989 pub sa_handler: usize,
1990 pub sa_flags: c_ulong,
1991 pub sa_restorer: usize,
1992 pub sa_mask: [c_ulong; 1],
1993}
1994
1995#[repr(C)]
1997pub struct sigaction {
1998 pub sa_handler: usize,
1999 pub sa_mask: [u64; 16],
2000 pub sa_flags: c_int,
2001 pub sa_restorer: usize,
2002}
2003
2004pub type SigSetT = c_ulong;
2005
2006#[cfg(target_arch = "x86_64")]
2007core::arch::global_asm!(
2008 ".global sig_restorer",
2009 ".type sig_restorer, @function",
2010 "sig_restorer:",
2011 "mov eax, 15",
2012 "syscall",
2013);
2014
2015#[cfg(target_arch = "aarch64")]
2016core::arch::global_asm!(
2017 ".global sig_restorer",
2018 ".type sig_restorer, @function",
2019 "sig_restorer:",
2020 "mov x8, #139",
2021 "svc #0",
2022);
2023
2024#[cfg(target_arch = "riscv64")]
2025core::arch::global_asm!(
2026 ".global sig_restorer",
2027 ".type sig_restorer, @function",
2028 "sig_restorer:",
2029 "li a7, 139",
2030 "ecall",
2031);
2032
2033extern "C" {
2034 fn sig_restorer();
2035}
2036
2037#[inline]
2038unsafe fn sys_rt_sigaction(sig: c_int,
2039 act: *const KSigAction,
2040 oldact: *mut KSigAction,
2041 sigsetsize: usize,) -> i64 {
2042 <Arch as Syscalls>::syscall4(SYS_RT_SIGACTION, sig as i64, act as i64, oldact as i64, sigsetsize as i64)
2043}
2044
2045#[inline]
2046unsafe fn sys_rt_sigprocmask(how: c_int,
2047 set: *const SigSetT,
2048 oldset: *mut SigSetT,
2049 sigsetsize: usize,) -> i64 {
2050 <Arch as Syscalls>::syscall4(SYS_RT_SIGPROCMASK, how as i64, set as i64, oldset as i64, sigsetsize as i64)
2051}
2052
2053#[inline]
2054unsafe fn sys_rt_sigpending(set: *mut SigSetT, sigsetsize: usize) -> i64 {
2055 <Arch as Syscalls>::syscall2(SYS_RT_SIGPENDING, set as i64, sigsetsize as i64)
2056}
2057
2058#[inline]
2059unsafe fn sys_rt_sigsuspend(mask: *const SigSetT, sigsetsize: usize) -> i64 {
2060 <Arch as Syscalls>::syscall2(SYS_RT_SIGSUSPEND, mask as i64, sigsetsize as i64)
2061}
2062
2063#[inline]
2064unsafe fn sys_rt_sigtimedwait(set: *const SigSetT,
2065 info: *mut siginfo_t,
2066 timeout: *const timespec,
2067 sigsetsize: usize,) -> i64 {
2068 <Arch as Syscalls>::syscall4(SYS_RT_SIGTIMEDWAIT, set as i64, info as i64, timeout as i64, sigsetsize as i64)
2069}
2070
2071#[inline]
2072unsafe fn sys_sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> i64 {
2073 <Arch as Syscalls>::syscall2(SYS_SIGALTSTACK, ss as i64, old_ss as i64)
2074}
2075
2076#[inline]
2077unsafe fn sys_tgkill(tgid: c_int, tid: c_int, sig: c_int) -> i64 {
2078 <Arch as Syscalls>::syscall3(SYS_TGKILL, tgid as i64, tid as i64, sig as i64)
2079}
2080
2081const CLOCK_REALTIME: c_int = 0;
2082const CLOCK_MONOTONIC: c_int = 1;
2083
2084#[inline]
2085unsafe fn sys_clock_gettime(clockid: c_int, ts: *mut timespec) -> i64 {
2086 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETTIME, clockid as i64, ts as i64)
2087}
2088
2089#[no_mangle]
2093pub unsafe extern "C" fn sigprocmask(
2094 how: c_int,
2095 set: *const SigSetT,
2096 oldset: *mut SigSetT,
2097) -> c_int {
2098 let internal_mask: SigSetT = (1u64 << 31) | (1u64 << 32);
2100 let filtered: SigSetT;
2101 let set_ptr: *const SigSetT = if set.is_null() {
2102 set
2103 } else {
2104 filtered = *set & !internal_mask;
2105 &filtered
2106 };
2107 let r = sys_rt_sigprocmask(how, set_ptr, oldset, core::mem::size_of::<SigSetT>());
2108 if !oldset.is_null() {
2109 *oldset &= !internal_mask;
2110 }
2111 if r < 0 { -1 } else { 0 }
2112}
2113
2114#[inline]
2115unsafe fn sys_kill(pid: c_int, sig: c_int) -> i64 {
2116 <Arch as Syscalls>::syscall2(SYS_KILL, pid as i64, sig as i64)
2117}
2118
2119#[inline]
2120unsafe fn sys_getpid() -> i64 {
2121 <Arch as Syscalls>::syscall0(SYS_GETPID)
2122}
2123
2124#[no_mangle]
2125pub unsafe extern "C" fn sigaction(
2126 signum: c_int,
2127 act: *const sigaction,
2128 oldact: *mut sigaction,
2129) -> c_int {
2130 let mut kact: KSigAction = core::mem::zeroed();
2131 let act_ptr = if act.is_null() {
2132 core::ptr::null()
2133 } else {
2134 kact.sa_handler = (*act).sa_handler;
2135 kact.sa_flags = ((*act).sa_flags as c_ulong) | SA_RESTORER;
2136 kact.sa_restorer = if (*act).sa_flags as c_ulong & SA_RESTORER != 0
2137 && (*act).sa_restorer != 0
2138 {
2139 (*act).sa_restorer
2140 } else {
2141 sig_restorer as *const () as usize
2142 };
2143 kact.sa_mask[0] = (*act).sa_mask[0];
2144 &kact
2145 };
2146 let mut kold: KSigAction = core::mem::zeroed();
2147 let old_ptr = if oldact.is_null() { core::ptr::null_mut() } else { &mut kold };
2148 let r = sys_rt_sigaction(signum, act_ptr, old_ptr, 8);
2149 if r < 0 {
2150 ERRNO!() = (-r) as c_int;
2151 return -1;
2152 }
2153 if !oldact.is_null() {
2154 (*oldact).sa_handler = kold.sa_handler;
2155 (*oldact).sa_flags = kold.sa_flags as c_int;
2156 (*oldact).sa_restorer = kold.sa_restorer;
2157 (*oldact).sa_mask = [0; 16];
2158 (*oldact).sa_mask[0] = kold.sa_mask[0];
2159 }
2160 0
2161}
2162
2163#[no_mangle]
2164pub unsafe extern "C" fn signal(signum: c_int, handler: usize) -> usize {
2165 let act = sigaction {
2168 sa_handler: handler,
2169 sa_mask: [0; 16],
2170 sa_flags: SA_RESTART as c_int,
2171 sa_restorer: 0,
2172 };
2173 let mut old: sigaction = core::mem::zeroed();
2174 if sigaction(signum, &act, &mut old) == -1 {
2175 SIG_ERR
2176 } else {
2177 old.sa_handler
2178 }
2179}
2180
2181#[no_mangle]
2182pub unsafe extern "C" fn kill(pid: c_int, sig: c_int) -> c_int {
2183 let r = sys_kill(pid, sig);
2184 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2185 0
2186}
2187
2188#[no_mangle]
2189pub unsafe extern "C" fn tgkill(tgid: c_int, tid: c_int, sig: c_int) -> c_int {
2190 let r = sys_tgkill(tgid, tid, sig);
2191 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2192 0
2193}
2194
2195#[no_mangle]
2196pub unsafe extern "C" fn getpid() -> c_int {
2197 sys_getpid() as c_int
2198}
2199
2200#[no_mangle]
2201pub unsafe extern "C" fn raise(sig: c_int) -> c_int {
2202 let r = sys_tgkill(sys_getpid() as c_int, sys_gettid() as c_int, sig);
2203 if r < 0 {
2204 ERRNO!() = (-r) as c_int;
2205 -1
2206 } else {
2207 0
2208 }
2209}
2210
2211#[no_mangle]
2212pub unsafe extern "C" fn sigemptyset(set: *mut SigSetT) -> c_int {
2213 *set = 0;
2214 0
2215}
2216
2217#[no_mangle]
2218pub unsafe extern "C" fn sigfillset(set: *mut SigSetT) -> c_int {
2219 *set = 0xFFFF_FFFC_7FFF_FFFFu64;
2221 0
2222}
2223
2224#[no_mangle]
2225pub unsafe extern "C" fn sigaddset(set: *mut SigSetT, signum: c_int) -> c_int {
2226 let s = (signum as c_uint).wrapping_sub(1);
2227 if s as usize >= 64 {
2228 ERRNO!() = EINVAL;
2229 return -1;
2230 }
2231 if signum >= 32 && signum < __libc_current_sigrtmin() {
2233 return 0;
2234 }
2235 *set |= 1u64 << s;
2236 0
2237}
2238
2239#[no_mangle]
2240pub unsafe extern "C" fn sigdelset(set: *mut SigSetT, signum: c_int) -> c_int {
2241 let s = (signum as c_uint).wrapping_sub(1);
2242 if s as usize >= 64 {
2243 ERRNO!() = EINVAL;
2244 return -1;
2245 }
2246 if signum >= 32 && signum < __libc_current_sigrtmin() {
2248 return 0;
2249 }
2250 *set &= !(1u64 << s);
2251 0
2252}
2253
2254#[no_mangle]
2255pub unsafe extern "C" fn sigismember(set: *const SigSetT, signum: c_int) -> c_int {
2256 let s = (signum as c_uint).wrapping_sub(1);
2257 if s as usize >= 64 { return 0; }
2258 if signum >= 32 && signum < __libc_current_sigrtmin() {
2260 return 0;
2261 }
2262 ((*set & (1u64 << s)) != 0) as c_int
2263}
2264
2265#[no_mangle]
2266pub unsafe extern "C" fn sigpending(set: *mut SigSetT) -> c_int {
2267 let r = sys_rt_sigpending(set, core::mem::size_of::<SigSetT>());
2268 if r < 0 {
2269 ERRNO!() = (-r) as c_int;
2270 return -1;
2271 }
2272 0
2273}
2274
2275#[no_mangle]
2276pub unsafe extern "C" fn sigsuspend(mask: *const SigSetT) -> c_int {
2277 let r = sys_rt_sigsuspend(mask, core::mem::size_of::<SigSetT>());
2278 if r < 0 {
2279 ERRNO!() = (-r) as c_int;
2280 }
2281 -1
2282}
2283
2284#[no_mangle]
2285pub unsafe extern "C" fn sigtimedwait(
2286 mask: *const SigSetT,
2287 info: *mut siginfo_t,
2288 timeout: *const timespec,
2289) -> c_int {
2290 loop {
2291 let r = sys_rt_sigtimedwait(mask, info, timeout, core::mem::size_of::<SigSetT>());
2292 if r >= 0 {
2293 return r as c_int;
2294 }
2295 let e = (-r) as c_int;
2296 if e != EINTR {
2297 ERRNO!() = e;
2298 return -1;
2299 }
2300 }
2301}
2302
2303#[no_mangle]
2304pub unsafe extern "C" fn sigwaitinfo(
2305 mask: *const SigSetT,
2306 info: *mut siginfo_t,
2307) -> c_int {
2308 sigtimedwait(mask, info, core::ptr::null())
2309}
2310
2311#[no_mangle]
2312pub unsafe extern "C" fn sigwait(
2313 mask: *const SigSetT,
2314 sig: *mut c_int,
2315) -> c_int {
2316 let mut info: siginfo_t = core::mem::zeroed();
2317 if sigtimedwait(mask, &mut info, core::ptr::null()) < 0 {
2318 return ERRNO!();
2319 }
2320 *sig = info.si_signo;
2321 0
2322}
2323
2324#[no_mangle]
2325pub unsafe extern "C" fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int {
2326 if !ss.is_null() {
2327 if (*ss).ss_flags & SS_ONSTACK != 0 {
2328 ERRNO!() = EINVAL;
2329 return -1;
2330 }
2331 if (*ss).ss_flags & SS_DISABLE == 0 && (*ss).ss_size < MINSIGSTKSZ {
2332 ERRNO!() = ENOMEM;
2333 return -1;
2334 }
2335 }
2336 let r = sys_sigaltstack(ss, old_ss);
2337 if r < 0 {
2338 ERRNO!() = (-r) as c_int;
2339 return -1;
2340 }
2341 0
2342}
2343
2344#[no_mangle]
2350#[inline(never)]
2351#[cfg(target_arch = "x86_64")]
2352pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2353 core::arch::asm!(
2354 "mov rax, [rsp]",
2355 "lea rcx, [rsp + 8]",
2356 "mov [r8], rbx",
2357 "mov [r8 + 8], rbp",
2358 "mov [r8 + 16], r12",
2359 "mov [r8 + 24], r13",
2360 "mov [r8 + 32], r14",
2361 "mov [r8 + 40], r15",
2362 "mov [r8 + 48], rcx",
2363 "mov [r8 + 56], rax",
2364 in("r8") env,
2365 lateout("rax") _,
2366 lateout("rcx") _,
2367 options(nostack),
2368 );
2369 0
2370}
2371
2372#[no_mangle]
2373#[inline(never)]
2374#[cfg(target_arch = "x86_64")]
2375pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2376 let ret = if val == 0 { 1 } else { val } as u32;
2377 core::arch::asm!(
2378 "mov rbx, [r8]",
2379 "mov rbp, [r8 + 8]",
2380 "mov r12, [r8 + 16]",
2381 "mov r13, [r8 + 24]",
2382 "mov r14, [r8 + 32]",
2383 "mov r15, [r8 + 40]",
2384 "mov rsp, [r8 + 48]",
2385 "mov eax, edx",
2386 "jmp [r8 + 56]",
2387 in("r8") env,
2388 in("edx") ret,
2389 options(noreturn),
2390 );
2391}
2392
2393#[no_mangle]
2394#[unsafe(naked)]
2395#[cfg(target_arch = "aarch64")]
2396pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2397 core::arch::naked_asm!(
2398 "stp x19, x20, [x0, #0]",
2399 "stp x21, x22, [x0, #16]",
2400 "stp x23, x24, [x0, #32]",
2401 "stp x25, x26, [x0, #48]",
2402 "stp x27, x28, [x0, #64]",
2403 "stp x29, x30, [x0, #80]",
2404 "mov x2, sp",
2405 "str x2, [x0, #104]",
2406 "stp d8, d9, [x0, #112]",
2407 "stp d10, d11, [x0, #128]",
2408 "stp d12, d13, [x0, #144]",
2409 "stp d14, d15, [x0, #160]",
2410 "mov x0, #0",
2411 "ret",
2412 );
2413}
2414
2415#[no_mangle]
2416#[inline(never)]
2417#[cfg(target_arch = "aarch64")]
2418pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2419 let ret = if val == 0 { 1 } else { val } as u64;
2420 core::arch::asm!(
2421 "ldp x19, x20, [x0]",
2422 "ldp x21, x22, [x0, #16]",
2423 "ldp x23, x24, [x0, #32]",
2424 "ldp x25, x26, [x0, #48]",
2425 "ldp x27, x28, [x0, #64]",
2426 "ldp x29, x30, [x0, #80]",
2427 "ldr x2, [x0, #104]",
2428 "mov sp, x2",
2429 "ldp d8, d9, [x0, #112]",
2430 "ldp d10, d11, [x0, #128]",
2431 "ldp d12, d13, [x0, #144]",
2432 "ldp d14, d15, [x0, #160]",
2433 "mov x0, x1",
2434 "br x30",
2435 in("x0") env,
2436 in("x1") ret,
2437 options(noreturn),
2438 );
2439}
2440
2441#[no_mangle]
2442#[unsafe(naked)]
2443#[cfg(target_arch = "riscv64")]
2444pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2445 core::arch::naked_asm!(
2446 "sd s0, 0(a0)",
2447 "sd s1, 8(a0)",
2448 "sd s2, 16(a0)",
2449 "sd s3, 24(a0)",
2450 "sd s4, 32(a0)",
2451 "sd s5, 40(a0)",
2452 "sd s6, 48(a0)",
2453 "sd s7, 56(a0)",
2454 "sd s8, 64(a0)",
2455 "sd s9, 72(a0)",
2456 "sd s10, 80(a0)",
2457 "sd s11, 88(a0)",
2458 "sd sp, 96(a0)",
2459 "sd ra, 104(a0)",
2460 "li a0, 0",
2461 "ret",
2462 );
2463}
2464
2465#[no_mangle]
2466#[inline(never)]
2467#[cfg(target_arch = "riscv64")]
2468pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2469 let ret = if val == 0 { 1 } else { val } as u64;
2470 core::arch::asm!(
2471 "ld s0, 0(a0)",
2472 "ld s1, 8(a0)",
2473 "ld s2, 16(a0)",
2474 "ld s3, 24(a0)",
2475 "ld s4, 32(a0)",
2476 "ld s5, 40(a0)",
2477 "ld s6, 48(a0)",
2478 "ld s7, 56(a0)",
2479 "ld s8, 64(a0)",
2480 "ld s9, 72(a0)",
2481 "ld s10, 80(a0)",
2482 "ld s11, 88(a0)",
2483 "ld sp, 96(a0)",
2484 "ld ra, 104(a0)",
2485 "mv a0, a1",
2486 "ret",
2487 in("a0") env,
2488 in("a1") ret,
2489 options(noreturn),
2490 );
2491}
2492
2493#[no_mangle]
2501#[unsafe(naked)]
2502#[cfg(target_arch = "x86_64")]
2503pub unsafe extern "C" fn sigsetjmp(_env: *mut c_ulong, _savemask: c_int) -> c_int {
2504 core::arch::naked_asm!("jmp sigsetjmp_real");
2505}
2506
2507#[no_mangle]
2508#[unsafe(naked)]
2509#[cfg(target_arch = "x86_64")]
2510pub unsafe extern "C" fn __sigsetjmp(_env: *mut c_ulong, _savemask: c_int) -> c_int {
2511 core::arch::naked_asm!("jmp sigsetjmp_real");
2512}
2513
2514#[cfg(target_arch = "x86_64")]
2515core::arch::global_asm!(
2516 ".type sigsetjmp_real, @function",
2517 "sigsetjmp_real:",
2518 " test esi, esi",
2519 " jz 1f",
2520 " pop qword ptr [rdi + 64]",
2521 " mov qword ptr [rdi + 80], rbx",
2522 " mov rbx, rdi",
2526 " call setjmp",
2527 " push qword ptr [rbx + 64]",
2528 " mov rdi, rbx",
2529 " mov esi, eax",
2530 " mov rbx, qword ptr [rbx + 80]",
2531 " lea rdx, [rdi + 72]",
2532 " test esi, esi",
2533 " jz 2f",
2534 " mov rsi, rdx",
2535 " xor rdx, rdx",
2536 " mov edi, 2",
2537 " jmp 3f",
2538 "2:",
2539 " xor rsi, rsi",
2540 " mov edi, 2",
2541 "3:",
2542 " mov eax, 14",
2543 " mov r10d, 8",
2544 " syscall",
2545 " test esi, esi",
2546 " jnz 4f",
2547 " mov rax, 0xfffffffe7fffffff",
2548 " and qword ptr [rdx], rax",
2549 "4:",
2550 " mov eax, esi",
2551 " ret",
2552 "1:",
2553 " jmp setjmp",
2554);
2555
2556#[no_mangle]
2557#[inline(never)]
2558#[cfg(target_arch = "x86_64")]
2559pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2560 longjmp(env, val);
2561}
2562
2563#[no_mangle]
2564#[cfg(target_arch = "aarch64")]
2565pub unsafe extern "C" fn __sigsetjmp_tail(env: *mut c_ulong, ret: c_int) -> c_int {
2566 const SIG_SETMASK: c_int = 2;
2567 let ss = env.add(23) as *mut SigSetT;
2568 let set = if ret != 0 { ss as *const SigSetT } else { core::ptr::null() };
2569 let old = if ret != 0 { core::ptr::null_mut() } else { ss };
2570 let _ = sys_rt_sigprocmask(SIG_SETMASK, set, old, core::mem::size_of::<SigSetT>());
2571 ret
2572}
2573
2574#[no_mangle]
2575#[unsafe(naked)]
2576#[cfg(target_arch = "aarch64")]
2577pub unsafe extern "C" fn sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2578 core::arch::naked_asm!(
2579 "cbz w1, setjmp",
2580 "str x30, [x0, #176]",
2581 "str x19, [x0, #192]",
2582 "mov x19, x0",
2583 "bl setjmp",
2584 "mov w1, w0",
2585 "mov x0, x19",
2586 "ldr x30, [x0, #176]",
2587 "ldr x19, [x0, #192]",
2588 "b __sigsetjmp_tail",
2589 );
2590}
2591
2592#[no_mangle]
2593#[unsafe(naked)]
2594#[cfg(target_arch = "aarch64")]
2595pub unsafe extern "C" fn __sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2596 core::arch::naked_asm!(
2597 "cbz w1, setjmp",
2598 "str x30, [x0, #176]",
2599 "str x19, [x0, #192]",
2600 "mov x19, x0",
2601 "bl setjmp",
2602 "mov w1, w0",
2603 "mov x0, x19",
2604 "ldr x30, [x0, #176]",
2605 "ldr x19, [x0, #192]",
2606 "b __sigsetjmp_tail",
2607 );
2608}
2609
2610#[no_mangle]
2611#[inline(never)]
2612#[cfg(target_arch = "aarch64")]
2613pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2614 longjmp(env, val);
2615}
2616
2617#[no_mangle]
2618#[cfg(target_arch = "riscv64")]
2619pub unsafe extern "C" fn __sigsetjmp_tail(env: *mut c_ulong, ret: c_int) -> c_int {
2620 const SIG_SETMASK: c_int = 2;
2621 let ss = env.add(27) as *mut SigSetT;
2622 let set = if ret != 0 { ss as *const SigSetT } else { core::ptr::null() };
2623 let old = if ret != 0 { core::ptr::null_mut() } else { ss };
2624 let _ = sys_rt_sigprocmask(SIG_SETMASK, set, old, core::mem::size_of::<SigSetT>());
2625 ret
2626}
2627
2628#[no_mangle]
2629#[unsafe(naked)]
2630#[cfg(target_arch = "riscv64")]
2631pub unsafe extern "C" fn sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2632 core::arch::naked_asm!(
2633 "bnez a1, 1f",
2634 "tail setjmp",
2635 "1:",
2636 "sd ra, 208(a0)",
2637 "sd s0, 224(a0)",
2638 "mv s0, a0",
2639 "call setjmp",
2640 "mv a1, a0",
2641 "mv a0, s0",
2642 "ld s0, 224(a0)",
2643 "ld ra, 208(a0)",
2644 "tail __sigsetjmp_tail",
2645 );
2646}
2647
2648#[no_mangle]
2649#[unsafe(naked)]
2650#[cfg(target_arch = "riscv64")]
2651pub unsafe extern "C" fn __sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2652 core::arch::naked_asm!(
2653 "bnez a1, 1f",
2654 "tail setjmp",
2655 "1:",
2656 "sd ra, 208(a0)",
2657 "sd s0, 224(a0)",
2658 "mv s0, a0",
2659 "call setjmp",
2660 "mv a1, a0",
2661 "mv a0, s0",
2662 "ld s0, 224(a0)",
2663 "ld ra, 208(a0)",
2664 "tail __sigsetjmp_tail",
2665 );
2666}
2667
2668#[no_mangle]
2669#[inline(never)]
2670#[cfg(target_arch = "riscv64")]
2671pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2672 longjmp(env, val);
2673}
2674
2675#[inline]
2680unsafe fn sys_newfstatat(dirfd: i32, path: *const c_char, buf: *mut u8, flags: i32) -> i64 {
2681 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, dirfd as i64, path as i64, buf as i64, flags as i64)
2682}
2683
2684#[inline]
2685unsafe fn sys_fstat(fd: i32, buf: *mut u8) -> i64 {
2686 <Arch as Syscalls>::syscall2(SYS_FSTAT, fd as i64, buf as i64)
2687}
2688
2689#[inline]
2690unsafe fn sys_getrlimit(resource: i32, rlim: *mut u8) -> i64 {
2691 <Arch as Syscalls>::syscall2(SYS_GETRLIMIT, resource as i64, rlim as i64)
2692}
2693
2694#[inline]
2695unsafe fn sys_setrlimit(resource: i32, rlim: *const u8) -> i64 {
2696 <Arch as Syscalls>::syscall2(SYS_SETRLIMIT, resource as i64, rlim as i64)
2697}
2698
2699#[inline]
2700unsafe fn sys_utimensat(dirfd: i32, path: *const c_char, times: *const u8, flags: i32) -> i64 {
2701 <Arch as Syscalls>::syscall4(SYS_UTIMENSAT, dirfd as i64, path as i64, times as i64, flags as i64)
2702}
2703
2704#[inline]
2709unsafe fn sys_fork() -> i64 {
2710 #[cfg(target_arch = "x86_64")]
2711 { <Arch as Syscalls>::syscall0(SYS_FORK) }
2712 #[cfg(target_arch = "aarch64")]
2713 { <Arch as Syscalls>::syscall2(SYS_CLONE, 17, 0) }
2714 #[cfg(target_arch = "riscv64")]
2715 { <Arch as Syscalls>::syscall2(SYS_CLONE, 17, 0) }
2716}
2717
2718
2719#[inline]
2720unsafe fn sys_execve(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> i64 {
2721 <Arch as Syscalls>::syscall3(SYS_EXECVE, path as i64, argv as i64, envp as i64)
2722}
2723
2724#[inline]
2725unsafe fn sys_wait4(pid: c_int, status: *mut c_int, options: c_int, rusage: *mut c_void) -> i64 {
2726 <Arch as Syscalls>::syscall4(SYS_WAIT4, pid as i64, status as i64, options as i64, rusage as i64)
2727}
2728
2729#[inline]
2730unsafe fn sys_getppid() -> i64 {
2731 <Arch as Syscalls>::syscall0(SYS_GETPPID)
2732}
2733
2734#[inline]
2735unsafe fn sys_getuid() -> i64 {
2736 <Arch as Syscalls>::syscall0(SYS_GETUID)
2737}
2738
2739#[inline]
2740unsafe fn sys_getgid() -> i64 {
2741 <Arch as Syscalls>::syscall0(SYS_GETGID)
2742}
2743
2744#[inline]
2745unsafe fn sys_geteuid() -> i64 {
2746 <Arch as Syscalls>::syscall0(SYS_GETEUID)
2747}
2748
2749#[inline]
2750unsafe fn sys_getegid() -> i64 {
2751 <Arch as Syscalls>::syscall0(SYS_GETEGID)
2752}
2753
2754#[no_mangle]
2755pub unsafe extern "C" fn fork() -> c_int {
2756 __fork_handler(-1);
2757 let ret = sys_fork();
2758 if ret < 0 {
2763 let err = (-ret) as c_int;
2764 __fork_handler(0);
2765 ERRNO!() = err;
2766 return -1;
2767 }
2768 if ret == 0 {
2769 allocator_after_fork();
2770 __fork_handler(1);
2771 } else {
2772 __fork_handler(0);
2773 }
2774 ret as c_int
2775}
2776
2777#[no_mangle]
2778pub unsafe extern "C" fn execve(
2779 path: *const c_char,
2780 argv: *const *const c_char,
2781 envp: *const *const c_char,
2782) -> c_int {
2783 let r = sys_execve(path, argv, envp);
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 wait(status: *mut c_int) -> c_int {
2790 let r = sys_wait4(-1, status, 0, 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 waitpid(pid: c_int, status: *mut c_int, options: c_int) -> c_int {
2797 let r = sys_wait4(pid, status, options, core::ptr::null_mut());
2798 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2799 r as c_int
2800}
2801
2802#[no_mangle]
2803pub unsafe extern "C" fn getppid() -> c_int {
2804 sys_getppid() as c_int
2805}
2806
2807#[no_mangle]
2808pub unsafe extern "C" fn getuid() -> c_uint {
2809 sys_getuid() as c_uint
2810}
2811
2812#[no_mangle]
2813pub unsafe extern "C" fn getgid() -> c_uint {
2814 sys_getgid() as c_uint
2815}
2816
2817#[no_mangle]
2818pub unsafe extern "C" fn geteuid() -> c_uint {
2819 sys_geteuid() as c_uint
2820}
2821
2822#[no_mangle]
2823pub unsafe extern "C" fn getegid() -> c_uint {
2824 sys_getegid() as c_uint
2825}
2826
2827#[no_mangle]
2829pub unsafe extern "C" fn vfork() -> c_int {
2830 let r = sys_fork();
2835 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2836 r as c_int
2837}
2838
2839#[no_mangle]
2840pub unsafe extern "C" fn execl(path: *const c_char, arg: *const c_char, mut args: ...) -> c_int {
2841 let mut argv: [*const c_char; 256] = [core::ptr::null(); 256];
2842 argv[0] = arg;
2843 let mut n: usize = 1;
2844 loop {
2845 let a: *const c_char = args.next_arg();
2846 if a.is_null() { break; }
2847 if n >= 255 { return -1; }
2848 argv[n] = a;
2849 n += 1;
2850 }
2851 argv[n] = core::ptr::null();
2852 sys_execve(path, argv.as_ptr(), __environ as *const *const c_char) as c_int
2853}
2854
2855unsafe fn spawn_execvp(file: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> ! {
2864 let flen = strlen(file as *const c_char);
2865 let f = file as *const u8;
2866 let mut has_slash = false;
2867 for i in 0..flen {
2868 if *f.add(i) == b'/' { has_slash = true; break; }
2869 }
2870 if has_slash {
2871 sys_execve(file, argv, envp);
2872 _exit(127);
2873 }
2874 let path = getenv(b"PATH\0".as_ptr() as *const c_char);
2875 let default_path = b"/usr/local/bin:/usr/bin:/bin\0";
2876 let p = if path.is_null() { default_path.as_ptr() } else { path as *const u8 };
2877 let plen = strlen(p as *const c_char);
2878 let mut buf: [u8; 4096] = [0; 4096];
2879 let mut i: usize = 0;
2880 while i <= plen {
2881 let start = i;
2882 while i < plen && *p.add(i) != b':' { i += 1; }
2883 let dlen = i - start;
2884 if dlen > 0 && dlen + 1 + flen < 4096 {
2885 core::ptr::copy_nonoverlapping(p.add(start), buf.as_mut_ptr(), dlen);
2886 *buf.as_mut_ptr().add(dlen) = b'/';
2887 core::ptr::copy_nonoverlapping(f, buf.as_mut_ptr().add(dlen + 1), flen + 1);
2888 sys_execve(buf.as_ptr() as *const c_char, argv, envp);
2889 }
2891 i += 1; }
2893 _exit(127);
2894}
2895
2896#[no_mangle]
2897pub unsafe extern "C" fn posix_spawnp(
2898 pid: *mut c_int,
2899 file: *const c_char,
2900 fa: *const posix_spawn_file_actions_t,
2901 attrp: *const posix_spawnattr_t,
2902 argv: *const *const c_char,
2903 envp: *const *const c_char,
2904) -> c_int {
2905 let child = sys_fork();
2906 if child < 0 {
2907 ERRNO!() = EAGAIN;
2908 return -1;
2909 }
2910 if child == 0 {
2911 spawn_apply_attr(attrp);
2913 spawn_apply_actions(fa);
2914 let actual_envp = if envp.is_null() { __environ as *const *const c_char } else { envp };
2915 spawn_execvp(file, argv, actual_envp);
2916 }
2918 *pid = child as c_int;
2919 0
2920}
2921
2922#[no_mangle]
2923pub unsafe extern "C" fn posix_spawn(
2924 pid: *mut c_int,
2925 path: *const c_char,
2926 fa: *const posix_spawn_file_actions_t,
2927 attrp: *const posix_spawnattr_t,
2928 argv: *const *const c_char,
2929 envp: *const *const c_char,
2930) -> c_int {
2931 posix_spawnp(pid, path, fa, attrp, argv, envp)
2934}
2935
2936#[cfg(target_arch = "x86_64")]
2941#[repr(C)]
2942pub struct Stat {
2943 pub st_dev: u64,
2944 pub st_ino: u64,
2945 pub st_nlink: u64,
2946 pub st_mode: u32,
2947 pub st_uid: u32,
2948 pub st_gid: u32,
2949 _pad0: u32,
2950 pub st_rdev: u64,
2951 pub st_size: i64,
2952 pub st_blksize: i64,
2953 pub st_blocks: i64,
2954 pub st_atim: timespec,
2955 pub st_mtim: timespec,
2956 pub st_ctim: timespec,
2957 _unused: [i64; 3],
2958}
2959
2960#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
2961#[repr(C)]
2962pub struct Stat {
2963 pub st_dev: u64,
2964 pub st_ino: u64,
2965 pub st_mode: u32,
2966 pub st_nlink: u32,
2967 pub st_uid: u32,
2968 pub st_gid: u32,
2969 pub st_rdev: u64,
2970 __pad1: u64,
2971 pub st_size: i64,
2972 pub st_blksize: i32,
2973 __pad2: i32,
2974 pub st_blocks: i64,
2975 pub st_atim: timespec,
2976 pub st_mtim: timespec,
2977 pub st_ctim: timespec,
2978 __unused4: u32,
2979 __unused5: u32,
2980}
2981
2982pub const S_IFMT: u32 = 0o170000;
2983pub const S_IFDIR: u32 = 0o040000;
2984pub const S_IFCHR: u32 = 0o020000;
2985pub const S_IFBLK: u32 = 0o060000;
2986pub const S_IFREG: u32 = 0o100000;
2987pub const S_IFLNK: u32 = 0o120000;
2988pub const S_IFIFO: u32 = 0o010000;
2989pub const S_IFSOCK: u32 = 0o140000;
2990
2991pub const AT_FDCWD: i32 = -100;
2992
2993#[no_mangle]
2994pub unsafe extern "C" fn stat(path: *const c_char, buf: *mut Stat) -> c_int {
2995 let r = sys_newfstatat(AT_FDCWD, path, buf as *mut u8, 0);
2996 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2997 if *path == b'/' as c_char && strcmp(path as *const u8, b"/dev/null\0".as_ptr()) == 0 {
2998 (*buf).st_mode = ((*buf).st_mode & !0o170000) | 0o020000;
2999 }
3000 0
3001}
3002
3003#[no_mangle]
3004pub unsafe extern "C" fn fstat(fd: c_int, buf: *mut Stat) -> c_int {
3005 let r = sys_fstat(fd, buf as *mut u8);
3006 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
3007}
3008
3009#[repr(C)]
3014pub struct Rlimit {
3015 pub rlim_cur: u64,
3016 pub rlim_max: u64,
3017}
3018
3019pub const RLIMIT_NOFILE: c_int = 7;
3020pub const RLIMIT_STACK: c_int = 3;
3021pub const RLIMIT_DATA: c_int = 2;
3022pub const RLIMIT_AS: c_int = 9;
3023pub const RLIMIT_CPU: c_int = 0;
3024pub const RLIMIT_FSIZE: c_int = 1;
3025pub const RLIMIT_CORE: c_int = 4;
3026pub const RLIMIT_RSS: c_int = 5;
3027pub const RLIMIT_NPROC: c_int = 6;
3028pub const RLIMIT_MEMLOCK: c_int = 8;
3029pub const RLIMIT_LOCKS: c_int = 10;
3030pub const RLIMIT_SIGPENDING: c_int = 11;
3031pub const RLIMIT_MSGQUEUE: c_int = 12;
3032pub const RLIMIT_NICE: c_int = 13;
3033pub const RLIMIT_RTPRIO: c_int = 14;
3034pub const RLIMIT_RTTIME: c_int = 15;
3035pub const RLIM_INFINITY: u64 = !0u64;
3036
3037#[no_mangle]
3038pub unsafe extern "C" fn getrlimit(resource: c_int, rlim: *mut Rlimit) -> c_int {
3039 let r = sys_getrlimit(resource, rlim as *mut u8);
3040 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
3041}
3042
3043#[no_mangle]
3044pub unsafe extern "C" fn setrlimit(resource: c_int, rlim: *const Rlimit) -> c_int {
3045 let r = sys_setrlimit(resource, rlim as *const u8);
3046 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
3047}
3048
3049#[no_mangle]
3054pub unsafe extern "C" fn utimensat(dirfd: c_int, path: *const c_char, times: *const timespec, flags: c_int) -> c_int {
3055 let r = sys_utimensat(dirfd, path, times as *const u8, flags);
3056 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
3057}
3058
3059#[no_mangle]
3060pub unsafe extern "C" fn futimens(fd: c_int, times: *const timespec) -> c_int {
3061 let r = sys_utimensat(fd, core::ptr::null(), times as *const u8, 0);
3062 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
3063}
3064
3065pub const AF_UNIX: c_int = 1;
3070pub const AF_INET: c_int = 2;
3071pub const AF_INET6: c_int = 10;
3072
3073pub const SOCK_STREAM: c_int = 1;
3074pub const SOCK_DGRAM: c_int = 2;
3075
3076pub const SHUT_RD: c_int = 0;
3077pub const SHUT_WR: c_int = 1;
3078pub const SHUT_RDWR: c_int = 2;
3079
3080pub const SOL_SOCKET: c_int = 1;
3081pub const SO_REUSEADDR: c_int = 2;
3082
3083#[repr(C)]
3084pub struct sockaddr {
3085 pub sa_family: u16,
3086 pub sa_data: [u8; 14],
3087}
3088
3089#[inline]
3090unsafe fn sys_socket(domain: c_int, ty: c_int, protocol: c_int) -> i64 {
3091 <Arch as Syscalls>::syscall3(SYS_SOCKET, domain as i64, ty as i64, protocol as i64)
3092}
3093
3094#[inline]
3095unsafe fn sys_socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> i64 {
3096 <Arch as Syscalls>::syscall4(SYS_SOCKETPAIR, domain as i64, ty as i64, protocol as i64, sv as i64)
3097}
3098
3099#[inline]
3100unsafe fn sys_bind(fd: c_int, addr: *const sockaddr, len: c_uint) -> i64 {
3101 <Arch as Syscalls>::syscall3(SYS_BIND, fd as i64, addr as i64, len as i64)
3102}
3103
3104#[inline]
3105unsafe fn sys_listen(fd: c_int, backlog: c_int) -> i64 {
3106 <Arch as Syscalls>::syscall2(SYS_LISTEN, fd as i64, backlog as i64)
3107}
3108
3109#[inline]
3110unsafe fn sys_accept(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> i64 {
3111 <Arch as Syscalls>::syscall3(SYS_ACCEPT, fd as i64, addr as i64, len as i64)
3112}
3113
3114#[inline]
3115unsafe fn sys_connect(fd: c_int, addr: *const sockaddr, len: c_uint) -> i64 {
3116 <Arch as Syscalls>::syscall3(SYS_CONNECT, fd as i64, addr as i64, len as i64)
3117}
3118
3119#[inline]
3120unsafe fn sys_sendto(fd: c_int,
3121 buf: *const c_void,
3122 len: usize,
3123 flags: c_int,
3124 addr: *const sockaddr,
3125 addrlen: c_uint,) -> i64 {
3126 <Arch as Syscalls>::syscall6(SYS_SENDTO, fd as i64, buf as i64, len as i64, flags as i64, addr as i64, addrlen as i64)
3127}
3128
3129#[inline]
3130unsafe fn sys_recvfrom(fd: c_int,
3131 buf: *mut c_void,
3132 len: usize,
3133 flags: c_int,
3134 addr: *mut sockaddr,
3135 addrlen: *mut c_uint,) -> i64 {
3136 <Arch as Syscalls>::syscall6(SYS_RECVFROM, fd as i64, buf as i64, len as i64, flags as i64, addr as i64, addrlen as i64)
3137}
3138
3139#[inline]
3140unsafe fn sys_shutdown(fd: c_int, how: c_int) -> i64 {
3141 <Arch as Syscalls>::syscall2(SYS_SHUTDOWN, fd as i64, how as i64)
3142}
3143
3144#[inline]
3145unsafe fn sys_setsockopt(fd: c_int,
3146 level: c_int,
3147 optname: c_int,
3148 optval: *const c_void,
3149 optlen: c_uint,) -> i64 {
3150 <Arch as Syscalls>::syscall5(SYS_SETSOCKOPT, fd as i64, level as i64, optname as i64, optval as i64, optlen as i64)
3151}
3152
3153#[inline]
3154unsafe fn sys_getsockname(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> i64 {
3155 <Arch as Syscalls>::syscall3(SYS_GETSOCKNAME, fd as i64, addr as i64, len as i64)
3156}
3157
3158#[no_mangle]
3159pub unsafe extern "C" fn socket(domain: c_int, ty: c_int, protocol: c_int) -> c_int {
3160 let r = sys_socket(domain, ty, protocol);
3161 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3162 r as c_int
3163}
3164
3165#[no_mangle]
3166pub unsafe extern "C" fn socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> c_int {
3167 let r = sys_socketpair(domain, ty, protocol, sv);
3168 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3169 0
3170}
3171
3172#[no_mangle]
3173pub unsafe extern "C" fn bind(fd: c_int, addr: *const sockaddr, len: c_uint) -> c_int {
3174 let r = sys_bind(fd, addr, len);
3175 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3176 0
3177}
3178
3179#[no_mangle]
3180pub unsafe extern "C" fn listen(fd: c_int, backlog: c_int) -> c_int {
3181 let r = sys_listen(fd, backlog);
3182 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3183 0
3184}
3185
3186#[no_mangle]
3187pub unsafe extern "C" fn accept(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> c_int {
3188 let r = sys_accept(fd, addr, len);
3189 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3190 r as c_int
3191}
3192
3193#[no_mangle]
3194pub unsafe extern "C" fn connect(fd: c_int, addr: *const sockaddr, len: c_uint) -> c_int {
3195 let r = sys_connect(fd, addr, len);
3196 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3197 0
3198}
3199
3200#[no_mangle]
3201pub unsafe extern "C" fn send(fd: c_int, buf: *const c_void, len: usize, flags: c_int) -> isize {
3202 let r = sys_sendto(fd, buf, len, flags, core::ptr::null(), 0);
3203 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3204 r as isize
3205}
3206
3207#[no_mangle]
3208pub unsafe extern "C" fn recv(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize {
3209 let r = sys_recvfrom(fd, buf, len, flags, core::ptr::null_mut(), core::ptr::null_mut());
3210 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3211 r as isize
3212}
3213
3214#[no_mangle]
3215pub unsafe extern "C" fn sendto(
3216 fd: c_int,
3217 buf: *const c_void,
3218 len: usize,
3219 flags: c_int,
3220 addr: *const sockaddr,
3221 addrlen: c_uint,
3222) -> isize {
3223 let r = sys_sendto(fd, buf, len, flags, addr, addrlen);
3224 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3225 r as isize
3226}
3227
3228#[no_mangle]
3229pub unsafe extern "C" fn recvfrom(
3230 fd: c_int,
3231 buf: *mut c_void,
3232 len: usize,
3233 flags: c_int,
3234 addr: *mut sockaddr,
3235 addrlen: *mut c_uint,
3236) -> isize {
3237 let r = sys_recvfrom(fd, buf, len, flags, addr, addrlen);
3238 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3239 r as isize
3240}
3241
3242#[no_mangle]
3243pub unsafe extern "C" fn shutdown(fd: c_int, how: c_int) -> c_int {
3244 let r = sys_shutdown(fd, how);
3245 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3246 0
3247}
3248
3249#[no_mangle]
3250pub unsafe extern "C" fn setsockopt(
3251 fd: c_int,
3252 level: c_int,
3253 optname: c_int,
3254 optval: *const c_void,
3255 optlen: c_uint,
3256) -> c_int {
3257 let r = sys_setsockopt(fd, level, optname, optval, optlen);
3258 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3259 0
3260}
3261
3262#[no_mangle]
3263pub unsafe extern "C" fn getsockname(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> c_int {
3264 let r = sys_getsockname(fd, addr, len);
3265 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3266 0
3267}
3268
3269#[no_mangle]
3270pub extern "C" fn htonl(hostlong: c_uint) -> c_uint {
3271 hostlong.to_be()
3272}
3273
3274#[no_mangle]
3275pub extern "C" fn ntohl(netlong: c_uint) -> c_uint {
3276 c_uint::from_be(netlong)
3277}
3278
3279#[no_mangle]
3280pub extern "C" fn htons(hostshort: u16) -> u16 {
3281 hostshort.to_be()
3282}
3283
3284#[no_mangle]
3285pub extern "C" fn ntohs(netshort: u16) -> u16 {
3286 u16::from_be(netshort)
3287}
3288
3289pub type PthreadT = c_ulong;
3290
3291#[repr(C)]
3293pub struct pthread_attr_t {
3294 __i: [c_int; 14],
3295}
3296
3297#[repr(C)]
3300pub struct pthread_mutex_t {
3301 __i: [c_int; 10],
3302}
3303
3304#[repr(C)]
3305pub struct pthread_mutexattr_t {
3306 __attr: c_uint,
3307}
3308
3309#[repr(C)]
3312pub struct pthread_cond_t {
3313 __i: [c_int; 12],
3314}
3315
3316#[repr(C)]
3317pub struct pthread_condattr_t {
3318 __attr: c_uint,
3319}
3320
3321#[repr(C)]
3324pub struct pthread_rwlock_t {
3325 __i: [c_int; 14],
3326}
3327
3328#[repr(C)]
3329pub struct pthread_rwlockattr_t {
3330 __attr: [c_uint; 2],
3331}
3332
3333#[repr(C)]
3335pub struct pthread_barrier_t {
3336 __i: [c_int; 8],
3337}
3338
3339#[repr(C)]
3340pub struct pthread_barrierattr_t {
3341 __attr: c_uint,
3342}
3343
3344pub type pthread_spinlock_t = c_int;
3345pub type pthread_once_t = c_int;
3346pub type pthread_key_t = c_uint;
3347
3348#[repr(C)]
3350pub struct sem_t {
3351 __val: [c_int; 8],
3352}
3353
3354#[repr(C)]
3355pub struct sched_param {
3356 pub sched_priority: c_int,
3357}
3358
3359const CLONE_VM: c_ulong = 0x00000100;
3360const CLONE_FS: c_ulong = 0x00000200;
3361const CLONE_FILES: c_ulong = 0x00000400;
3362const CLONE_SIGHAND: c_ulong = 0x00000800;
3363const CLONE_THREAD: c_ulong = 0x00010000;
3364const CLONE_SYSVSEM: c_ulong = 0x00040000;
3365const CLONE_SETTLS: c_ulong = 0x00080000;
3366const CLONE_PARENT_SETTID: c_ulong = 0x00100000;
3367const CLONE_CHILD_CLEARTID: c_ulong = 0x00200000;
3368
3369const FUTEX_WAIT: c_int = 0;
3370const FUTEX_WAKE: c_int = 1;
3371const FUTEX_LOCK_PI: c_int = 6;
3372const FUTEX_UNLOCK_PI: c_int = 7;
3373const FUTEX_TRYLOCK_PI: c_int = 8;
3374
3375const SIGCANCEL: c_int = 32;
3377
3378const PTHREAD_MUTEX_NORMAL: c_int = 0;
3379const PTHREAD_MUTEX_DEFAULT: c_int = 0;
3380const PTHREAD_MUTEX_RECURSIVE: c_int = 1;
3381const PTHREAD_MUTEX_ERRORCHECK: c_int = 2;
3382
3383const PTHREAD_CREATE_JOINABLE: c_int = 0;
3384const PTHREAD_CREATE_DETACHED: c_int = 1;
3385
3386const PTHREAD_CANCEL_ENABLE: c_int = 0;
3387const PTHREAD_CANCEL_DISABLE: c_int = 1;
3388const PTHREAD_CANCEL_DEFERRED: c_int = 0;
3389const PTHREAD_CANCEL_ASYNCHRONOUS: c_int = 1;
3390
3391const PTHREAD_SCOPE_SYSTEM: c_int = 0;
3392const PTHREAD_PROCESS_PRIVATE: c_int = 0;
3393const PTHREAD_PROCESS_SHARED: c_int = 1;
3394const PTHREAD_INHERIT_SCHED: c_int = 0;
3395const PTHREAD_EXPLICIT_SCHED: c_int = 1;
3396
3397const PTHREAD_BARRIER_SERIAL_THREAD: c_int = -1;
3398
3399const PTHREAD_KEYS_MAX: usize = 128;
3400const PTHREAD_DESTRUCTOR_ITERATIONS: usize = 4;
3401const SEM_VALUE_MAX: c_int = 0x7fffffff;
3402
3403const DT_EXITED: c_int = 0;
3404const DT_EXITING: c_int = 1;
3405const DT_JOINABLE: c_int = 2;
3406const DT_DETACHED: c_int = 3;
3407
3408#[repr(C)]
3410#[derive(Copy, Clone)]
3411pub struct __ptcb {
3412 __f: Option<unsafe extern "C" fn(*mut c_void)>,
3413 __x: *mut c_void,
3414 __next: *mut __ptcb,
3415}
3416
3417#[repr(C)]
3419#[derive(Copy, Clone)]
3420struct robust_list {
3421 next: *mut robust_list,
3422}
3423
3424#[repr(C)]
3425#[derive(Copy, Clone)]
3426struct robust_list_head {
3427 list: robust_list,
3428 futex_offset: c_long,
3429 pending: *mut robust_list,
3430}
3431
3432#[cfg(all(target_arch = "x86_64", not(test)))]
3434core::arch::global_asm!(
3435 ".global __rc_clone",
3436 ".type __rc_clone, @function",
3437 "__rc_clone:",
3438 "mov rax, rdi",
3439 "mov rdi, rdx",
3440 "mov rdx, r8",
3441 "mov r10, [rsp + 8]",
3442 "mov r8, r9",
3443 "mov r9, rax",
3444 "and rsi, -16",
3445 "sub rsi, 8",
3446 "mov [rsi], rcx",
3447 "mov eax, 56",
3448 "syscall",
3449 "test rax, rax",
3450 "jnz 1f",
3451 "pop rdi",
3452 "call r9",
3453 "mov edi, eax",
3456 "mov eax, 60",
3457 "syscall",
3458 "hlt",
3459 "1:",
3460 "ret",
3461);
3462
3463#[no_mangle]
3465#[unsafe(naked)]
3466#[cfg(target_arch = "aarch64")]
3467pub unsafe extern "C" fn __rc_clone(
3468 fn_: usize,
3469 stack: *mut u8,
3470 flags: c_ulong,
3471 arg: *mut c_void,
3472 ptid: *mut c_int,
3473 tls: c_ulong,
3474 ctid: *mut c_int,
3475) -> i64 {
3476 core::arch::naked_asm!(
3477 "and x1, x1, #-16",
3478 "stp x0, x3, [x1, #-16]!",
3479 "uxtw x0, w2",
3480 "mov x2, x4",
3481 "mov x3, x5",
3482 "mov x4, x6",
3483 "mov x8, #220",
3484 "svc #0",
3485 "cbz x0, 1f",
3486 "ret",
3487 "1:",
3488 "mov x29, #0",
3489 "ldp x1, x0, [sp], #16",
3490 "blr x1",
3491 "mov x8, #93",
3492 "svc #0",
3493 );
3494}
3495
3496#[no_mangle]
3497#[unsafe(naked)]
3498#[cfg(target_arch = "riscv64")]
3499pub unsafe extern "C" fn __rc_clone(
3500 fn_: usize,
3501 stack: *mut u8,
3502 flags: c_ulong,
3503 arg: *mut c_void,
3504 ptid: *mut c_int,
3505 tls: c_ulong,
3506 ctid: *mut c_int,
3507) -> i64 {
3508 core::arch::naked_asm!(
3509 "andi a1, a1, -16",
3510 "addi a1, a1, -16",
3511 "sd a0, 0(a1)",
3512 "sd a3, 8(a1)",
3513 "mv a0, a2",
3514 "mv a2, a4",
3515 "mv a3, a5",
3516 "mv a4, a6",
3517 "li a7, 220",
3518 "ecall",
3519 "beqz a0, 1f",
3520 "ret",
3521 "1:",
3522 "ld a1, 0(sp)",
3523 "ld a0, 8(sp)",
3524 "jalr a1",
3525 "li a7, 93",
3526 "ecall",
3527 );
3528}
3529
3530#[cfg(all(target_arch = "x86_64", test))]
3531#[inline(never)]
3532unsafe fn __rc_clone(
3533 _fn_: usize,
3534 _stack: *mut u8,
3535 _flags: c_ulong,
3536 _arg: *mut c_void,
3537 _ptid: *mut c_int,
3538 _tls: c_ulong,
3539 _ctid: *mut c_int,
3540) -> i64 {
3541 -1
3542}
3543
3544#[cfg(all(target_arch = "x86_64", not(test)))]
3545extern "C" {
3546 fn __rc_clone(
3547 fn_: usize,
3548 stack: *mut u8,
3549 flags: c_ulong,
3550 arg: *mut c_void,
3551 ptid: *mut c_int,
3552 tls: c_ulong,
3553 ctid: *mut c_int,
3554 ) -> i64;
3555}
3556
3557#[inline(never)]
3558#[linkage = "weak"]
3559#[no_mangle]
3560pub extern "C" fn __rc_create_thread_tls() -> *mut u8 {
3561 core::ptr::null_mut()
3562}
3563
3564#[inline(never)]
3565#[linkage = "weak"]
3566#[no_mangle]
3567pub unsafe extern "C" fn __rc_init_thread_tls_at(_block: *mut u8) -> *mut u8 {
3568 core::ptr::null_mut()
3569}
3570
3571#[inline(never)]
3572#[linkage = "weak"]
3573#[no_mangle]
3574pub extern "C" fn __rc_tls_block_size() -> usize {
3575 0
3576}
3577
3578#[inline(never)]
3579#[linkage = "weak"]
3580#[no_mangle]
3581pub extern "C" fn __rc_tls_base_offset() -> usize {
3582 0
3583}
3584
3585#[inline]
3586unsafe fn sys_gettid() -> i64 {
3587 <Arch as Syscalls>::syscall0(SYS_GETTID)
3588}
3589
3590#[inline]
3591unsafe fn sys_futex(uaddr: *mut c_int,
3592 futex_op: c_int,
3593 val: c_int,
3594 timeout: *mut c_void,
3595 uaddr2: *mut c_int,
3596 val3: c_int,) -> i64 {
3597 <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)
3598}
3599
3600const MAX_THREADS: usize = 1024;
3601const STACK_SIZE: usize = 1024 * 1024;
3602
3603#[repr(C)]
3604#[derive(Copy, Clone)]
3605struct Thread {
3606 tid: c_int,
3607 detach_state: c_int,
3608 result: *mut c_void,
3609 cancel: c_int,
3610 cancel_state: c_int,
3611 cancel_type: c_int,
3612 user_fn: usize,
3613 user_arg: *mut c_void,
3614 stack: *mut u8,
3615 stack_size: usize,
3616 stack_owned: bool,
3617 fs_base: *mut u8,
3618 tls_base: *mut u8,
3623 tls_size: usize,
3624 tsd: [*mut c_void; PTHREAD_KEYS_MAX],
3625 cancelbuf: *mut __ptcb,
3626 robust_list: robust_list_head,
3627}
3628
3629static mut THREADS: [Thread; MAX_THREADS] = [Thread {
3630 tid: -1,
3631 detach_state: DT_JOINABLE,
3632 result: core::ptr::null_mut(),
3633 cancel: 0,
3634 cancel_state: PTHREAD_CANCEL_ENABLE,
3635 cancel_type: PTHREAD_CANCEL_DEFERRED,
3636 user_fn: 0,
3637 user_arg: core::ptr::null_mut(),
3638 stack: core::ptr::null_mut(),
3639 stack_size: 0,
3640 stack_owned: false,
3641 fs_base: core::ptr::null_mut(),
3642 tls_base: core::ptr::null_mut(),
3643 tls_size: 0,
3644 tsd: [core::ptr::null_mut(); PTHREAD_KEYS_MAX],
3645 cancelbuf: core::ptr::null_mut(),
3646 robust_list: robust_list_head {
3647 list: robust_list { next: core::ptr::null_mut() },
3648 futex_offset: 0,
3649 pending: core::ptr::null_mut(),
3650 },
3651}; MAX_THREADS];
3652const SLOT_WORDS: usize = (MAX_THREADS + usize::BITS as usize - 1) / usize::BITS as usize;
3653static SLOT_USED: [AtomicUsize; SLOT_WORDS] = [const { AtomicUsize::new(0) }; SLOT_WORDS];
3654static mut KEY_DTORS: [Option<unsafe extern "C" fn(*mut c_void)>; PTHREAD_KEYS_MAX] = [None; PTHREAD_KEYS_MAX];
3655static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
3656
3657unsafe fn futex_wait(addr: *mut c_int, expected: c_int) -> c_int {
3659 let r = sys_futex(addr, FUTEX_WAIT, expected, null_mut(), null_mut(), 0);
3660 if r < 0 { let e = (-r) as c_int; if e == EAGAIN { 0 } else { e } } else { 0 }
3661}
3662
3663unsafe fn futex_wake(addr: *mut c_int, count: c_int) {
3664 let c = if count < 0 { c_int::MAX } else { count };
3665 sys_futex(addr, FUTEX_WAKE, c, null_mut(), null_mut(), 0);
3666}
3667
3668unsafe fn futex_lock_pi(addr: *mut c_int, abs_timeout: *const timespec) -> c_int {
3669 let timeout_ptr = if abs_timeout.is_null() { null_mut() } else { abs_timeout as *mut c_void };
3670 let r = sys_futex(addr, FUTEX_LOCK_PI, 0, timeout_ptr, null_mut(), 0);
3671 if r < 0 { (-r) as c_int } else { 0 }
3672}
3673
3674unsafe fn futex_unlock_pi(addr: *mut c_int) -> c_int {
3675 let r = sys_futex(addr, FUTEX_UNLOCK_PI, 0, null_mut(), null_mut(), 0);
3676 if r < 0 { (-r) as c_int } else { 0 }
3677}
3678
3679#[inline]
3680unsafe fn sys_set_robust_list(head: *mut robust_list_head, len: usize) -> i64 {
3681 <Arch as Syscalls>::syscall2(SYS_SET_ROBUST_LIST, head as i64, len as i64)
3682}
3683
3684unsafe fn futex_timedwait(addr: *mut c_int, expected: c_int, abs_timeout: *const timespec) -> c_int {
3685 if abs_timeout.is_null() { return futex_wait(addr, expected); }
3686 let mut now: timespec = core::mem::zeroed();
3687 if sys_clock_gettime(CLOCK_REALTIME, &mut now) < 0 { return EINVAL; }
3688 let mut rel: timespec = core::mem::zeroed();
3689 rel.tv_sec = (*abs_timeout).tv_sec - now.tv_sec;
3690 rel.tv_nsec = (*abs_timeout).tv_nsec - now.tv_nsec;
3691 if rel.tv_nsec < 0 { rel.tv_sec -= 1; rel.tv_nsec += 1_000_000_000; }
3692 if rel.tv_sec < 0 { return ETIMEDOUT; }
3693 let r = sys_futex(addr, FUTEX_WAIT, expected, &mut rel as *mut timespec as *mut c_void, null_mut(), 0);
3694 if r < 0 { let e = (-r) as c_int; if e == EAGAIN { 0 } else { e } } else { 0 }
3695}
3696
3697unsafe fn a_cas(addr: *mut c_int, expected: c_int, desired: c_int) -> c_int {
3699 let a = &*(addr as *const AtomicI32);
3700 match a.compare_exchange(expected, desired, Ordering::AcqRel, Ordering::Acquire) {
3701 Ok(v) | Err(v) => v,
3702 }
3703}
3704
3705unsafe fn a_store(addr: *mut c_int, val: c_int) {
3706 (*(addr as *const AtomicI32)).store(val, Ordering::Release);
3707}
3708
3709unsafe fn a_load(addr: *const c_int) -> c_int {
3710 (*(addr as *const AtomicI32)).load(Ordering::Acquire)
3711}
3712
3713unsafe fn a_swap(addr: *mut c_int, val: c_int) -> c_int {
3714 (*(addr as *const AtomicI32)).swap(val, Ordering::AcqRel)
3715}
3716
3717unsafe fn a_fetch_add(addr: *mut c_int, val: c_int) -> c_int {
3718 (*(addr as *const AtomicI32)).fetch_add(val, Ordering::AcqRel)
3719}
3720
3721unsafe fn a_fetch_sub(addr: *mut c_int, val: c_int) -> c_int {
3722 (*(addr as *const AtomicI32)).fetch_sub(val, Ordering::AcqRel)
3723}
3724
3725unsafe fn spinlock_lock(lock: *mut c_int, waiters: *mut c_int) {
3726 while a_swap(lock, 1) != 0 {
3727 let mut spins = 100;
3728 while spins > 0 && a_load(lock) != 0 { core::hint::spin_loop(); spins -= 1; }
3729 if a_load(lock) == 0 { continue; }
3730 a_fetch_add(waiters, 1);
3731 futex_wait(lock, 1);
3732 a_fetch_sub(waiters, 1);
3733 }
3734}
3735
3736unsafe fn spinlock_unlock(lock: *mut c_int, waiters: *mut c_int) {
3737 a_store(lock, 0);
3738 if a_load(waiters) > 0 { futex_wake(lock, 1); }
3739}
3740
3741unsafe fn slot_index(slot: *const Thread) -> usize {
3742 let base = core::ptr::addr_of!(THREADS[0]) as usize;
3743 (slot as usize - base) / core::mem::size_of::<Thread>()
3744}
3745
3746unsafe fn release_thread_slot(slot: *const Thread) {
3747 let idx = slot_index(slot);
3748 if idx < MAX_THREADS {
3749 let word = idx / usize::BITS as usize;
3750 let bit = idx % usize::BITS as usize;
3751 SLOT_USED[word].fetch_and(!(1usize << bit), Ordering::AcqRel);
3752 }
3753}
3754
3755unsafe fn alloc_thread_slot() -> Option<&'static mut Thread> {
3756 for word in 0..SLOT_WORDS {
3757 let mut used = SLOT_USED[word].load(Ordering::Acquire);
3758 loop {
3759 let free = !used;
3760 if free == 0 {
3761 break;
3762 }
3763 let bit = free.trailing_zeros() as usize;
3764 let idx = word * usize::BITS as usize + bit;
3765 if idx >= MAX_THREADS {
3766 break;
3767 }
3768 match SLOT_USED[word].compare_exchange_weak(
3769 used,
3770 used | (1usize << bit),
3771 Ordering::AcqRel,
3772 Ordering::Acquire,
3773 ) {
3774 Ok(_) => return Some(&mut THREADS[idx]),
3775 Err(v) => used = v,
3776 }
3777 }
3778 }
3779 None
3780}
3781
3782unsafe fn run_key_dtors(slot: &mut Thread) {
3783 for _ in 0..PTHREAD_DESTRUCTOR_ITERATIONS {
3784 let mut any = false;
3785 for i in 0..PTHREAD_KEYS_MAX {
3786 let val = slot.tsd[i];
3787 if !val.is_null() {
3788 if let Some(dtor) = KEY_DTORS[i] {
3789 slot.tsd[i] = core::ptr::null_mut();
3790 any = true;
3791 dtor(val);
3792 }
3793 }
3794 }
3795 if !any { break; }
3796 }
3797}
3798
3799unsafe extern "C" fn thread_entry(slot: *mut c_void) -> *mut c_void {
3800 let slot = &mut *(slot as *mut Thread);
3801 slot.robust_list.list.next = core::ptr::null_mut();
3804 slot.robust_list.futex_offset = 0;
3805 slot.robust_list.pending = core::ptr::null_mut();
3806 ensure_robust_list(slot);
3807 let mut set: SigSetT = 0;
3808 sigemptyset(&mut set);
3809 sigaddset(&mut set, SIGCANCEL);
3810 pthread_sigmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
3811 let user_fn: unsafe extern "C" fn(*mut c_void) -> *mut c_void =
3812 core::mem::transmute::<usize, _>(slot.user_fn);
3813 let ret = user_fn(slot.user_arg);
3814 run_key_dtors(slot);
3815 slot.result = ret;
3816 a_store(&raw mut slot.detach_state, DT_EXITED);
3817 futex_wake(&raw mut slot.detach_state, 1);
3818 sys_exit_thread(0)
3819}
3820
3821unsafe fn find_thread() -> Option<&'static mut Thread> {
3822 let me = sys_gettid() as c_int;
3823 let base = core::ptr::addr_of_mut!(THREADS[0]);
3824 for i in 0..MAX_THREADS {
3825 let slot = base.add(i);
3826 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3827 return Some(&mut *slot);
3828 }
3829 }
3830 pthread_self();
3832 for i in 0..MAX_THREADS {
3833 let slot = base.add(i);
3834 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3835 return Some(&mut *slot);
3836 }
3837 }
3838 None
3839}
3840
3841#[no_mangle]
3842pub unsafe extern "C" fn pthread_self() -> PthreadT {
3843 let me = sys_gettid() as c_int;
3844 let base = core::ptr::addr_of_mut!(THREADS[0]);
3845 for i in 0..MAX_THREADS {
3846 let slot = base.add(i);
3847 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3848 return slot as PthreadT;
3849 }
3850 }
3851 if let Some(slot) = alloc_thread_slot() {
3853 let slot = slot as *mut Thread;
3854 (*slot).tid = me;
3855 (*slot).detach_state = DT_JOINABLE;
3856 return slot as PthreadT;
3857 }
3858 0
3859}
3860
3861#[no_mangle]
3862pub unsafe extern "C" fn pthread_equal(t1: PthreadT, t2: PthreadT) -> c_int {
3863 (t1 == t2) as c_int
3864}
3865
3866#[no_mangle]
3867pub unsafe extern "C" fn pthread_create(
3868 thread: *mut PthreadT,
3869 attr: *const pthread_attr_t,
3870 start_routine: usize,
3871 arg: *mut c_void,
3872) -> c_int {
3873 if start_routine == 0 || thread.is_null() { return EINVAL; }
3874 let Some(slot_ref) = alloc_thread_slot() else { return EAGAIN; };
3875 let slot = slot_ref as *mut Thread;
3876 let stack_size = if !attr.is_null() {
3877 let s = *((*attr).__i.as_ptr() as *const usize);
3878 if s > 0 { s } else { STACK_SIZE }
3879 } else { STACK_SIZE };
3880 let user_top = if !attr.is_null() {
3882 *((*attr).__i.as_ptr().add(4) as *const *mut c_void)
3883 } else {
3884 core::ptr::null_mut()
3885 };
3886 let stack_owned = user_top.is_null();
3887 let stack = if stack_owned {
3888 sys_mmap(null_mut(), stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
3889 } else {
3890 (user_top as *mut u8).sub(stack_size)
3891 };
3892 if stack == MMAP_FAILED { release_thread_slot(slot); return EAGAIN; }
3893 let static_mode = RC_STATIC_EXEC;
3894 let tls_total = if static_mode {
3895 STATIC_TLS_BLOCK_SIZE
3896 } else {
3897 __rc_tls_block_size()
3898 };
3899 let mut stack_top = stack.add(stack_size);
3900 let mut tls_owned = true;
3901 let fs_base = if static_mode {
3902 if !stack_owned && tls_total > 0 && stack_size > tls_total + 4096 {
3903 let block = ((user_top as usize - tls_total) & !63usize) as *mut u8;
3904 let fs = static_tls_init_block(block);
3905 if fs.is_null() {
3906 static_tls_create_block()
3907 } else {
3908 stack_top = block;
3909 tls_owned = false;
3910 fs
3911 }
3912 } else {
3913 static_tls_create_block()
3914 }
3915 } else if !stack_owned && tls_total > 0 && stack_size > tls_total + 4096 {
3916 let block = ((user_top as usize - tls_total) & !63usize) as *mut u8;
3920 let fs = __rc_init_thread_tls_at(block);
3921 if fs.is_null() {
3922 __rc_create_thread_tls()
3923 } else {
3924 stack_top = block;
3925 tls_owned = false;
3926 fs
3927 }
3928 } else {
3929 __rc_create_thread_tls()
3930 };
3931 if fs_base.is_null() {
3932 if stack_owned { sys_munmap(stack, stack_size); }
3933 release_thread_slot(slot);
3934 return EAGAIN;
3935 }
3936 let tls_base = if static_mode {
3937 fs_base.sub(STATIC_TLS_TP_OFFSET)
3938 } else {
3939 fs_base.sub(__rc_tls_base_offset())
3940 };
3941 let tls_size = if tls_owned { tls_total } else { 0 };
3942 (*slot).detach_state = DT_JOINABLE;
3943 (*slot).result = core::ptr::null_mut();
3944 (*slot).cancel = 0;
3945 (*slot).cancel_state = PTHREAD_CANCEL_ENABLE;
3946 (*slot).cancel_type = PTHREAD_CANCEL_DEFERRED;
3947 core::ptr::write_bytes((*slot).tsd.as_mut_ptr(), 0, PTHREAD_KEYS_MAX);
3948 (*slot).tid = 1;
3949 (*slot).user_fn = start_routine;
3950 (*slot).user_arg = arg;
3951 (*slot).stack = stack;
3952 (*slot).stack_size = stack_size;
3953 (*slot).stack_owned = stack_owned;
3954 (*slot).fs_base = fs_base;
3955 (*slot).tls_base = tls_base;
3956 (*slot).tls_size = tls_size;
3957 let tid_ptr = &raw mut (*slot).tid;
3958 let flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD
3959 | CLONE_SYSVSEM | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SETTLS;
3960 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);
3961 if tid < 0 {
3962 (*slot).tid = -1;
3963 if stack_owned { sys_munmap(stack, stack_size); }
3964 if tls_size > 0 { sys_munmap(tls_base, tls_size); }
3965 release_thread_slot(slot);
3966 return EAGAIN;
3967 }
3968 if !attr.is_null() && (*attr).__i[6] == PTHREAD_CREATE_DETACHED {
3969 (*slot).detach_state = DT_DETACHED;
3970 }
3971 *thread = slot as PthreadT;
3972 0
3973}
3974
3975#[no_mangle]
3976pub unsafe extern "C" fn pthread_join(thread: PthreadT, retval: *mut *mut c_void) -> c_int {
3977 let slot = thread as *mut Thread;
3978 if slot.is_null() { return EINVAL; }
3979 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
3980 let tid_ptr = &raw mut (*slot).tid;
3981 loop {
3982 pthread_testcancel();
3983 let tid = core::ptr::read_volatile(tid_ptr);
3984 if tid == 0 { break; }
3985 if tid < 0 { return EINVAL; }
3986 sys_futex(tid_ptr, FUTEX_WAIT, tid, null_mut(), null_mut(), 0);
3987 pthread_testcancel();
3988 }
3989 if !retval.is_null() { *retval = (*slot).result; }
3990 let stack = (*slot).stack;
3991 let stack_size = (*slot).stack_size;
3992 let stack_owned = (*slot).stack_owned;
3993 let tls_base = (*slot).tls_base;
3994 let tls_size = (*slot).tls_size;
3995 (*slot).tid = -1;
3996 (*slot).detach_state = DT_JOINABLE;
3997 (*slot).result = core::ptr::null_mut();
3998 (*slot).stack = core::ptr::null_mut();
3999 (*slot).stack_size = 0;
4000 (*slot).stack_owned = false;
4001 (*slot).fs_base = core::ptr::null_mut();
4002 (*slot).tls_base = core::ptr::null_mut();
4003 (*slot).tls_size = 0;
4004 if stack_owned && !stack.is_null() && stack_size > 0 { sys_munmap(stack, stack_size); }
4005 let _ = (tls_base, tls_size);
4015 release_thread_slot(slot);
4016 0
4017}
4018
4019#[no_mangle]
4020pub unsafe extern "C" fn pthread_detach(thread: PthreadT) -> c_int {
4021 let slot = thread as *mut Thread;
4022 if slot.is_null() { return EINVAL; }
4023 let old = a_cas(&raw mut (*slot).detach_state, DT_JOINABLE, DT_DETACHED);
4024 if old == DT_EXITED {
4025 let stack = (*slot).stack;
4026 let stack_size = (*slot).stack_size;
4027 let stack_owned = (*slot).stack_owned;
4028 let tls_base = (*slot).tls_base;
4029 let tls_size = (*slot).tls_size;
4030 (*slot).tid = -1;
4031 (*slot).stack = core::ptr::null_mut();
4032 (*slot).stack_size = 0;
4033 (*slot).stack_owned = false;
4034 (*slot).fs_base = core::ptr::null_mut();
4035 (*slot).tls_base = core::ptr::null_mut();
4036 (*slot).tls_size = 0;
4037 if stack_owned && !stack.is_null() && stack_size > 0 { sys_munmap(stack, stack_size); }
4038 let _ = (tls_base, tls_size);
4040 release_thread_slot(slot);
4041 }
4042 0
4043}
4044
4045#[no_mangle]
4046pub unsafe extern "C" fn pthread_exit(retval: *mut c_void) -> ! {
4047 if let Some(slot) = find_thread() {
4048 run_cleanup_handlers(slot);
4049 run_key_dtors(slot);
4050 slot.result = retval;
4051 slot.detach_state = DT_EXITED;
4052 futex_wake(&slot.detach_state as *const c_int as *mut c_int, 1);
4053
4054 let mut active = 0usize;
4056 for i in 0..MAX_THREADS {
4057 if THREADS[i].tid > 0 {
4058 active += 1;
4059 }
4060 }
4061 if active == 1 {
4062 exit(0);
4063 }
4064 }
4065 sys_exit_thread(0);
4066}
4067
4068#[no_mangle]
4070pub unsafe extern "C" fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int {
4071 core::ptr::write_bytes(attr, 0, 1);
4072 *((*attr).__i.as_mut_ptr() as *mut usize) = STACK_SIZE;
4073 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = 4096;
4074 (*attr).__i[6] = PTHREAD_CREATE_JOINABLE;
4075 (*attr).__i[7] = PTHREAD_INHERIT_SCHED;
4076 0
4077}
4078#[no_mangle]
4079pub unsafe extern "C" fn pthread_attr_destroy(_attr: *mut pthread_attr_t) -> c_int { 0 }
4080#[no_mangle]
4081pub unsafe extern "C" fn pthread_attr_setdetachstate(attr: *mut pthread_attr_t, s: c_int) -> c_int {
4082 if s != PTHREAD_CREATE_JOINABLE && s != PTHREAD_CREATE_DETACHED { return EINVAL; }
4083 (*attr).__i[6] = s; 0
4084}
4085#[no_mangle]
4086pub unsafe extern "C" fn pthread_attr_getdetachstate(attr: *const pthread_attr_t, s: *mut c_int) -> c_int {
4087 *s = (*attr).__i[6]; 0
4088}
4089#[no_mangle]
4090pub unsafe extern "C" fn pthread_attr_setstacksize(attr: *mut pthread_attr_t, sz: usize) -> c_int {
4091 if sz < 2048 { return EINVAL; }
4092 *((*attr).__i.as_mut_ptr() as *mut usize) = sz;
4093 *((*attr).__i.as_mut_ptr().add(4) as *mut *mut c_void) = core::ptr::null_mut();
4094 0
4095}
4096#[no_mangle]
4097pub unsafe extern "C" fn pthread_attr_getstacksize(attr: *const pthread_attr_t, sz: *mut usize) -> c_int {
4098 *sz = *((*attr).__i.as_ptr() as *const usize); 0
4099}
4100#[no_mangle]
4101pub unsafe extern "C" fn pthread_attr_setstack(attr: *mut pthread_attr_t, addr: *mut c_void, sz: usize) -> c_int {
4102 if sz < 2048 { return EINVAL; }
4103 *((*attr).__i.as_mut_ptr() as *mut usize) = sz;
4104 *((*attr).__i.as_mut_ptr().add(4) as *mut *mut c_void) = (addr as *mut u8).add(sz) as *mut c_void;
4106 0
4107}
4108#[no_mangle]
4109pub unsafe extern "C" fn pthread_attr_getstack(attr: *const pthread_attr_t, addr: *mut *mut c_void, sz: *mut usize) -> c_int {
4110 let size = *((*attr).__i.as_ptr() as *const usize);
4111 *sz = size;
4112 let top = *((*attr).__i.as_ptr().add(4) as *const *mut c_void);
4113 *addr = if top.is_null() {
4114 core::ptr::null_mut()
4115 } else {
4116 (top as *mut u8).sub(size) as *mut c_void
4117 };
4118 0
4119}
4120#[no_mangle]
4121pub unsafe extern "C" fn pthread_attr_setguardsize(attr: *mut pthread_attr_t, sz: usize) -> c_int {
4122 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = sz; 0
4123}
4124#[no_mangle]
4125pub unsafe extern "C" fn pthread_attr_getguardsize(attr: *const pthread_attr_t, sz: *mut usize) -> c_int {
4126 *sz = *((*attr).__i.as_ptr().add(2) as *const usize); 0
4127}
4128#[no_mangle]
4129pub unsafe extern "C" fn pthread_attr_setscope(_attr: *mut pthread_attr_t, scope: c_int) -> c_int {
4130 if scope != PTHREAD_SCOPE_SYSTEM { return EINVAL; }
4131 0
4132}
4133#[no_mangle]
4134pub unsafe extern "C" fn pthread_attr_getscope(_attr: *const pthread_attr_t, scope: *mut c_int) -> c_int {
4135 *scope = PTHREAD_SCOPE_SYSTEM; 0
4136}
4137#[no_mangle]
4138pub unsafe extern "C" fn pthread_attr_setinheritsched(attr: *mut pthread_attr_t, inh: c_int) -> c_int {
4139 if inh != PTHREAD_INHERIT_SCHED && inh != PTHREAD_EXPLICIT_SCHED { return EINVAL; }
4140 (*attr).__i[7] = inh; 0
4141}
4142#[no_mangle]
4143pub unsafe extern "C" fn pthread_attr_getinheritsched(attr: *const pthread_attr_t, inh: *mut c_int) -> c_int {
4144 *inh = (*attr).__i[7]; 0
4145}
4146#[no_mangle]
4147pub unsafe extern "C" fn pthread_attr_setschedpolicy(attr: *mut pthread_attr_t, p: c_int) -> c_int {
4148 (*attr).__i[8] = p; 0
4149}
4150#[no_mangle]
4151pub unsafe extern "C" fn pthread_attr_getschedpolicy(attr: *const pthread_attr_t, p: *mut c_int) -> c_int {
4152 *p = (*attr).__i[8]; 0
4153}
4154#[no_mangle]
4155pub unsafe extern "C" fn pthread_attr_setschedparam(attr: *mut pthread_attr_t, param: *const sched_param) -> c_int {
4156 (*attr).__i[9] = (*param).sched_priority; 0
4157}
4158#[no_mangle]
4159pub unsafe extern "C" fn pthread_attr_getschedparam(attr: *const pthread_attr_t, param: *mut sched_param) -> c_int {
4160 (*param).sched_priority = (*attr).__i[9]; 0
4161}
4162
4163#[no_mangle]
4165pub unsafe extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int {
4166 (*attr).__attr = 0; 0
4167}
4168#[no_mangle]
4169pub unsafe extern "C" fn pthread_mutexattr_destroy(_attr: *mut pthread_mutexattr_t) -> c_int { 0 }
4170#[no_mangle]
4171pub unsafe extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, t: c_int) -> c_int {
4172 if (t as c_uint) > 2 { return EINVAL; }
4173 (*attr).__attr = ((*attr).__attr & !3) | t as c_uint; 0
4174}
4175#[no_mangle]
4176pub unsafe extern "C" fn pthread_mutexattr_gettype(attr: *const pthread_mutexattr_t, t: *mut c_int) -> c_int {
4177 *t = ((*attr).__attr & 3) as c_int; 0
4178}
4179#[no_mangle]
4180pub unsafe extern "C" fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, p: c_int) -> c_int {
4181 if (p as c_uint) > 1 { return EINVAL; }
4182 (*attr).__attr = ((*attr).__attr & !128) | ((p as c_uint) << 7); 0
4183}
4184#[no_mangle]
4185pub unsafe extern "C" fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, p: *mut c_int) -> c_int {
4186 *p = (((*attr).__attr >> 7) & 1) as c_int; 0
4187}
4188
4189#[no_mangle]
4190pub unsafe extern "C" fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int {
4191 match protocol {
4192 0 => { (*attr).__attr &= !(MUTEX_PI as c_uint); 0 }
4193 1 => {
4194 let mut lk: c_int = 0;
4195 let r = sys_futex(&raw mut lk, FUTEX_LOCK_PI, 0, null_mut(), null_mut(), 0);
4196 if r < 0 { return (-r) as c_int; }
4197 sys_futex(&raw mut lk, FUTEX_UNLOCK_PI, 0, null_mut(), null_mut(), 0);
4198 (*attr).__attr |= MUTEX_PI as c_uint;
4199 0
4200 }
4201 2 => ENOTSUP,
4202 _ => EINVAL,
4203 }
4204}
4205#[no_mangle]
4206pub unsafe extern "C" fn pthread_mutexattr_getprotocol(attr: *const pthread_mutexattr_t, protocol: *mut c_int) -> c_int {
4207 *protocol = (((*attr).__attr >> 3) & 3) as c_int; 0
4208}
4209
4210const ENOTSUP: c_int = 95;
4211
4212#[no_mangle]
4213pub unsafe extern "C" fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robust: c_int) -> c_int {
4214 if (robust as c_uint) > 1 { return EINVAL; }
4215 if robust != 0 {
4216 (*attr).__attr |= MUTEX_ROBUST as c_uint;
4217 } else {
4218 (*attr).__attr &= !(MUTEX_ROBUST as c_uint);
4219 }
4220 0
4221}
4222#[no_mangle]
4223pub unsafe extern "C" fn pthread_mutexattr_getrobust(attr: *const pthread_mutexattr_t, robust: *mut c_int) -> c_int {
4224 *robust = (((*attr).__attr >> 2) & 1) as c_int; 0
4225}
4226
4227#[no_mangle]
4228pub unsafe extern "C" fn pthread_mutex_consistent(m: *mut pthread_mutex_t) -> c_int {
4229 let old = a_load(&raw const (*m).__i[1]);
4230 let own = old & 0x3fffffff;
4231 if ((*m).__i[0] & MUTEX_ROBUST) == 0 || own == 0 || (old & 0x40000000) == 0 {
4232 return EINVAL;
4233 }
4234 let self_tid = sys_gettid() as c_int;
4235 if own != self_tid { return EPERM; }
4236 a_and(&raw mut (*m).__i[1], !(0x40000000i32));
4237 0
4238}
4239
4240unsafe fn a_and(addr: *mut c_int, val: c_int) {
4241 let a = &*(addr as *const AtomicI32);
4242 a.fetch_and(val, Ordering::AcqRel);
4243}
4244
4245const MUTEX_TYPE_MASK: c_int = 3;
4247const MUTEX_ROBUST: c_int = 4;
4248const MUTEX_PI: c_int = 8;
4249const MUTEX_PSHARED: c_int = 128;
4250
4251unsafe fn ensure_robust_list(slot: &mut Thread) {
4252 if slot.robust_list.futex_offset == 0 {
4253 slot.robust_list.futex_offset = -28;
4254 slot.robust_list.pending = core::ptr::null_mut();
4255 sys_set_robust_list(&mut slot.robust_list, 24);
4256 }
4257}
4258
4259unsafe fn mutex_trylock(m: *mut pthread_mutex_t) -> c_int {
4260 let type_ = (*m).__i[0];
4261 if (type_ & 0x8f) == PTHREAD_MUTEX_NORMAL {
4266 let old = a_cas(&raw mut (*m).__i[1], 0, EBUSY);
4267 return if old == 0 { 0 } else { EBUSY };
4268 }
4269 let base_type = type_ & MUTEX_TYPE_MASK;
4270 let self_tid = sys_gettid() as c_int;
4271 let old = a_load(&raw const (*m).__i[1]);
4272 let own = old & 0x3fffffff;
4273 if own == self_tid {
4274 if (type_ & MUTEX_PI) != 0 && (*m).__i[5] < 0 {
4275 (*m).__i[5] = 0;
4276 return 0;
4277 }
4278 if base_type == PTHREAD_MUTEX_RECURSIVE {
4279 if (*m).__i[5] >= c_int::MAX { return EAGAIN; }
4280 (*m).__i[5] += 1;
4281 return 0;
4282 }
4283 if base_type == PTHREAD_MUTEX_ERRORCHECK { return EDEADLK; }
4284 return EBUSY;
4285 }
4286 if own == 0x3fffffff { return ENOTRECOVERABLE; }
4287 if own != 0 || (old != 0 && (type_ & MUTEX_ROBUST) == 0) { return EBUSY; }
4288 let mut newtid = self_tid;
4289 if (type_ & MUTEX_ROBUST) != 0 {
4290 if (*m).__i[2] != 0 { newtid |= 1i32 << 31; }
4291 newtid |= old & 0x40000000;
4292 }
4293 if a_cas(&raw mut (*m).__i[1], old, newtid) == old {
4294 (*m).__i[5] = 0;
4295 if (type_ & MUTEX_ROBUST) != 0 {
4296 if let Some(slot) = find_thread() {
4297 ensure_robust_list(slot);
4298 let m_next = &raw mut (*m).__i[8] as *mut robust_list;
4299 let head = &mut slot.robust_list.list;
4300 (*m_next).next = head.next;
4301 head.next = m_next;
4302 }
4303 }
4304 if old != 0 { return EOWNERDEAD; }
4305 0
4306 } else { EBUSY }
4307}
4308
4309unsafe fn mutex_lock_internal(m: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4310 let type_ = (*m).__i[0];
4311 if (type_ & 0x8f) == PTHREAD_MUTEX_NORMAL && a_cas(&raw mut (*m).__i[1], 0, EBUSY) == 0 {
4312 return 0;
4313 }
4314 let r = mutex_trylock(m);
4315 if r != EBUSY { return r; }
4316 if (type_ & MUTEX_PI) != 0 {
4317 let timeout_ptr = if abs_timeout.is_null() { core::ptr::null() } else { abs_timeout };
4318 loop {
4319 let e = futex_lock_pi(&raw mut (*m).__i[1], timeout_ptr);
4320 match e {
4321 0 => {
4322 if (type_ & MUTEX_ROBUST) != 0 && (((*m).__i[1] & 0x40000000) != 0 || (*m).__i[2] != 0) {
4323 (*m).__i[5] = -1;
4324 let _ = mutex_trylock(m);
4325 return EOWNERDEAD;
4326 }
4327 if (type_ & MUTEX_ROBUST) == 0 && (((*m).__i[1] & 0x40000000) != 0 || (*m).__i[2] != 0) {
4328 (*m).__i[2] = -1;
4329 futex_unlock_pi(&raw mut (*m).__i[1]);
4330 return EBUSY;
4331 }
4332 (*m).__i[5] = -1;
4333 let r2 = mutex_trylock(m);
4334 if r2 == 0 { return 0; }
4335 return r2;
4336 }
4337 EINTR => continue,
4338 EDEADLK => {
4339 if (type_ & MUTEX_TYPE_MASK) == PTHREAD_MUTEX_ERRORCHECK { return e; }
4340 loop { pause(); }
4341 }
4342 EOWNERDEAD => {
4343 (*m).__i[5] = -1;
4344 let _ = mutex_trylock(m);
4345 return EOWNERDEAD;
4346 }
4347 _ => return e,
4348 }
4349 }
4350 }
4351 let mut spins = 100;
4352 while spins > 0 {
4353 let r = mutex_trylock(m);
4354 if r != EBUSY { return r; }
4355 core::hint::spin_loop();
4356 spins -= 1;
4357 }
4358 loop {
4359 let r = mutex_trylock(m);
4360 if r != EBUSY { return r; }
4361 if (type_ & MUTEX_TYPE_MASK) == PTHREAD_MUTEX_ERRORCHECK {
4362 let self_tid = sys_gettid() as c_int;
4363 if (a_load(&raw const (*m).__i[1]) & 0x3fffffff) == self_tid { return EDEADLK; }
4364 }
4365 a_fetch_add(&raw mut (*m).__i[2], 1);
4366 let val = a_load(&raw const (*m).__i[1]);
4367 if val == 0 {
4371 a_fetch_sub(&raw mut (*m).__i[2], 1);
4372 continue;
4373 }
4374 a_cas(&raw mut (*m).__i[1], val, val | (1i32 << 31));
4375 let e = futex_timedwait(&raw mut (*m).__i[1], val | (1i32 << 31), abs_timeout);
4376 a_fetch_sub(&raw mut (*m).__i[2], 1);
4377 if e != 0 && e != EINTR { return e; }
4378 }
4379}
4380
4381#[no_mangle]
4382pub unsafe extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t) -> c_int {
4383 core::ptr::write_bytes(mutex, 0, 1);
4384 if !attr.is_null() { (*mutex).__i[0] = (*attr).__attr as c_int; }
4385 0
4386}
4387#[no_mangle]
4388pub unsafe extern "C" fn pthread_mutex_destroy(_mutex: *mut pthread_mutex_t) -> c_int { 0 }
4389#[no_mangle]
4390pub unsafe extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int {
4391 mutex_lock_internal(mutex, core::ptr::null())
4392}
4393#[no_mangle]
4394pub unsafe extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int {
4395 mutex_trylock(mutex)
4396}
4397#[no_mangle]
4398pub unsafe extern "C" fn pthread_mutex_timedlock(mutex: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4399 mutex_lock_internal(mutex, abs_timeout)
4400}
4401#[no_mangle]
4402pub unsafe extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int {
4403 let type_ = (*mutex).__i[0];
4404 let base_type = type_ & MUTEX_TYPE_MASK;
4405 let old = a_load(&raw const (*mutex).__i[1]);
4406 if base_type != PTHREAD_MUTEX_NORMAL {
4407 let self_tid = sys_gettid() as c_int;
4408 if (old & 0x3fffffff) != self_tid { return EPERM; }
4409 if base_type == PTHREAD_MUTEX_RECURSIVE && (*mutex).__i[5] > 0 {
4410 (*mutex).__i[5] -= 1;
4411 return 0;
4412 }
4413 }
4414 let mut new = 0;
4415 if (type_ & MUTEX_ROBUST) != 0 && (old & 0x40000000) != 0 {
4416 new = 0x7fffffff;
4417 }
4418 if (type_ & MUTEX_PI) != 0 {
4419 if old < 0 || a_cas(&raw mut (*mutex).__i[1], old, new) != old {
4420 if new != 0 { a_store(&raw mut (*mutex).__i[2], -1); }
4421 return futex_unlock_pi(&raw mut (*mutex).__i[1]);
4422 }
4423 return 0;
4424 }
4425 a_store(&raw mut (*mutex).__i[1], new);
4426 if new == 0 && (a_load(&raw const (*mutex).__i[2]) > 0 || old < 0) {
4427 futex_wake(&raw mut (*mutex).__i[1], 1);
4428 }
4429 0
4430}
4431
4432#[no_mangle]
4434pub unsafe extern "C" fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> c_int {
4435 (*attr).__attr = 0; 0
4436}
4437#[no_mangle]
4438pub unsafe extern "C" fn pthread_condattr_destroy(_attr: *mut pthread_condattr_t) -> c_int { 0 }
4439#[no_mangle]
4440pub unsafe extern "C" fn pthread_condattr_setclock(attr: *mut pthread_condattr_t, clk: c_int) -> c_int {
4441 if clk != CLOCK_REALTIME && clk != CLOCK_MONOTONIC { return EINVAL; }
4442 (*attr).__attr = ((*attr).__attr & 0x80000000) | clk as c_uint; 0
4443}
4444#[no_mangle]
4445pub unsafe extern "C" fn pthread_condattr_getclock(attr: *const pthread_condattr_t, clk: *mut c_int) -> c_int {
4446 *clk = ((*attr).__attr & 0x7fffffff) as c_int; 0
4447}
4448#[no_mangle]
4449pub unsafe extern "C" fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, p: c_int) -> c_int {
4450 if (p as c_uint) > 1 { return EINVAL; }
4451 (*attr).__attr = ((*attr).__attr & 0x7fffffff) | ((p as c_uint) << 31); 0
4452}
4453#[no_mangle]
4454pub unsafe extern "C" fn pthread_condattr_getpshared(attr: *const pthread_condattr_t, p: *mut c_int) -> c_int {
4455 *p = ((*attr).__attr >> 31) as c_int; 0
4456}
4457
4458#[no_mangle]
4460pub unsafe extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int {
4461 core::ptr::write_bytes(cond, 0, 1);
4462 if !attr.is_null() {
4463 (*cond).__i[4] = ((*attr).__attr & 0x7fffffff) as c_int;
4464 }
4465 0
4466}
4467#[no_mangle]
4468pub unsafe extern "C" fn pthread_cond_destroy(_cond: *mut pthread_cond_t) -> c_int { 0 }
4469#[no_mangle]
4470pub unsafe extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t) -> c_int {
4471 pthread_cond_timedwait(cond, mutex, core::ptr::null())
4472}
4473
4474
4475#[no_mangle]
4476pub unsafe extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4477 pthread_testcancel();
4478 let seq_ptr = &raw mut (*cond).__i[2];
4479 let waiters_ptr = &raw mut (*cond).__i[3];
4480 let seq = a_load(seq_ptr);
4481 a_fetch_add(waiters_ptr, 1);
4482 pthread_mutex_unlock(mutex);
4483 let e = futex_timedwait(seq_ptr, seq, abs_timeout);
4484 a_fetch_sub(waiters_ptr, 1);
4485 let r = pthread_mutex_lock(mutex);
4486 if r != 0 { return r; }
4487 if e == EINTR {
4488 pthread_testcancel();
4489 }
4490 if e != 0 && e != EINTR { return e; }
4491 0
4492}
4493#[no_mangle]
4494pub unsafe extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int {
4495 if a_load(&raw const (*cond).__i[3]) == 0 { return 0; }
4496 a_fetch_add(&raw mut (*cond).__i[2], 1);
4497 futex_wake(&raw mut (*cond).__i[2], 1);
4498 0
4499}
4500#[no_mangle]
4501pub unsafe extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int {
4502 if a_load(&raw const (*cond).__i[3]) == 0 { return 0; }
4503 a_fetch_add(&raw mut (*cond).__i[2], 1);
4504 futex_wake(&raw mut (*cond).__i[2], -1);
4505 0
4506}
4507
4508#[no_mangle]
4510pub unsafe extern "C" fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> c_int {
4511 (*attr).__attr = [0; 2]; 0
4512}
4513#[no_mangle]
4514pub unsafe extern "C" fn pthread_rwlockattr_destroy(_attr: *mut pthread_rwlockattr_t) -> c_int { 0 }
4515#[no_mangle]
4516pub unsafe extern "C" fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, p: c_int) -> c_int {
4517 if (p as c_uint) > 1 { return EINVAL; }
4518 (*attr).__attr[0] = ((*attr).__attr[0] & !128) | ((p as c_uint) << 7); 0
4519}
4520#[no_mangle]
4521pub unsafe extern "C" fn pthread_rwlockattr_getpshared(attr: *const pthread_rwlockattr_t, p: *mut c_int) -> c_int {
4522 *p = (((*attr).__attr[0] >> 7) & 1) as c_int; 0
4523}
4524
4525unsafe fn rwlock_tryrdlock(rw: *mut pthread_rwlock_t) -> c_int {
4527 loop {
4528 let val = a_load(&raw const (*rw).__i[0]);
4529 let cnt = val & 0x7fffffff;
4530 if cnt == 0x7fffffff { return EBUSY; }
4531 if cnt == 0x7ffffffe { return EAGAIN; }
4532 if a_cas(&raw mut (*rw).__i[0], val, val + 1) == val { return 0; }
4533 }
4534}
4535unsafe fn rwlock_trywrlock(rw: *mut pthread_rwlock_t) -> c_int {
4536 if a_cas(&raw mut (*rw).__i[0], 0, 0x7fffffff) == 0 { 0 } else { EBUSY }
4537}
4538unsafe fn rwlock_timedrdlock(rw: *mut pthread_rwlock_t, abs_timeout: *const timespec) -> c_int {
4539 let r = rwlock_tryrdlock(rw);
4540 if r != EBUSY { return r; }
4541 let mut spins = 100;
4542 while spins > 0 { let r = rwlock_tryrdlock(rw); if r != EBUSY { return r; } core::hint::spin_loop(); spins -= 1; }
4543 loop {
4544 let r = rwlock_tryrdlock(rw);
4545 if r != EBUSY { return r; }
4546 let val = a_load(&raw const (*rw).__i[0]);
4547 if val & 0x7fffffff != 0x7fffffff { continue; }
4548 a_fetch_add(&raw mut (*rw).__i[1], 1);
4549 a_cas(&raw mut (*rw).__i[0], val, val | (1i32 << 31));
4550 let e = futex_timedwait(&raw mut (*rw).__i[0], val | (1i32 << 31), abs_timeout);
4551 a_fetch_sub(&raw mut (*rw).__i[1], 1);
4552 if e != 0 && e != EINTR { return e; }
4553 }
4554}
4555unsafe fn rwlock_timedwrlock(rw: *mut pthread_rwlock_t, abs_timeout: *const timespec) -> c_int {
4556 let r = rwlock_trywrlock(rw);
4557 if r != EBUSY { return r; }
4558 let mut spins = 100;
4559 while spins > 0 { let r = rwlock_trywrlock(rw); if r != EBUSY { return r; } core::hint::spin_loop(); spins -= 1; }
4560 loop {
4561 let r = rwlock_trywrlock(rw);
4562 if r != EBUSY { return r; }
4563 let val = a_load(&raw const (*rw).__i[0]);
4564 if val == 0 { continue; }
4565 a_fetch_add(&raw mut (*rw).__i[1], 1);
4566 a_cas(&raw mut (*rw).__i[0], val, val | (1i32 << 31));
4567 let e = futex_timedwait(&raw mut (*rw).__i[0], val | (1i32 << 31), abs_timeout);
4568 a_fetch_sub(&raw mut (*rw).__i[1], 1);
4569 if e != 0 && e != EINTR { return e; }
4570 }
4571}
4572
4573#[no_mangle]
4574pub unsafe extern "C" fn pthread_rwlock_init(rw: *mut pthread_rwlock_t, attr: *const pthread_rwlockattr_t) -> c_int {
4575 core::ptr::write_bytes(rw, 0, 1);
4576 if !attr.is_null() { (*rw).__i[2] = (*attr).__attr[0] as c_int & 128; }
4577 0
4578}
4579#[no_mangle]
4580pub unsafe extern "C" fn pthread_rwlock_destroy(_rw: *mut pthread_rwlock_t) -> c_int { 0 }
4581#[no_mangle]
4582pub unsafe extern "C" fn pthread_rwlock_rdlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_timedrdlock(rw, core::ptr::null()) }
4583#[no_mangle]
4584pub unsafe extern "C" fn pthread_rwlock_tryrdlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_tryrdlock(rw) }
4585#[no_mangle]
4586pub unsafe extern "C" fn pthread_rwlock_timedrdlock(rw: *mut pthread_rwlock_t, t: *const timespec) -> c_int { rwlock_timedrdlock(rw, t) }
4587#[no_mangle]
4588pub unsafe extern "C" fn pthread_rwlock_wrlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_timedwrlock(rw, core::ptr::null()) }
4589#[no_mangle]
4590pub unsafe extern "C" fn pthread_rwlock_trywrlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_trywrlock(rw) }
4591#[no_mangle]
4592pub unsafe extern "C" fn pthread_rwlock_timedwrlock(rw: *mut pthread_rwlock_t, t: *const timespec) -> c_int { rwlock_timedwrlock(rw, t) }
4593#[no_mangle]
4594pub unsafe extern "C" fn pthread_rwlock_unlock(rw: *mut pthread_rwlock_t) -> c_int {
4595 loop {
4596 let val = a_load(&raw const (*rw).__i[0]);
4597 let cnt = val & 0x7fffffff;
4598 let new_val = if cnt == 0x7fffffff || cnt == 1 { 0 } else { val - 1 };
4599 if a_cas(&raw mut (*rw).__i[0], val, new_val) == val {
4600 if new_val == 0 && (a_load(&raw const (*rw).__i[1]) > 0 || val < 0) {
4601 futex_wake(&raw mut (*rw).__i[0], cnt);
4602 }
4603 return 0;
4604 }
4605 }
4606}
4607
4608#[no_mangle]
4610pub unsafe extern "C" fn pthread_barrierattr_init(attr: *mut pthread_barrierattr_t) -> c_int { (*attr).__attr = 0; 0 }
4611#[no_mangle]
4612pub unsafe extern "C" fn pthread_barrierattr_destroy(_attr: *mut pthread_barrierattr_t) -> c_int { 0 }
4613#[no_mangle]
4614pub unsafe extern "C" fn pthread_barrierattr_setpshared(attr: *mut pthread_barrierattr_t, p: c_int) -> c_int {
4615 if (p as c_uint) > 1 { return EINVAL; }
4616 (*attr).__attr = p as c_uint; 0
4617}
4618#[no_mangle]
4619pub unsafe extern "C" fn pthread_barrierattr_getpshared(attr: *const pthread_barrierattr_t, p: *mut c_int) -> c_int {
4620 *p = (*attr).__attr as c_int; 0
4621}
4622
4623#[no_mangle]
4625pub unsafe extern "C" fn pthread_barrier_init(b: *mut pthread_barrier_t, _attr: *const pthread_barrierattr_t, count: c_uint) -> c_int {
4626 if count == 0 { return EINVAL; }
4627 core::ptr::write_bytes(b, 0, 1);
4628 (*b).__i[2] = count as c_int - 1;
4629 0
4630}
4631#[no_mangle]
4632pub unsafe extern "C" fn pthread_barrier_destroy(_b: *mut pthread_barrier_t) -> c_int { 0 }
4633#[no_mangle]
4634pub unsafe extern "C" fn pthread_barrier_wait(b: *mut pthread_barrier_t) -> c_int {
4635 let limit = (*b).__i[2];
4636 if limit == 0 { return PTHREAD_BARRIER_SERIAL_THREAD; }
4637 spinlock_lock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4638 let arrived = a_load(&raw const (*b).__i[3]) + 1;
4639 a_store(&raw mut (*b).__i[3], arrived);
4640 if arrived > limit {
4641 a_store(&raw mut (*b).__i[3], 0);
4642 let gen = a_load(&raw const (*b).__i[4]);
4643 a_store(&raw mut (*b).__i[4], gen + 1);
4644 spinlock_unlock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4645 futex_wake(&raw mut (*b).__i[4], -1);
4646 return PTHREAD_BARRIER_SERIAL_THREAD;
4647 }
4648 let gen = a_load(&raw const (*b).__i[4]);
4649 spinlock_unlock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4650 while a_load(&raw const (*b).__i[4]) == gen {
4651 futex_wait(&raw mut (*b).__i[4], gen);
4652 }
4653 0
4654}
4655
4656#[no_mangle]
4658pub unsafe extern "C" fn pthread_spin_init(s: *mut pthread_spinlock_t, _pshared: c_int) -> c_int { a_store(s, 0); 0 }
4659#[no_mangle]
4660pub unsafe extern "C" fn pthread_spin_destroy(_s: *mut pthread_spinlock_t) -> c_int { 0 }
4661#[no_mangle]
4662pub unsafe extern "C" fn pthread_spin_lock(s: *mut pthread_spinlock_t) -> c_int {
4663 while a_load(s) != 0 || a_cas(s, 0, EBUSY) != 0 { core::hint::spin_loop(); }
4664 0
4665}
4666#[no_mangle]
4667pub unsafe extern "C" fn pthread_spin_trylock(s: *mut pthread_spinlock_t) -> c_int { a_cas(s, 0, EBUSY) }
4668#[no_mangle]
4669pub unsafe extern "C" fn pthread_spin_unlock(s: *mut pthread_spinlock_t) -> c_int { a_store(s, 0); 0 }
4670
4671#[no_mangle]
4673pub unsafe extern "C" fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int {
4674 if value > SEM_VALUE_MAX as c_uint { return EINVAL; }
4675 (*sem).__val[0] = value as c_int;
4676 (*sem).__val[1] = 0;
4677 (*sem).__val[2] = if pshared != 0 { 0 } else { 128 };
4678 0
4679}
4680#[no_mangle]
4681pub unsafe extern "C" fn sem_destroy(_sem: *mut sem_t) -> c_int { 0 }
4682
4683unsafe fn sem_trywait_internal(sem: *mut sem_t) -> c_int {
4684 loop {
4685 let val = a_load(&raw const (*sem).__val[0]);
4686 if val & SEM_VALUE_MAX == 0 { return EAGAIN; }
4687 if a_cas(&raw mut (*sem).__val[0], val, val - 1) == val { return 0; }
4688 }
4689}
4690
4691#[no_mangle]
4692pub unsafe extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
4693 if sem_trywait_internal(sem) == 0 { 0 } else { ERRNO!() = EAGAIN; -1 }
4694}
4695#[no_mangle]
4696pub unsafe extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
4697 pthread_testcancel();
4698 if sem_trywait_internal(sem) == 0 { return 0; }
4699 let mut spins = 100;
4700 while spins > 0 { if sem_trywait_internal(sem) == 0 { return 0; } core::hint::spin_loop(); spins -= 1; }
4701 loop {
4702 pthread_testcancel();
4703 if sem_trywait_internal(sem) == 0 { return 0; }
4704 let val = a_load(&raw const (*sem).__val[0]);
4705 if val & SEM_VALUE_MAX != 0 { continue; }
4706 a_cas(&raw mut (*sem).__val[0], val, val | (1i32 << 31));
4707 a_fetch_add(&raw mut (*sem).__val[1], 1);
4708 futex_wait(&raw mut (*sem).__val[0], 1i32 << 31);
4709 a_fetch_sub(&raw mut (*sem).__val[1], 1);
4710 }
4711}
4712#[no_mangle]
4713pub unsafe extern "C" fn sem_timedwait(sem: *mut sem_t, abs_timeout: *const timespec) -> c_int {
4714 pthread_testcancel();
4715 if sem_trywait_internal(sem) == 0 { return 0; }
4716 let mut spins = 100;
4717 while spins > 0 { if sem_trywait_internal(sem) == 0 { return 0; } core::hint::spin_loop(); spins -= 1; }
4718 loop {
4719 pthread_testcancel();
4720 if sem_trywait_internal(sem) == 0 { return 0; }
4721 let val = a_load(&raw const (*sem).__val[0]);
4722 if val & SEM_VALUE_MAX != 0 { continue; }
4723 a_cas(&raw mut (*sem).__val[0], val, val | (1i32 << 31));
4724 a_fetch_add(&raw mut (*sem).__val[1], 1);
4725 let e = futex_timedwait(&raw mut (*sem).__val[0], 1i32 << 31, abs_timeout);
4726 a_fetch_sub(&raw mut (*sem).__val[1], 1);
4727 if e != 0 && e != EINTR { ERRNO!() = e; return -1; }
4728 }
4729}
4730#[no_mangle]
4731pub unsafe extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
4732 loop {
4733 let val = a_load(&raw const (*sem).__val[0]);
4734 if (val & SEM_VALUE_MAX) == SEM_VALUE_MAX { ERRNO!() = EOVERFLOW; return -1; }
4735 let mut new = val + 1;
4736 let waiters = a_load(&raw const (*sem).__val[1]);
4737 if waiters <= 1 { new &= !(1i32 << 31); }
4738 if a_cas(&raw mut (*sem).__val[0], val, new) == val {
4739 if val < 0 || waiters > 0 {
4740 futex_wake(&raw mut (*sem).__val[0], if waiters > 1 { 1 } else { -1 });
4741 }
4742 return 0;
4743 }
4744 }
4745}
4746#[no_mangle]
4747pub unsafe extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int {
4748 *sval = a_load(&raw const (*sem).__val[0]) & SEM_VALUE_MAX;
4749 0
4750}
4751
4752const NAME_MAX: usize = 255;
4757const SEM_NSEMS_MAX: usize = 256;
4758
4759static SEMTAB_LOCK: AtomicI32 = AtomicI32::new(0);
4761
4762struct SemEntry {
4763 ino: u64,
4764 sem: *mut sem_t,
4765 refcnt: u32,
4766}
4767
4768static mut SEMTAB: [SemEntry; SEM_NSEMS_MAX] = {
4770 const ZERO: SemEntry = SemEntry { ino: 0, sem: core::ptr::null_mut(), refcnt: 0 };
4771 [ZERO; SEM_NSEMS_MAX]
4772};
4773
4774unsafe fn semtab_lock() {
4775 while SEMTAB_LOCK.compare_exchange_weak(0, 1, Ordering::Acquire, Ordering::Relaxed).is_err() {
4776 core::hint::spin_loop();
4777 }
4778}
4779
4780unsafe fn semtab_unlock() {
4781 SEMTAB_LOCK.store(0, Ordering::Release);
4782}
4783
4784unsafe fn shm_mapname(name: *const c_char, buf: *mut u8) -> c_int {
4787 let mut p = name;
4788 while *p == b'/' as c_char { p = p.add(1); }
4790 let start = p;
4791 while *p != 0 && *p != b'/' as c_char { p = p.add(1); }
4793 let len = p.offset_from(start) as usize;
4794 if len == 0 || *p != 0 {
4796 ERRNO!() = EINVAL;
4797 return -1;
4798 }
4799 if len == 1 && *start == b'.' as c_char {
4800 ERRNO!() = EINVAL;
4801 return -1;
4802 }
4803 if len == 2 && *start == b'.' as c_char && *start.add(1) == b'.' as c_char {
4804 ERRNO!() = EINVAL;
4805 return -1;
4806 }
4807 if len > NAME_MAX {
4808 ERRNO!() = ENAMETOOLONG;
4809 return -1;
4810 }
4811 let prefix = b"/dev/shm/\0";
4813 let mut i = 0;
4814 while prefix[i] != 0 {
4815 *buf.add(i) = prefix[i];
4816 i += 1;
4817 }
4818 let mut j = 0;
4819 while j < len {
4820 *buf.add(i + j) = *start.add(j) as u8;
4821 j += 1;
4822 }
4823 *buf.add(i + j) = 0;
4824 (i + j) as c_int
4825}
4826
4827#[no_mangle]
4828pub unsafe extern "C" fn shm_open(name: *const c_char, flags: c_int, mode: mode_t) -> c_int {
4829 let mut buf = [0u8; 16 + NAME_MAX + 1];
4830 if shm_mapname(name, buf.as_mut_ptr()) < 0 { return -1; }
4831 let fd = sys_open(buf.as_ptr(), (flags | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, mode as i64);
4832 if fd < 0 { ERRNO!() = (-fd) as c_int; return -1; }
4833 fd as c_int
4834}
4835
4836#[no_mangle]
4837pub unsafe extern "C" fn shm_unlink(name: *const c_char) -> c_int {
4838 let mut buf = [0u8; 16 + NAME_MAX + 1];
4839 if shm_mapname(name, buf.as_mut_ptr()) < 0 { return -1; }
4840 let r = sys_unlink(buf.as_ptr());
4841 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
4842 0
4843}
4844
4845#[no_mangle]
4846pub unsafe extern "C" fn sem_open(name: *const c_char, flags: c_int, mut args: ...) -> *mut sem_t {
4847 let mut buf = [0u8; 16 + NAME_MAX + 1];
4848 if shm_mapname(name, buf.as_mut_ptr()).is_negative() {
4849 return core::ptr::null_mut(); }
4851
4852 let oflags = flags & (O_CREAT | O_EXCL);
4853
4854 semtab_lock();
4855
4856 let mut slot: c_int = -1;
4858 for i in 0..SEMTAB_LEN {
4859 if SEMTAB[i].sem.is_null() && slot < 0 { slot = i as c_int; }
4860 }
4861 if slot < 0 {
4862 ERRNO!() = EMFILE;
4863 semtab_unlock();
4864 return core::ptr::null_mut();
4865 }
4866 SEMTAB[slot as usize].sem = !0usize as *mut sem_t; semtab_unlock();
4869
4870 let mut mode: mode_t = 0;
4872 let mut value: c_uint = 0;
4873 if oflags & O_CREAT != 0 {
4874 mode = args.next_arg::<mode_t>() & 0o666;
4875 value = args.next_arg::<c_uint>();
4876 if value > SEM_VALUE_MAX as c_uint {
4877 ERRNO!() = EINVAL;
4878 semtab_lock();
4879 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4880 semtab_unlock();
4881 return core::ptr::null_mut();
4882 }
4883 }
4884
4885 if oflags != O_CREAT | O_EXCL {
4887 let fd = sys_open(buf.as_ptr(), (O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, 0);
4888 if fd >= 0 {
4889 let map = sys_mmap(
4890 core::ptr::null_mut(),
4891 core::mem::size_of::<sem_t>(),
4892 PROT_READ | PROT_WRITE,
4893 MAP_SHARED,
4894 fd as i32,
4895 0,
4896 );
4897 sys_close(fd);
4898 if map != MMAP_FAILED {
4899 let st_ino = get_ino(fd as c_int, buf.as_ptr());
4900 return sem_register(map as *mut sem_t, st_ino, slot);
4901 }
4902 }
4903 if oflags == 0 {
4904 semtab_lock();
4906 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4907 semtab_unlock();
4908 return core::ptr::null_mut();
4909 }
4910 }
4911
4912 let mut tmp = [0u8; 32];
4914 let tmpname = b"/dev/shm/tmp-XXXXXX\0";
4915 tmp[..tmpname.len()].copy_from_slice(tmpname);
4916 let mut ts: timespec = core::mem::zeroed();
4918 sys_clock_gettime(0, &mut ts);
4919 let mut n = ts.tv_nsec;
4921 let mut pos = tmpname.len() - 1;
4922 tmp[pos] = 0;
4923 pos -= 1;
4924 loop {
4925 tmp[pos] = b'0' + (n % 10) as u8;
4926 n /= 10;
4927 if n == 0 || pos == 0 { break; }
4928 pos -= 1;
4929 }
4930 let tmp_path = tmp.as_ptr();
4932
4933 let mut newsem: sem_t = core::mem::zeroed();
4934 newsem.__val[0] = value as c_int;
4935 newsem.__val[1] = 0;
4936 newsem.__val[2] = 128; loop {
4939 let fd = sys_open(tmp_path as *const u8, (O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC | O_NONBLOCK) as i64, mode as i64);
4940 if fd < 0 {
4941 if (-fd) as c_int == EEXIST { continue; }
4942 semtab_lock();
4943 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4944 semtab_unlock();
4945 return core::ptr::null_mut();
4946 }
4947 let written = sys_write(fd, &newsem as *const sem_t as *const u8, core::mem::size_of::<sem_t>());
4948 if written != core::mem::size_of::<sem_t>() as i64 {
4949 sys_close(fd);
4950 sys_unlink(tmp_path);
4951 semtab_lock();
4952 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4953 semtab_unlock();
4954 return core::ptr::null_mut();
4955 }
4956 let map = sys_mmap(
4957 core::ptr::null_mut(),
4958 core::mem::size_of::<sem_t>(),
4959 PROT_READ | PROT_WRITE,
4960 MAP_SHARED,
4961 fd as i32,
4962 0,
4963 );
4964 sys_close(fd);
4965 if map == MMAP_FAILED {
4966 sys_unlink(tmp_path);
4967 semtab_lock();
4968 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4969 semtab_unlock();
4970 return core::ptr::null_mut();
4971 }
4972 let r = sys_linkat(AT_FDCWD, tmp_path, AT_FDCWD, buf.as_ptr(), 0);
4974 let e = if r < 0 { (-r) as c_int } else { 0 };
4975 sys_unlink(tmp_path);
4976 if e == 0 {
4977 let st_ino = get_ino(-1, buf.as_ptr());
4978 return sem_register(map as *mut sem_t, st_ino, slot);
4979 }
4980 sys_munmap(map, core::mem::size_of::<sem_t>());
4981 if e != EEXIST || oflags == O_CREAT | O_EXCL {
4982 ERRNO!() = e;
4983 semtab_lock();
4984 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4985 semtab_unlock();
4986 return core::ptr::null_mut();
4987 }
4988 break;
4990 }
4991
4992 let fd = sys_open(buf.as_ptr(), (O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, 0);
4994 if fd < 0 {
4995 semtab_lock();
4996 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4997 semtab_unlock();
4998 return core::ptr::null_mut();
4999 }
5000 let map = sys_mmap(
5001 core::ptr::null_mut(),
5002 core::mem::size_of::<sem_t>(),
5003 PROT_READ | PROT_WRITE,
5004 MAP_SHARED,
5005 fd as i32,
5006 0,
5007 );
5008 sys_close(fd);
5009 if map == MMAP_FAILED {
5010 semtab_lock();
5011 SEMTAB[slot as usize].sem = core::ptr::null_mut();
5012 semtab_unlock();
5013 return core::ptr::null_mut();
5014 }
5015 let st_ino = get_ino(-1, buf.as_ptr());
5016 sem_register(map as *mut sem_t, st_ino, slot)
5017}
5018
5019unsafe fn get_ino(_fd_hint: c_int, path: *const u8) -> u64 {
5020 let mut st: Stat = core::mem::zeroed();
5021 if sys_newfstatat(AT_FDCWD, path as *const c_char, &mut st as *mut Stat as *mut u8, 0) == 0 {
5022 st.st_ino
5023 } else {
5024 0
5025 }
5026}
5027
5028unsafe fn sem_register(map: *mut sem_t, ino: u64, slot_hint: c_int) -> *mut sem_t {
5029 semtab_lock();
5030 for i in 0..SEMTAB_LEN {
5032 if SEMTAB[i].ino == ino && !SEMTAB[i].sem.is_null() && SEMTAB[i].sem != !0usize as *mut sem_t {
5033 sys_munmap(map as *mut u8, core::mem::size_of::<sem_t>());
5035 SEMTAB[slot_hint as usize].sem = core::ptr::null_mut();
5036 SEMTAB[i].refcnt += 1;
5037 let ret = SEMTAB[i].sem;
5038 semtab_unlock();
5039 return ret;
5040 }
5041 }
5042 SEMTAB[slot_hint as usize].sem = map;
5044 SEMTAB[slot_hint as usize].ino = ino;
5045 SEMTAB[slot_hint as usize].refcnt = 1;
5046 semtab_unlock();
5047 map
5048}
5049
5050const SEMTAB_LEN: usize = SEM_NSEMS_MAX;
5051
5052#[no_mangle]
5053pub unsafe extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
5054 semtab_lock();
5055 for i in 0..SEMTAB_LEN {
5056 if SEMTAB[i].sem == sem {
5057 SEMTAB[i].refcnt -= 1;
5058 if SEMTAB[i].refcnt == 0 {
5059 SEMTAB[i].sem = core::ptr::null_mut();
5060 SEMTAB[i].ino = 0;
5061 semtab_unlock();
5062 sys_munmap(sem as *mut u8, core::mem::size_of::<sem_t>());
5063 return 0;
5064 }
5065 semtab_unlock();
5066 return 0;
5067 }
5068 }
5069 semtab_unlock();
5070 0
5071}
5072
5073#[no_mangle]
5074pub unsafe extern "C" fn sem_unlink(name: *const c_char) -> c_int {
5075 shm_unlink(name)
5076}
5077
5078#[no_mangle]
5080pub unsafe extern "C" fn pthread_once(control: *mut pthread_once_t, init_routine: Option<unsafe extern "C" fn()>) -> c_int {
5081 if a_load(control) == 2 { return 0; }
5082 loop {
5083 match a_cas(control, 0, 1) {
5084 0 => {
5085 if let Some(f) = init_routine { f(); }
5086 if a_swap(control, 2) == 3 { futex_wake(control, -1); }
5087 return 0;
5088 }
5089 1 => { a_cas(control, 1, 3); }
5090 3 => { futex_wait(control, 3); }
5091 _ => { return 0; }
5092 }
5093 }
5094}
5095
5096#[no_mangle]
5098pub unsafe extern "C" fn pthread_key_create(key: *mut pthread_key_t, dtor: Option<unsafe extern "C" fn(*mut c_void)>) -> c_int {
5099 let start = NEXT_KEY.load(Ordering::Relaxed);
5100 let mut j = start;
5101 loop {
5102 if KEY_DTORS[j].is_none() {
5103 KEY_DTORS[j] = dtor;
5104 NEXT_KEY.store((j + 1) % PTHREAD_KEYS_MAX, Ordering::Relaxed);
5105 *key = j as pthread_key_t;
5106 return 0;
5107 }
5108 j = (j + 1) % PTHREAD_KEYS_MAX;
5109 if j == start { return EAGAIN; }
5110 }
5111}
5112#[no_mangle]
5113pub unsafe extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int {
5114 KEY_DTORS[key as usize] = None;
5115 for i in 0..MAX_THREADS {
5116 if THREADS[i].tid > 0 { THREADS[i].tsd[key as usize] = core::ptr::null_mut(); }
5117 }
5118 0
5119}
5120#[no_mangle]
5121pub unsafe extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void {
5122 if let Some(slot) = find_thread() { slot.tsd[key as usize] } else { core::ptr::null_mut() }
5123}
5124#[no_mangle]
5125pub unsafe extern "C" fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int {
5126 if let Some(slot) = find_thread() {
5127 slot.tsd[key as usize] = value as *mut c_void;
5128 0
5129 } else { EINVAL }
5130}
5131
5132unsafe fn run_cleanup_handlers(slot: &mut Thread) {
5134 let mut cb = slot.cancelbuf;
5135 while !cb.is_null() {
5136 let cur = &*cb;
5137 let f = cur.__f;
5138 let x = cur.__x;
5139 cb = cur.__next;
5140 if let Some(func) = f {
5141 func(x);
5142 }
5143 }
5144 slot.cancelbuf = core::ptr::null_mut();
5145}
5146
5147unsafe fn do_cancel() -> ! {
5148 if let Some(slot) = find_thread() {
5149 run_cleanup_handlers(slot);
5150 slot.result = !0usize as *mut c_void; slot.detach_state = DT_EXITED;
5152 futex_wake(&raw mut slot.detach_state, 1);
5153 }
5154 sys_exit_thread(0);
5155}
5156
5157extern "C" fn cancel_handler(_sig: c_int) {
5158 unsafe {
5159 if let Some(slot) = find_thread() {
5160 if slot.cancel != 0
5164 && slot.cancel_state == PTHREAD_CANCEL_ENABLE
5165 && slot.cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS
5166 {
5167 do_cancel();
5168 }
5169 }
5170 }
5171}
5172
5173static CANCEL_INIT: AtomicI32 = AtomicI32::new(0);
5174
5175unsafe fn ensure_cancel_handler() {
5176 if CANCEL_INIT.swap(1, Ordering::AcqRel) == 0 {
5177 let act = KSigAction {
5178 sa_handler: cancel_handler as *const () as usize,
5179 sa_flags: SA_RESTORER,
5180 sa_restorer: sig_restorer as *const () as usize,
5181 sa_mask: [!0u64],
5182 };
5183 sys_rt_sigaction(SIGCANCEL, &act as *const KSigAction, core::ptr::null_mut(), 8);
5184 }
5185}
5186
5187#[no_mangle]
5188pub unsafe extern "C" fn pthread_cancel(thread: PthreadT) -> c_int {
5189 let slot = thread as *mut Thread;
5190 if slot.is_null() { return EINVAL; }
5191 ensure_cancel_handler();
5192 a_store(&raw mut (*slot).cancel, 1);
5193 let tid = (*slot).tid;
5194 if tid > 0 {
5195 sys_tgkill(sys_getpid() as c_int, tid, SIGCANCEL);
5196 }
5197 0
5198}
5199#[no_mangle]
5200pub unsafe extern "C" fn pthread_setcancelstate(state: c_int, oldstate: *mut c_int) -> c_int {
5201 if state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE { return EINVAL; }
5202 if let Some(slot) = find_thread() {
5203 if !oldstate.is_null() { *oldstate = slot.cancel_state; }
5204 slot.cancel_state = state;
5205 0
5206 } else { EINVAL }
5207}
5208#[no_mangle]
5209pub unsafe extern "C" fn pthread_setcanceltype(type_: c_int, oldtype: *mut c_int) -> c_int {
5210 if type_ != PTHREAD_CANCEL_DEFERRED && type_ != PTHREAD_CANCEL_ASYNCHRONOUS { return EINVAL; }
5211 if let Some(slot) = find_thread() {
5212 if !oldtype.is_null() { *oldtype = slot.cancel_type; }
5213 slot.cancel_type = type_;
5214 0
5215 } else { EINVAL }
5216}
5217#[no_mangle]
5218pub unsafe extern "C" fn pthread_testcancel() {
5219 if let Some(slot) = find_thread() {
5220 if slot.cancel != 0 && slot.cancel_state == PTHREAD_CANCEL_ENABLE {
5221 do_cancel();
5222 }
5223 }
5224}
5225
5226#[no_mangle]
5227pub unsafe extern "C" fn _pthread_cleanup_push(cb: *mut __ptcb, f: Option<unsafe extern "C" fn(*mut c_void)>, x: *mut c_void) {
5228 (*cb).__f = f;
5229 (*cb).__x = x;
5230 if let Some(slot) = find_thread() {
5231 (*cb).__next = slot.cancelbuf;
5232 slot.cancelbuf = cb;
5233 } else {
5234 (*cb).__next = core::ptr::null_mut();
5235 }
5236}
5237
5238#[no_mangle]
5239pub unsafe extern "C" fn _pthread_cleanup_pop(cb: *mut __ptcb, run: c_int) {
5240 if let Some(slot) = find_thread() {
5241 slot.cancelbuf = (*cb).__next;
5242 }
5243 if run != 0 {
5244 if let Some(f) = (*cb).__f {
5245 f((*cb).__x);
5246 }
5247 }
5248}
5249
5250#[no_mangle]
5251pub unsafe extern "C" fn pthread_kill(thread: PthreadT, sig: c_int) -> c_int {
5252 let slot = thread as *mut Thread;
5253 if slot.is_null() { return EINVAL; }
5254 let tid = (*slot).tid;
5255 if tid <= 0 { return EINVAL; }
5256 if sys_tgkill(sys_getpid() as c_int, tid, sig) < 0 { -1 } else { 0 }
5257}
5258
5259#[no_mangle]
5260pub unsafe extern "C" fn pthread_sigmask(how: c_int, set: *const SigSetT, oldset: *mut SigSetT) -> c_int {
5261 sigprocmask(how, set, oldset)
5262}
5263
5264
5265#[repr(C)]
5266pub struct lconv {
5267 pub decimal_point: *mut c_char,
5268 pub thousands_sep: *mut c_char,
5269 pub grouping: *mut c_char,
5270 pub int_curr_symbol: *mut c_char,
5271 pub currency_symbol: *mut c_char,
5272 pub mon_decimal_point: *mut c_char,
5273 pub mon_thousands_sep: *mut c_char,
5274 pub mon_grouping: *mut c_char,
5275 pub positive_sign: *mut c_char,
5276 pub negative_sign: *mut c_char,
5277 pub int_frac_digits: c_char,
5278 pub frac_digits: c_char,
5279 pub p_cs_precedes: c_char,
5280 pub p_sep_by_space: c_char,
5281 pub n_cs_precedes: c_char,
5282 pub n_sep_by_space: c_char,
5283 pub p_sign_posn: c_char,
5284 pub n_sign_posn: c_char,
5285 pub int_p_cs_precedes: c_char,
5286 pub int_p_sep_by_space: c_char,
5287 pub int_n_cs_precedes: c_char,
5288 pub int_n_sep_by_space: c_char,
5289 pub int_p_sign_posn: c_char,
5290 pub int_n_sign_posn: c_char,
5291}
5292
5293static UTF8_NAME: [u8; 6] = [b'U', b'T', b'F', b'-', b'8', 0];
5294static C_NAME: [u8; 2] = [b'C', 0];
5295static mut LOCALE_NAME: *const c_char = C_NAME.as_ptr() as *const c_char;
5296static mut LOCALE_CTYPE_UTF8: bool = true;
5297static mut EMPTY_STR: [c_char; 1] = [0];
5298static mut DECIMAL_POINT: [c_char; 2] = [b'.' as c_char, 0];
5299static mut LCONV: lconv = lconv {
5300 decimal_point: core::ptr::null_mut(),
5301 thousands_sep: core::ptr::null_mut(),
5302 grouping: core::ptr::null_mut(),
5303 int_curr_symbol: core::ptr::null_mut(),
5304 currency_symbol: core::ptr::null_mut(),
5305 mon_decimal_point: core::ptr::null_mut(),
5306 mon_thousands_sep: core::ptr::null_mut(),
5307 mon_grouping: core::ptr::null_mut(),
5308 positive_sign: core::ptr::null_mut(),
5309 negative_sign: core::ptr::null_mut(),
5310 int_frac_digits: (-1i32) as c_char,
5311 frac_digits: (-1i32) as c_char,
5312 p_cs_precedes: (-1i32) as c_char,
5313 p_sep_by_space: (-1i32) as c_char,
5314 n_cs_precedes: (-1i32) as c_char,
5315 n_sep_by_space: (-1i32) as c_char,
5316 p_sign_posn: (-1i32) as c_char,
5317 n_sign_posn: (-1i32) as c_char,
5318 int_p_cs_precedes: (-1i32) as c_char,
5319 int_p_sep_by_space: (-1i32) as c_char,
5320 int_n_cs_precedes: (-1i32) as c_char,
5321 int_n_sep_by_space: (-1i32) as c_char,
5322 int_p_sign_posn: (-1i32) as c_char,
5323 int_n_sign_posn: (-1i32) as c_char,
5324};
5325
5326unsafe fn cstr_contains_ci(s: *const u8, needle: &[u8]) -> bool {
5327 let len = strlen(s as *const c_char) as usize;
5328 let s_slice = core::slice::from_raw_parts(s, len);
5329 if needle.len() > len { return false; }
5330 for i in 0..=len - needle.len() {
5331 if s_slice[i..i + needle.len()].eq_ignore_ascii_case(needle) {
5332 return true;
5333 }
5334 }
5335 false
5336}
5337
5338#[no_mangle]
5339pub unsafe extern "C" fn setlocale(_category: c_int, locale: *const c_char) -> *mut c_char {
5340 if locale.is_null() || *locale == 0 {
5341 return LOCALE_NAME as *mut c_char;
5342 }
5343 let name = locale as *const u8;
5344 if strcmp(name, b"C\0".as_ptr()) == 0 || strcmp(name, b"POSIX\0".as_ptr()) == 0 {
5345 LOCALE_CTYPE_UTF8 = false;
5346 return LOCALE_NAME as *mut c_char;
5347 }
5348 if cstr_contains_ci(name, b"UTF-8") || cstr_contains_ci(name, b"UTF8") {
5349 LOCALE_CTYPE_UTF8 = true;
5350 return LOCALE_NAME as *mut c_char;
5351 }
5352 core::ptr::null_mut()
5353}
5354
5355#[no_mangle]
5356pub unsafe extern "C" fn localeconv() -> *mut lconv {
5357 let empty = core::ptr::addr_of_mut!(EMPTY_STR) as *mut c_char;
5358 let lconv = core::ptr::addr_of_mut!(LCONV);
5359 (*lconv).decimal_point = core::ptr::addr_of_mut!(DECIMAL_POINT) as *mut c_char;
5360 (*lconv).thousands_sep = empty;
5361 (*lconv).grouping = empty;
5362 (*lconv).int_curr_symbol = empty;
5363 (*lconv).currency_symbol = empty;
5364 (*lconv).mon_decimal_point = empty;
5365 (*lconv).mon_thousands_sep = empty;
5366 (*lconv).mon_grouping = empty;
5367 (*lconv).positive_sign = empty;
5368 (*lconv).negative_sign = empty;
5369 lconv
5370}
5371
5372pub type locale_t = *mut c_void;
5373static mut CURRENT_LOCALE: locale_t = LC_GLOBAL_LOCALE;
5374
5375static mut C_LOCALE_STORAGE: c_int = 0;
5376const C_LOCALE: locale_t = core::ptr::addr_of_mut!(C_LOCALE_STORAGE) as locale_t;
5377const LC_GLOBAL_LOCALE: locale_t = usize::MAX as locale_t;
5378
5379#[no_mangle]
5380pub unsafe extern "C" fn newlocale(_mask: c_int, name: *const c_char, base: locale_t) -> locale_t {
5381 if !name.is_null() && *name != 0 {
5382 let n = name as *const u8;
5383 if strcmp(n, b"C\0".as_ptr()) != 0
5384 && strcmp(n, b"POSIX\0".as_ptr()) != 0
5385 {
5386 return core::ptr::null_mut();
5387 }
5388 }
5389 if base.is_null() || base == C_LOCALE || base == LC_GLOBAL_LOCALE {
5390 C_LOCALE
5391 } else {
5392 core::ptr::null_mut()
5393 }
5394}
5395
5396#[no_mangle]
5397pub unsafe extern "C" fn freelocale(_loc: locale_t) {}
5398
5399#[no_mangle]
5400pub unsafe extern "C" fn uselocale(loc: locale_t) -> locale_t {
5401 let old = CURRENT_LOCALE;
5402 if !loc.is_null() {
5403 CURRENT_LOCALE = loc;
5404 }
5405 old
5406}
5407
5408#[no_mangle]
5409pub unsafe extern "C" fn duplocale(loc: locale_t) -> locale_t {
5410 if loc.is_null() {
5411 return core::ptr::null_mut();
5412 }
5413 C_LOCALE
5414}
5415
5416const NL_ITEM_CODESET: c_int = 14;
5417const NL_ITEM_RADIXCHAR: c_int = 0x10000;
5418const NL_ITEM_THOUSEP: c_int = 0x10001;
5419const NL_ITEM_YESEXPR: c_int = 0x50000;
5420const NL_ITEM_NOEXPR: c_int = 0x50001;
5421
5422const C_TIME_STRINGS: &[u8] = b"Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat\0\
5423Sunday\0Monday\0Tuesday\0Wednesday\0Thursday\0Friday\0Saturday\0\
5424Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec\0\
5425January\0February\0March\0April\0May\0June\0July\0August\0\
5426September\0October\0November\0December\0\
5427AM\0PM\0\
5428%a %b %e %T %Y\0%m/%d/%y\0%H:%M:%S\0%I:%M:%S %p\0\
5429\0\0%m/%d/%y\00123456789\0%a %b %e %T %Y\0%H:%M:%S\0";
5430
5431const C_NUMERIC_STRINGS: &[u8] = b".\0\0";
5432const C_MESSAGES_STRINGS: &[u8] = b"^[yY]\0^[nN]\0";
5433
5434unsafe fn langinfo_str(table: *const u8, mut idx: c_int) -> *mut c_char {
5435 let mut p = table;
5436 while idx > 0 {
5437 while *p != 0 { p = p.add(1); }
5438 p = p.add(1);
5439 idx -= 1;
5440 }
5441 p as *mut c_char
5442}
5443
5444#[no_mangle]
5445pub unsafe extern "C" fn nl_langinfo(item: c_int) -> *mut c_char {
5446 if item == NL_ITEM_CODESET {
5447 return if LOCALE_CTYPE_UTF8 {
5448 b"UTF-8\0".as_ptr() as *mut c_char
5449 } else {
5450 b"US-ASCII\0".as_ptr() as *mut c_char
5451 };
5452 }
5453 let cat = item >> 16;
5454 let idx = item & 0xFFFF;
5455 match cat {
5456 1 => {
5457 if idx > 1 { return b"\0".as_ptr() as *mut c_char; }
5458 langinfo_str(C_NUMERIC_STRINGS.as_ptr(), idx)
5459 }
5460 2 => {
5461 if idx > 49 { return b"\0".as_ptr() as *mut c_char; }
5462 langinfo_str(C_TIME_STRINGS.as_ptr(), idx)
5463 }
5464 5 => {
5465 if idx > 1 { return b"\0".as_ptr() as *mut c_char; }
5466 langinfo_str(C_MESSAGES_STRINGS.as_ptr(), idx)
5467 }
5468 _ => b"\0".as_ptr() as *mut c_char,
5469 }
5470}
5471
5472pub type nl_catd = *mut c_void;
5473
5474#[no_mangle]
5475pub unsafe extern "C" fn catopen(_name: *const c_char, _oflag: c_int) -> nl_catd {
5476 !0usize as nl_catd
5477}
5478
5479#[no_mangle]
5480pub unsafe extern "C" fn catclose(_catd: nl_catd) -> c_int { 0 }
5481
5482#[no_mangle]
5483pub unsafe extern "C" fn catgets(catd: nl_catd, _set_id: c_int, _msg_id: c_int, s: *const c_char) -> *mut c_char {
5484 if catd == !0usize as nl_catd { return s as *mut c_char; }
5485 s as *mut c_char
5486}
5487
5488pub type IconvT = *mut c_void;
5489
5490const ENC_UTF8: i32 = 1;
5491const ENC_UTF16LE: i32 = 2;
5492const ENC_UTF16BE: i32 = 3;
5493const ENC_UTF32LE: i32 = 4;
5494const ENC_UTF32BE: i32 = 5;
5495const ENC_WCHAR_T: i32 = 6;
5496const ENC_ASCII: i32 = 7;
5497const ENC_LATIN1: i32 = 8;
5498const ENC_WIN1252: i32 = 9;
5499const ENC_WIN1251: i32 = 10;
5500const ENC_KOI8R: i32 = 11;
5501const ENC_GBK: i32 = 12;
5502const ENC_GB2312: i32 = 13;
5503const ENC_BIG5: i32 = 14;
5504const ENC_EUCJP: i32 = 15;
5505const ENC_SHIFTJIS: i32 = 16;
5506const ENC_ISO8859_2: i32 = 17;
5507const ENC_ISO8859_3: i32 = 18;
5508const ENC_ISO8859_4: i32 = 19;
5509const ENC_ISO8859_5: i32 = 20;
5510const ENC_ISO8859_6: i32 = 21;
5511const ENC_ISO8859_7: i32 = 22;
5512const ENC_ISO8859_8: i32 = 23;
5513const ENC_ISO8859_9: i32 = 24;
5514const ENC_ISO8859_10: i32 = 25;
5515const ENC_ISO8859_11: i32 = 26;
5516const ENC_ISO8859_13: i32 = 27;
5517const ENC_ISO8859_14: i32 = 28;
5518const ENC_ISO8859_15: i32 = 29;
5519const ENC_ISO8859_16: i32 = 30;
5520
5521include!("iconv_iso8859.rs");
5522
5523fn make_cd(from: i32, to: i32) -> IconvT {
5524 ((from as usize) << 16 | (to as usize) << 1 | 1) as IconvT
5525}
5526fn extract_from(cd: IconvT) -> i32 {
5527 ((cd as usize) >> 16) as i32
5528}
5529fn extract_to(cd: IconvT) -> i32 {
5530 (((cd as usize) >> 1) & 0x7fff) as i32
5531}
5532
5533unsafe fn match_name(input: *const u8, target: &[u8]) -> bool {
5534 let mut i = input;
5535 let mut j = 0;
5536 while *i != 0 && j < target.len() {
5537 let mut c = *i;
5538 if !c.is_ascii_alphanumeric() { i = i.add(1); continue; }
5539 c = c.to_ascii_lowercase();
5540 if c != target[j] { return false; }
5541 i = i.add(1);
5542 j += 1;
5543 }
5544 while *i != 0 && !(*i).is_ascii_alphanumeric() { i = i.add(1); }
5545 *i == 0 && j == target.len()
5546}
5547
5548unsafe fn find_encoding(name: *const u8) -> i32 {
5549 if name.is_null() { return -1; }
5550 if match_name(name, b"utf8") || match_name(name, b"utf-8") || match_name(name, b"char") { return ENC_UTF8; }
5551 if match_name(name, b"utf16le") || match_name(name, b"utf-16le") { return ENC_UTF16LE; }
5552 if match_name(name, b"utf16be") || match_name(name, b"utf-16be") { return ENC_UTF16BE; }
5553 if match_name(name, b"utf32le") || match_name(name, b"utf-32le") || match_name(name, b"ucs4le") { return ENC_UTF32LE; }
5554 if match_name(name, b"utf32be") || match_name(name, b"utf-32be") || match_name(name, b"ucs4be") { return ENC_UTF32BE; }
5555 if match_name(name, b"wchart") || match_name(name, b"wchar-t") { return ENC_WCHAR_T; }
5556 if match_name(name, b"ascii") || match_name(name, b"usascii") || match_name(name, b"iso646") { return ENC_ASCII; }
5557 if match_name(name, b"iso88591") || match_name(name, b"iso-8859-1") || match_name(name, b"latin1") { return ENC_LATIN1; }
5558 if match_name(name, b"iso88592") || match_name(name, b"iso-8859-2") { return ENC_ISO8859_2; }
5559 if match_name(name, b"iso88593") || match_name(name, b"iso-8859-3") { return ENC_ISO8859_3; }
5560 if match_name(name, b"iso88594") || match_name(name, b"iso-8859-4") { return ENC_ISO8859_4; }
5561 if match_name(name, b"iso88595") || match_name(name, b"iso-8859-5") { return ENC_ISO8859_5; }
5562 if match_name(name, b"iso88596") || match_name(name, b"iso-8859-6") { return ENC_ISO8859_6; }
5563 if match_name(name, b"iso88597") || match_name(name, b"iso-8859-7") { return ENC_ISO8859_7; }
5564 if match_name(name, b"iso88598") || match_name(name, b"iso-8859-8") { return ENC_ISO8859_8; }
5565 if match_name(name, b"iso88599") || match_name(name, b"iso-8859-9") { return ENC_ISO8859_9; }
5566 if match_name(name, b"iso885910") || match_name(name, b"iso-8859-10") { return ENC_ISO8859_10; }
5567 if match_name(name, b"iso885911") || match_name(name, b"iso-8859-11") || match_name(name, b"tis620") { return ENC_ISO8859_11; }
5568 if match_name(name, b"iso885913") || match_name(name, b"iso-8859-13") { return ENC_ISO8859_13; }
5569 if match_name(name, b"iso885914") || match_name(name, b"iso-8859-14") { return ENC_ISO8859_14; }
5570 if match_name(name, b"iso885915") || match_name(name, b"iso-8859-15") { return ENC_ISO8859_15; }
5571 if match_name(name, b"iso885916") || match_name(name, b"iso-8859-16") { return ENC_ISO8859_16; }
5572 if match_name(name, b"cp1252") || match_name(name, b"windows1252") || match_name(name, b"windows-1252") { return ENC_WIN1252; }
5573 if match_name(name, b"cp1251") || match_name(name, b"windows1251") || match_name(name, b"windows-1251") { return ENC_WIN1251; }
5574 if match_name(name, b"koi8r") || match_name(name, b"koi8-r") { return ENC_KOI8R; }
5575 if match_name(name, b"gbk") || match_name(name, b"cp936") { return ENC_GBK; }
5576 if match_name(name, b"gb2312") { return ENC_GB2312; }
5577 if match_name(name, b"big5") || match_name(name, b"bigfive") || match_name(name, b"cp950") { return ENC_BIG5; }
5578 if match_name(name, b"eucjp") || match_name(name, b"euc-jp") { return ENC_EUCJP; }
5579 if match_name(name, b"shiftjis") || match_name(name, b"sjis") || match_name(name, b"cp932") { return ENC_SHIFTJIS; }
5580 -1
5581}
5582
5583fn uni_to_jis(c: u32) -> u16 {
5584 let mut b = 0usize;
5585 let mut nel = REV_JIS.len();
5586 loop {
5587 let i = nel / 2;
5588 let j = REV_JIS[b + i] as usize;
5589 let row = j / 256;
5590 let col = j % 256;
5591 let d = JIS0208[row * 94 + col] as u32;
5592 if d == c { return (j as u16) + 0x2121; }
5593 if nel == 1 { return 0; }
5594 if c < d { nel /= 2; }
5595 else { b += i; nel -= nel / 2; }
5596 }
5597}
5598
5599unsafe fn iconv_decode(enc: i32, src: *const u8, src_left: usize) -> (u32, usize, c_int) {
5600 if src_left == 0 { return (0, 0, EINVAL); }
5601 match enc {
5602 ENC_UTF8 => {
5603 let c = *src;
5604 if c < 128 { return (c as u32, 1, 0); }
5605 if c < 0xC2 { return (0, 0, EILSEQ); }
5606 if c < 0xE0 {
5607 if src_left < 2 || (*src.add(1) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5608 return (((c as u32 & 0x1F) << 6) | (*src.add(1) as u32 & 0x3F), 2, 0);
5609 }
5610 if c < 0xF0 {
5611 if src_left < 3 || (*src.add(1) & 0xC0) != 0x80 || (*src.add(2) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5612 let cp = ((c as u32 & 0x0F) << 12) | ((*src.add(1) as u32 & 0x3F) << 6) | (*src.add(2) as u32 & 0x3F);
5613 if cp < 0x800 { return (0, 0, EILSEQ); }
5614 return (cp, 3, 0);
5615 }
5616 if c < 0xF8 {
5617 if src_left < 4 || (*src.add(1) & 0xC0) != 0x80 || (*src.add(2) & 0xC0) != 0x80 || (*src.add(3) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5618 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);
5619 if cp < 0x10000 || cp >= 0x110000 { return (0, 0, EILSEQ); }
5620 return (cp, 4, 0);
5621 }
5622 (0, 0, EILSEQ)
5623 }
5624 ENC_UTF16LE => {
5625 if src_left < 2 { return (0, 0, EINVAL); }
5626 let c = (*src as u32) | ((*src.add(1) as u32) << 8);
5627 if c >= 0xD800 && c <= 0xDBFF {
5628 if src_left < 4 { return (0, 0, EINVAL); }
5629 let d = (*src.add(2) as u32) | ((*src.add(3) as u32) << 8);
5630 if d < 0xDC00 || d > 0xDFFF { return (0, 0, EILSEQ); }
5631 return (((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000, 4, 0);
5632 }
5633 if c >= 0xDC00 && c <= 0xDFFF { return (0, 0, EILSEQ); }
5634 (c, 2, 0)
5635 }
5636 ENC_UTF16BE => {
5637 if src_left < 2 { return (0, 0, EINVAL); }
5638 let c = ((*src as u32) << 8) | (*src.add(1) as u32);
5639 if c >= 0xD800 && c <= 0xDBFF {
5640 if src_left < 4 { return (0, 0, EINVAL); }
5641 let d = ((*src.add(2) as u32) << 8) | (*src.add(3) as u32);
5642 if d < 0xDC00 || d > 0xDFFF { return (0, 0, EILSEQ); }
5643 return (((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000, 4, 0);
5644 }
5645 if c >= 0xDC00 && c <= 0xDFFF { return (0, 0, EILSEQ); }
5646 (c, 2, 0)
5647 }
5648 ENC_UTF32LE => {
5649 if src_left < 4 { return (0, 0, EINVAL); }
5650 let c = (*src as u32) | ((*src.add(1) as u32) << 8) | ((*src.add(2) as u32) << 16) | ((*src.add(3) as u32) << 24);
5651 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5652 if c >= 0x110000 { return (0, 0, EILSEQ); }
5653 (c, 4, 0)
5654 }
5655 ENC_UTF32BE => {
5656 if src_left < 4 { return (0, 0, EINVAL); }
5657 let c = ((*src as u32) << 24) | ((*src.add(1) as u32) << 16) | ((*src.add(2) as u32) << 8) | (*src.add(3) as u32);
5658 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5659 if c >= 0x110000 { return (0, 0, EILSEQ); }
5660 (c, 4, 0)
5661 }
5662 ENC_WCHAR_T => {
5663 if src_left < 4 { return (0, 0, EINVAL); }
5664 let c = *(src as *const u32);
5665 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5666 if c >= 0x110000 { return (0, 0, EILSEQ); }
5667 (c, 4, 0)
5668 }
5669 ENC_ASCII => {
5670 let c = *src as u32;
5671 if c >= 128 { return (0, 0, EILSEQ); }
5672 (c, 1, 0)
5673 }
5674 ENC_LATIN1 => (*src as u32, 1, 0),
5675 ENC_ISO8859_2 => (iso8859_to_u(&ISO8859_2_TO_U, *src), 1, 0),
5676 ENC_ISO8859_3 => (iso8859_to_u(&ISO8859_3_TO_U, *src), 1, 0),
5677 ENC_ISO8859_4 => (iso8859_to_u(&ISO8859_4_TO_U, *src), 1, 0),
5678 ENC_ISO8859_5 => (iso8859_to_u(&ISO8859_5_TO_U, *src), 1, 0),
5679 ENC_ISO8859_6 => (iso8859_to_u(&ISO8859_6_TO_U, *src), 1, 0),
5680 ENC_ISO8859_7 => (iso8859_to_u(&ISO8859_7_TO_U, *src), 1, 0),
5681 ENC_ISO8859_8 => (iso8859_to_u(&ISO8859_8_TO_U, *src), 1, 0),
5682 ENC_ISO8859_9 => (iso8859_to_u(&ISO8859_9_TO_U, *src), 1, 0),
5683 ENC_ISO8859_10 => (iso8859_to_u(&ISO8859_10_TO_U, *src), 1, 0),
5684 ENC_ISO8859_11 => (iso8859_to_u(&ISO8859_11_TO_U, *src), 1, 0),
5685 ENC_ISO8859_13 => (iso8859_to_u(&ISO8859_13_TO_U, *src), 1, 0),
5686 ENC_ISO8859_14 => (iso8859_to_u(&ISO8859_14_TO_U, *src), 1, 0),
5687 ENC_ISO8859_15 => (iso8859_to_u(&ISO8859_15_TO_U, *src), 1, 0),
5688 ENC_ISO8859_16 => (iso8859_to_u(&ISO8859_16_TO_U, *src), 1, 0),
5689 ENC_WIN1252 => {
5690 let b = *src;
5691 if b < 128 { return (b as u32, 1, 0); }
5692 (WIN1252_TO_U[b as usize - 128], 1, 0)
5693 }
5694 ENC_WIN1251 => {
5695 let b = *src;
5696 if b < 128 { return (b as u32, 1, 0); }
5697 (WIN1251_TO_U[b as usize - 128], 1, 0)
5698 }
5699 ENC_KOI8R => {
5700 let b = *src;
5701 if b < 128 { return (b as u32, 1, 0); }
5702 (KOI8R_TO_U[b as usize - 128], 1, 0)
5703 }
5704 ENC_GBK | ENC_GB2312 => {
5705 let c = *src;
5706 if c < 128 { return (c as u32, 1, 0); }
5707 if c == 128 { return (0x20AC, 1, 0); }
5708 if src_left < 2 { return (0, 0, EINVAL); }
5709 let d = *src.add(1);
5710 if d < 0x40 || d == 0x7F || d > 0xFE { return (0, 0, EILSEQ); }
5711 let row = (c as usize).wrapping_sub(0x81);
5712 if row >= 126 { return (0, 0, EILSEQ); }
5713 let mut col = (d as usize) - 0x40;
5714 if col > 63 { col -= 1; }
5715 let cp = GB18030_TABLE[row * 190 + col] as u32;
5716 if cp == 0 { return (0, 0, EILSEQ); }
5717 (cp, 2, 0)
5718 }
5719 ENC_BIG5 => {
5720 let c = *src;
5721 if c < 128 { return (c as u32, 1, 0); }
5722 if src_left < 2 { return (0, 0, EINVAL); }
5723 let d = *src.add(1);
5724 if d < 0x40 || d == 0x7F || d > 0xFE { return (0, 0, EILSEQ); }
5725 let mut col = (d as usize) - 0x40;
5726 if col > 0x3E { col -= 0x22; }
5727 if c >= 0xA1 && c < 0xFA {
5728 let row = (c as usize) - 0xA1;
5729 if row >= 89 { return (0, 0, EILSEQ); }
5730 let cp = BIG5_TABLE[row * 157 + col] as u32;
5731 if cp == 0 { return (0, 0, EILSEQ); }
5732 return (cp, 2, 0);
5733 }
5734 (0, 0, EILSEQ)
5735 }
5736 ENC_EUCJP => {
5737 let c = *src;
5738 if c < 128 { return (c as u32, 1, 0); }
5739 if c == 0x8E {
5740 if src_left < 2 { return (0, 0, EINVAL); }
5741 let d = *src.add(1);
5742 if d < 0xA1 || d > 0xDF { return (0, 0, EILSEQ); }
5743 return ((d as u32) + 0xFF61 - 0xA1, 2, 0);
5744 }
5745 if c < 0xA1 { return (0, 0, EILSEQ); }
5746 if src_left < 2 { return (0, 0, EINVAL); }
5747 let d = *src.add(1);
5748 if d < 0xA1 || d > 0xFE { return (0, 0, EILSEQ); }
5749 let row = (c as usize) - 0xA1;
5750 let col = (d as usize) - 0xA1;
5751 if row >= 84 || col >= 94 { return (0, 0, EILSEQ); }
5752 let cp = JIS0208[row * 94 + col] as u32;
5753 if cp == 0 { return (0, 0, EILSEQ); }
5754 (cp, 2, 0)
5755 }
5756 ENC_SHIFTJIS => {
5757 let c = *src;
5758 if c < 128 { return (c as u32, 1, 0); }
5759 if c >= 0xA1 && c <= 0xDF { return ((c as u32) + 0xFF61 - 0xA1, 1, 0); }
5760 if src_left < 2 { return (0, 0, EINVAL); }
5761 let d = *src.add(1);
5762 if d < 0x40 || d == 0x7F || d > 0xFC { return (0, 0, EILSEQ); }
5763 let row = if c >= 129 && c <= 159 { (c as usize) - 129 }
5764 else if c >= 224 && c <= 239 { (c as usize) - 193 }
5765 else { return (0, 0, EILSEQ); };
5766 let (col, row_adj) = if d >= 64 && d <= 158 && d != 127 {
5767 let mut dd = d as usize;
5768 if dd > 127 { dd -= 1; }
5769 (dd - 64, row * 2)
5770 } else if d >= 159 && d <= 252 {
5771 ((d as usize) - 159, row * 2 + 1)
5772 } else {
5773 return (0, 0, EILSEQ);
5774 };
5775 if row_adj >= 84 { return (0, 0, EILSEQ); }
5776 let cp = JIS0208[row_adj * 94 + col] as u32;
5777 if cp == 0 { return (0, 0, EILSEQ); }
5778 (cp, 2, 0)
5779 }
5780 _ => (0, 0, EILSEQ),
5781 }
5782}
5783
5784unsafe fn iconv_encode(enc: i32, c: u32, dst: *mut u8, dst_left: usize) -> (usize, c_int) {
5785 match enc {
5786 ENC_UTF8 => {
5787 if c < 0x80 {
5788 if dst_left < 1 { return (0, E2BIG); }
5789 *dst = c as u8; return (1, 0);
5790 }
5791 if c < 0x800 {
5792 if dst_left < 2 { return (0, E2BIG); }
5793 *dst = (0xC0 | (c >> 6)) as u8;
5794 *dst.add(1) = (0x80 | (c & 0x3F)) as u8;
5795 return (2, 0);
5796 }
5797 if c < 0x10000 {
5798 if dst_left < 3 { return (0, E2BIG); }
5799 *dst = (0xE0 | (c >> 12)) as u8;
5800 *dst.add(1) = (0x80 | ((c >> 6) & 0x3F)) as u8;
5801 *dst.add(2) = (0x80 | (c & 0x3F)) as u8;
5802 return (3, 0);
5803 }
5804 if dst_left < 4 { return (0, E2BIG); }
5805 *dst = (0xF0 | (c >> 18)) as u8;
5806 *dst.add(1) = (0x80 | ((c >> 12) & 0x3F)) as u8;
5807 *dst.add(2) = (0x80 | ((c >> 6) & 0x3F)) as u8;
5808 *dst.add(3) = (0x80 | (c & 0x3F)) as u8;
5809 (4, 0)
5810 }
5811 ENC_UTF16LE => {
5812 if c < 0x10000 {
5813 if dst_left < 2 { return (0, E2BIG); }
5814 *dst = (c & 0xFF) as u8;
5815 *dst.add(1) = (c >> 8) as u8;
5816 return (2, 0);
5817 }
5818 if dst_left < 4 { return (0, E2BIG); }
5819 let c = c - 0x10000;
5820 let hi = ((c >> 10) + 0xD800) as u16;
5821 let lo = ((c & 0x3FF) + 0xDC00) as u16;
5822 *dst = (hi & 0xFF) as u8; *dst.add(1) = (hi >> 8) as u8;
5823 *dst.add(2) = (lo & 0xFF) as u8; *dst.add(3) = (lo >> 8) as u8;
5824 (4, 0)
5825 }
5826 ENC_UTF16BE => {
5827 if c < 0x10000 {
5828 if dst_left < 2 { return (0, E2BIG); }
5829 *dst = (c >> 8) as u8;
5830 *dst.add(1) = (c & 0xFF) as u8;
5831 return (2, 0);
5832 }
5833 if dst_left < 4 { return (0, E2BIG); }
5834 let c = c - 0x10000;
5835 let hi = ((c >> 10) + 0xD800) as u16;
5836 let lo = ((c & 0x3FF) + 0xDC00) as u16;
5837 *dst = (hi >> 8) as u8; *dst.add(1) = (hi & 0xFF) as u8;
5838 *dst.add(2) = (lo >> 8) as u8; *dst.add(3) = (lo & 0xFF) as u8;
5839 (4, 0)
5840 }
5841 ENC_UTF32LE => {
5842 if dst_left < 4 { return (0, E2BIG); }
5843 *dst = (c & 0xFF) as u8; *dst.add(1) = ((c >> 8) & 0xFF) as u8;
5844 *dst.add(2) = ((c >> 16) & 0xFF) as u8; *dst.add(3) = (c >> 24) as u8;
5845 (4, 0)
5846 }
5847 ENC_UTF32BE => {
5848 if dst_left < 4 { return (0, E2BIG); }
5849 *dst = (c >> 24) as u8; *dst.add(1) = ((c >> 16) & 0xFF) as u8;
5850 *dst.add(2) = ((c >> 8) & 0xFF) as u8; *dst.add(3) = (c & 0xFF) as u8;
5851 (4, 0)
5852 }
5853 ENC_WCHAR_T => {
5854 if dst_left < 4 { return (0, E2BIG); }
5855 *(dst as *mut u32) = c;
5856 (4, 0)
5857 }
5858 ENC_ASCII => {
5859 if c < 128 {
5860 if dst_left < 1 { return (0, E2BIG); }
5861 *dst = c as u8; return (1, 0);
5862 }
5863 (0, EILSEQ)
5864 }
5865 ENC_LATIN1 => {
5866 if c < 256 {
5867 if dst_left < 1 { return (0, E2BIG); }
5868 *dst = c as u8; return (1, 0);
5869 }
5870 (0, EILSEQ)
5871 }
5872 ENC_ISO8859_2 => {
5873 if let Some(b) = u_to_iso8859(&ISO8859_2_TO_U, c) {
5874 if dst_left < 1 { return (0, E2BIG); }
5875 *dst = b; return (1, 0);
5876 }
5877 (0, EILSEQ)
5878 }
5879 ENC_ISO8859_3 => {
5880 if let Some(b) = u_to_iso8859(&ISO8859_3_TO_U, c) {
5881 if dst_left < 1 { return (0, E2BIG); }
5882 *dst = b; return (1, 0);
5883 }
5884 (0, EILSEQ)
5885 }
5886 ENC_ISO8859_4 => {
5887 if let Some(b) = u_to_iso8859(&ISO8859_4_TO_U, c) {
5888 if dst_left < 1 { return (0, E2BIG); }
5889 *dst = b; return (1, 0);
5890 }
5891 (0, EILSEQ)
5892 }
5893 ENC_ISO8859_5 => {
5894 if let Some(b) = u_to_iso8859(&ISO8859_5_TO_U, c) {
5895 if dst_left < 1 { return (0, E2BIG); }
5896 *dst = b; return (1, 0);
5897 }
5898 (0, EILSEQ)
5899 }
5900 ENC_ISO8859_6 => {
5901 if let Some(b) = u_to_iso8859(&ISO8859_6_TO_U, c) {
5902 if dst_left < 1 { return (0, E2BIG); }
5903 *dst = b; return (1, 0);
5904 }
5905 (0, EILSEQ)
5906 }
5907 ENC_ISO8859_7 => {
5908 if let Some(b) = u_to_iso8859(&ISO8859_7_TO_U, c) {
5909 if dst_left < 1 { return (0, E2BIG); }
5910 *dst = b; return (1, 0);
5911 }
5912 (0, EILSEQ)
5913 }
5914 ENC_ISO8859_8 => {
5915 if let Some(b) = u_to_iso8859(&ISO8859_8_TO_U, c) {
5916 if dst_left < 1 { return (0, E2BIG); }
5917 *dst = b; return (1, 0);
5918 }
5919 (0, EILSEQ)
5920 }
5921 ENC_ISO8859_9 => {
5922 if let Some(b) = u_to_iso8859(&ISO8859_9_TO_U, c) {
5923 if dst_left < 1 { return (0, E2BIG); }
5924 *dst = b; return (1, 0);
5925 }
5926 (0, EILSEQ)
5927 }
5928 ENC_ISO8859_10 => {
5929 if let Some(b) = u_to_iso8859(&ISO8859_10_TO_U, c) {
5930 if dst_left < 1 { return (0, E2BIG); }
5931 *dst = b; return (1, 0);
5932 }
5933 (0, EILSEQ)
5934 }
5935 ENC_ISO8859_11 => {
5936 if let Some(b) = u_to_iso8859(&ISO8859_11_TO_U, c) {
5937 if dst_left < 1 { return (0, E2BIG); }
5938 *dst = b; return (1, 0);
5939 }
5940 (0, EILSEQ)
5941 }
5942 ENC_ISO8859_13 => {
5943 if let Some(b) = u_to_iso8859(&ISO8859_13_TO_U, c) {
5944 if dst_left < 1 { return (0, E2BIG); }
5945 *dst = b; return (1, 0);
5946 }
5947 (0, EILSEQ)
5948 }
5949 ENC_ISO8859_14 => {
5950 if let Some(b) = u_to_iso8859(&ISO8859_14_TO_U, c) {
5951 if dst_left < 1 { return (0, E2BIG); }
5952 *dst = b; return (1, 0);
5953 }
5954 (0, EILSEQ)
5955 }
5956 ENC_ISO8859_15 => {
5957 if let Some(b) = u_to_iso8859(&ISO8859_15_TO_U, c) {
5958 if dst_left < 1 { return (0, E2BIG); }
5959 *dst = b; return (1, 0);
5960 }
5961 (0, EILSEQ)
5962 }
5963 ENC_ISO8859_16 => {
5964 if let Some(b) = u_to_iso8859(&ISO8859_16_TO_U, c) {
5965 if dst_left < 1 { return (0, E2BIG); }
5966 *dst = b; return (1, 0);
5967 }
5968 (0, EILSEQ)
5969 }
5970 ENC_WIN1252 => {
5971 if c < 128 {
5972 if dst_left < 1 { return (0, E2BIG); }
5973 *dst = c as u8; return (1, 0);
5974 }
5975 if c >= 0xA0 && c <= 0xFF && WIN1252_TO_U[c as usize - 128] == c {
5976 if dst_left < 1 { return (0, E2BIG); }
5977 *dst = c as u8; return (1, 0);
5978 }
5979 for i in 0..128usize {
5980 if WIN1252_TO_U[i] == c {
5981 if dst_left < 1 { return (0, E2BIG); }
5982 *dst = (i + 128) as u8; return (1, 0);
5983 }
5984 }
5985 (0, EILSEQ)
5986 }
5987 ENC_WIN1251 => {
5988 if c < 128 {
5989 if dst_left < 1 { return (0, E2BIG); }
5990 *dst = c as u8; return (1, 0);
5991 }
5992 for i in 0..128usize {
5993 if WIN1251_TO_U[i] == c {
5994 if dst_left < 1 { return (0, E2BIG); }
5995 *dst = (i + 128) as u8; return (1, 0);
5996 }
5997 }
5998 (0, EILSEQ)
5999 }
6000 ENC_KOI8R => {
6001 if c < 128 {
6002 if dst_left < 1 { return (0, E2BIG); }
6003 *dst = c as u8; return (1, 0);
6004 }
6005 for i in 0..128usize {
6006 if KOI8R_TO_U[i] == c {
6007 if dst_left < 1 { return (0, E2BIG); }
6008 *dst = (i + 128) as u8; return (1, 0);
6009 }
6010 }
6011 (0, EILSEQ)
6012 }
6013 ENC_GBK | ENC_GB2312 => {
6014 if c < 128 {
6015 if dst_left < 1 { return (0, E2BIG); }
6016 *dst = c as u8; return (1, 0);
6017 }
6018 if c == 0x20AC {
6019 if dst_left < 1 { return (0, E2BIG); }
6020 *dst = 128; return (1, 0);
6021 }
6022 for row in 0..126usize {
6023 for col in 0..190usize {
6024 if GB18030_TABLE[row * 190 + col] as u32 == c {
6025 if dst_left < 2 { return (0, E2BIG); }
6026 *dst = (row + 0x81) as u8;
6027 *dst.add(1) = if col <= 62 { (col + 0x40) as u8 } else { (col + 0x41) as u8 };
6028 return (2, 0);
6029 }
6030 }
6031 }
6032 (0, EILSEQ)
6033 }
6034 ENC_BIG5 => {
6035 if c < 128 {
6036 if dst_left < 1 { return (0, E2BIG); }
6037 *dst = c as u8; return (1, 0);
6038 }
6039 for row in 0..89usize {
6040 for col in 0..157usize {
6041 if BIG5_TABLE[row * 157 + col] as u32 == c {
6042 if dst_left < 2 { return (0, E2BIG); }
6043 *dst = (row + 0xA1) as u8;
6044 *dst.add(1) = if col <= 0x3E { (col + 0x40) as u8 } else { (col + 0x62) as u8 };
6045 return (2, 0);
6046 }
6047 }
6048 }
6049 (0, EILSEQ)
6050 }
6051 ENC_EUCJP => {
6052 if c < 128 {
6053 if dst_left < 1 { return (0, E2BIG); }
6054 *dst = c as u8; return (1, 0);
6055 }
6056 if c >= 0xFF61 && c <= 0xFF9F {
6057 if dst_left < 2 { return (0, E2BIG); }
6058 *dst = 0x8E;
6059 *dst.add(1) = (c - 0xFF61 + 0xA1) as u8;
6060 return (2, 0);
6061 }
6062 let jis = uni_to_jis(c);
6063 if jis == 0 { return (0, EILSEQ); }
6064 if dst_left < 2 { return (0, E2BIG); }
6065 *dst = ((jis >> 8) as u8).wrapping_add(0x80);
6066 *dst.add(1) = ((jis & 0xFF) as u8).wrapping_add(0x80);
6067 (2, 0)
6068 }
6069 ENC_SHIFTJIS => {
6070 if c < 128 {
6071 if dst_left < 1 { return (0, E2BIG); }
6072 *dst = c as u8; return (1, 0);
6073 }
6074 if c >= 0xFF61 && c <= 0xFF9F {
6075 if dst_left < 1 { return (0, E2BIG); }
6076 *dst = (c - 0xFF61 + 0xA1) as u8;
6077 return (1, 0);
6078 }
6079 let jis = uni_to_jis(c);
6080 if jis == 0 { return (0, EILSEQ); }
6081 if dst_left < 2 { return (0, E2BIG); }
6082 let r = (jis >> 8) as usize;
6083 let d = (jis & 0xFF) as usize;
6084 *dst = ((r + 1) / 2 + if r < 95 { 112 } else { 176 }) as u8;
6085 *dst.add(1) = if r % 2 == 1 { (d + 31 + d / 96) as u8 } else { (d + 126) as u8 };
6086 (2, 0)
6087 }
6088 _ => (0, EILSEQ),
6089 }
6090}
6091
6092#[no_mangle]
6093pub unsafe extern "C" fn iconv_open(tocode: *const c_char, fromcode: *const c_char) -> IconvT {
6094 let to = find_encoding(tocode as *const u8);
6095 let from = find_encoding(fromcode as *const u8);
6096 if to < 0 || from < 0 {
6097 ERRNO!() = EINVAL;
6098 return !0usize as IconvT;
6099 }
6100 make_cd(from, to)
6101}
6102
6103#[no_mangle]
6104pub unsafe extern "C" fn iconv(
6105 cd: IconvT,
6106 inbuf: *mut *mut c_char,
6107 inbytesleft: *mut SizeT,
6108 outbuf: *mut *mut c_char,
6109 outbytesleft: *mut SizeT,
6110) -> SizeT {
6111 if cd == !0usize as IconvT {
6112 ERRNO!() = EINVAL;
6113 return !0usize;
6114 }
6115 if inbuf.is_null() || outbuf.is_null() { return 0; }
6116 let from = extract_from(cd);
6117 let to = extract_to(cd);
6118 let mut src = *inbuf as *const u8;
6119 let mut dst = *outbuf as *mut u8;
6120 let mut src_left = *inbytesleft;
6121 let mut dst_left = *outbytesleft;
6122 let mut subst = 0usize;
6123 while src_left > 0 {
6124 let (cp, consumed, err) = iconv_decode(from, src, src_left);
6125 if err != 0 {
6126 if err == EINVAL { break; }
6127 ERRNO!() = err;
6128 return !0usize;
6129 }
6130 let (written, err) = iconv_encode(to, cp, dst, dst_left);
6131 if err != 0 {
6132 if err == E2BIG {
6133 ERRNO!() = E2BIG;
6134 return !0usize;
6135 }
6136 if dst_left < 1 {
6137 ERRNO!() = E2BIG;
6138 return !0usize;
6139 }
6140 *dst = b'*';
6141 dst = dst.add(1);
6142 dst_left -= 1;
6143 subst += 1;
6144 } else {
6145 dst = dst.add(written);
6146 dst_left -= written;
6147 }
6148 src = src.add(consumed);
6149 src_left -= consumed;
6150 }
6151 *inbuf = src as *mut c_char;
6152 *outbuf = dst as *mut c_char;
6153 *inbytesleft = src_left;
6154 *outbytesleft = dst_left;
6155 subst
6156}
6157
6158#[no_mangle]
6159pub unsafe extern "C" fn iconv_close(_cd: IconvT) -> c_int { 0 }
6160
6161#[no_mangle]
6166pub unsafe extern "C" fn write(fd: c_int, buf: *const c_void, count: SizeT) -> SSizeT {
6167 syscall_ret(sys_write(fd as i64, buf as *const u8, count)) as SSizeT
6168}
6169
6170#[no_mangle]
6171pub unsafe extern "C" fn read(fd: c_int, buf: *mut c_void, count: SizeT) -> SSizeT {
6172 syscall_ret(sys_read(fd as i64, buf as *mut u8, count)) as SSizeT
6173}
6174
6175#[no_mangle]
6176pub unsafe extern "C" fn open(path: *const c_char, flags: c_int, mode: c_int) -> c_int {
6177 syscall_ret(sys_open(path as *const u8, flags as i64, mode as i64)) as c_int
6178}
6179
6180#[no_mangle]
6181pub unsafe extern "C" fn close(fd: c_int) -> c_int {
6182 syscall_ret(sys_close(fd as i64)) as c_int
6183}
6184
6185#[no_mangle]
6186pub unsafe extern "C" fn lseek(fd: c_int, offset: i64, whence: c_int) -> i64 {
6187 syscall_ret(sys_lseek(fd as i64, offset, whence as i64))
6188}
6189
6190const O_RDONLY: i32 = 0;
6195const O_WRONLY: i32 = 1;
6196const O_RDWR: i32 = 2;
6197const O_CREAT: i32 = 64;
6198const O_TRUNC: i32 = 512;
6199const O_APPEND: i32 = 1024;
6200const O_EXCL: i32 = 128;
6201const O_NONBLOCK: i32 = 2048;
6202const O_NOFOLLOW: i32 = if cfg!(target_arch = "aarch64") { 0o100000 } else { 0o400000 };
6203const O_DIRECTORY: i32 = if cfg!(target_arch = "aarch64") { 0o40000 } else { 0o200000 };
6204const O_CLOEXEC: i32 = 0x80000;
6205
6206const F_GETFD: i32 = 1;
6207const F_SETFD: i32 = 2;
6208const F_GETFL: i32 = 3;
6209const F_SETFL: i32 = 4;
6210const F_GETLK: i32 = 5;
6211const F_SETLK: i32 = 6;
6212const F_SETLKW: i32 = 7;
6213const F_DUPFD: i32 = 0;
6214const F_DUPFD_CLOEXEC: i32 = 1030;
6215const FD_CLOEXEC: i32 = 1;
6216
6217const TIOCGWINSZ: u32 = 0x5413;
6218
6219#[repr(C)]
6220struct winsize {
6221 ws_row: u16,
6222 ws_col: u16,
6223 ws_xpixel: u16,
6224 ws_ypixel: u16,
6225}
6226
6227#[inline]
6228unsafe fn sys_pipe2(fds: *mut c_int, flags: i32) -> i64 {
6229 <Arch as Syscalls>::syscall2(SYS_PIPE2, fds as i64, flags as i64)
6230}
6231
6232#[inline]
6233unsafe fn sys_dup3(oldfd: i32, newfd: i32, flags: i32) -> i64 {
6234 <Arch as Syscalls>::syscall3(SYS_DUP3, oldfd as i64, newfd as i64, flags as i64)
6235}
6236
6237#[inline]
6238unsafe fn sys_fcntl(fd: i32, cmd: i32, arg: i64) -> i64 {
6239 <Arch as Syscalls>::syscall3(SYS_FCNTL, fd as i64, cmd as i64, arg as i64)
6240}
6241
6242#[inline]
6243unsafe fn sys_ioctl(fd: c_int, request: u32, arg: *mut u8) -> i64 {
6244 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, request as i64, arg as i64)
6245}
6246
6247#[inline]
6248unsafe fn sys_unlinkat(dirfd: i32, path: *const u8, flags: i32) -> i64 {
6249 <Arch as Syscalls>::syscall3(SYS_UNLINKAT, dirfd as i64, path as i64, flags as i64)
6250}
6251
6252#[inline]
6253unsafe fn sys_renameat2(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: u32) -> i64 {
6254 <Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
6255}
6256
6257const UNGET: usize = 8;
6262const F_PERM: u32 = 1;
6263const F_NORD: u32 = 4;
6264const F_NOWR: u32 = 8;
6265const F_EOF: u32 = 16;
6266const F_ERR: u32 = 32;
6267const F_SVB: u32 = 64;
6268const F_APP: u32 = 128;
6269
6270const BUFSIZ: usize = 1024;
6271
6272const _IOFBF: c_int = 0;
6273const _IOLBF: c_int = 1;
6274const _IONBF: c_int = 2;
6275
6276const SEEK_SET: c_int = 0;
6277const SEEK_CUR: c_int = 1;
6278const SEEK_END: c_int = 2;
6279
6280#[repr(C)]
6282pub struct FILE {
6283 flags: c_uint,
6284 rpos: *mut u8,
6285 rend: *mut u8,
6286 close: Option<unsafe extern "C" fn(*mut FILE) -> c_int>,
6287 wend: *mut u8,
6288 wpos: *mut u8,
6289 mustbezero_1: *mut u8,
6290 wbase: *mut u8,
6291 read_fn: Option<unsafe extern "C" fn(*mut FILE, *mut u8, usize) -> usize>,
6292 write_fn: Option<unsafe extern "C" fn(*mut FILE, *const u8, usize) -> usize>,
6293 seek_fn: Option<unsafe extern "C" fn(*mut FILE, i64, c_int) -> i64>,
6294 buf: *mut u8,
6295 buf_size: usize,
6296 prev: *mut FILE,
6297 next: *mut FILE,
6298 fd: c_int,
6299 pipe_pid: c_int,
6300 lockcount: c_long,
6301 mode: c_int,
6302 lock: c_int,
6303 lbf: c_int,
6304 cookie: *mut c_void,
6305 off: i64,
6306 getln_buf: *mut c_char,
6307 mustbezero_2: *mut c_void,
6308 shend: *mut u8,
6309 shlim: i64,
6310 shcnt: i64,
6311 ungotten: [c_int; UNGET],
6312 ungotten_count: c_int,
6313 _eof: c_int,
6314 _err: c_int,
6315}
6316
6317static mut STDIN_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6318static mut STDOUT_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6319static mut STDERR_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6320
6321static mut STDIN_FILE: FILE = FILE {
6322 flags: 0, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6323 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6324 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6325 read_fn: None, write_fn: None, seek_fn: None,
6326 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6327 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6328 fd: 0, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6329 cookie: core::ptr::null_mut(), off: 0,
6330 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6331 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6332 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6333};
6334static mut STDOUT_FILE: FILE = FILE {
6335 flags: F_NOWR as u32 + F_SVB as u32, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6336 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6337 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6338 read_fn: None, write_fn: None, seek_fn: None,
6339 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6340 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6341 fd: 1, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6342 cookie: core::ptr::null_mut(), off: 0,
6343 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6344 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6345 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6346};
6347static mut STDERR_FILE: FILE = FILE {
6348 flags: F_NOWR as u32, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6349 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6350 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6351 read_fn: None, write_fn: None, seek_fn: None,
6352 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6353 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6354 fd: 2, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6355 cookie: core::ptr::null_mut(), off: 0,
6356 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6357 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6358 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6359};
6360
6361#[no_mangle]
6362pub static mut stdin: *mut FILE = &raw mut STDIN_FILE as *mut FILE;
6363#[no_mangle]
6364pub static mut stdout: *mut FILE = &raw mut STDOUT_FILE as *mut FILE;
6365#[no_mangle]
6366pub static mut stderr: *mut FILE = &raw mut STDERR_FILE as *mut FILE;
6367
6368unsafe fn __stdio_init() {
6373 STDIN_FILE.buf = core::ptr::addr_of_mut!(STDIN_BUF) as *mut u8;
6374 STDIN_FILE.buf_size = BUFSIZ;
6375 STDIN_FILE.read_fn = Some(__stdio_read);
6376 STDIN_FILE.write_fn = Some(__stdio_write);
6377 STDIN_FILE.seek_fn = Some(__stdio_seek);
6378 STDOUT_FILE.buf = core::ptr::addr_of_mut!(STDOUT_BUF) as *mut u8;
6379 STDOUT_FILE.buf_size = BUFSIZ;
6380 STDOUT_FILE.lbf = b'\n' as c_int;
6381 STDOUT_FILE.read_fn = Some(__stdio_read);
6382 STDOUT_FILE.write_fn = Some(__stdio_write);
6383 STDOUT_FILE.seek_fn = Some(__stdio_seek);
6384 STDERR_FILE.buf = core::ptr::addr_of_mut!(STDERR_BUF) as *mut u8;
6385 STDERR_FILE.buf_size = BUFSIZ;
6386 STDERR_FILE.read_fn = Some(__stdio_read);
6387 STDERR_FILE.write_fn = Some(__stdio_write);
6388 STDERR_FILE.seek_fn = Some(__stdio_seek);
6389}
6390
6391unsafe fn buf_ptr(f: *mut FILE) -> *mut u8 {
6392 (f as *mut u8).add(core::mem::size_of::<FILE>())
6393}
6394
6395unsafe extern "C" fn __stdio_read(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
6396 let n = sys_read((*f).fd as i64, buf, len);
6397 if n <= 0 {
6398 if n == 0 { (*f).flags |= F_EOF; } else { (*f).flags |= F_ERR; (*f)._err = 1; }
6399 return 0;
6400 }
6401 n as usize
6402}
6403
6404unsafe extern "C" fn __stdio_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
6405 let l = (*f).wpos as usize - (*f).wbase as usize;
6406 let mut iov = [
6407 ((*f).wbase as *const u8, l),
6408 (buf, len),
6409 ];
6410 if iov[0].1 == 0 { iov = [iov[1], (core::ptr::null(), 0)]; }
6411 if (*f).flags & F_APP != 0 {
6412 let _ = sys_lseek((*f).fd as i64, 0, SEEK_END as i64);
6413 }
6414 let mut rem = iov[0].1 + iov[1].1;
6415 let mut idx = 0usize;
6416 while rem > 0 {
6417 let ptr = iov[idx].0;
6418 let cnt = iov[idx].1;
6419 if cnt == 0 { idx += 1; continue; }
6420 let n = sys_write((*f).fd as i64, ptr, cnt);
6421 if n <= 0 {
6422 (*f).wpos = core::ptr::null_mut();
6423 (*f).wbase = core::ptr::null_mut();
6424 (*f).wend = core::ptr::null_mut();
6425 (*f).flags |= F_ERR;
6426 return if iov[idx].0 == buf { 0 } else { len };
6427 }
6428 rem -= n as usize;
6429 iov[idx].0 = iov[idx].0.add(n as usize);
6430 iov[idx].1 -= n as usize;
6431 if iov[idx].1 == 0 { idx += 1; }
6432 }
6433 (*f).wend = (*f).buf.add((*f).buf_size);
6434 (*f).wbase = (*f).buf;
6435 (*f).wpos = (*f).buf;
6436 len
6437}
6438
6439unsafe extern "C" fn __stdio_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
6440 sys_lseek((*f).fd as i64, off, whence as i64)
6441}
6442
6443unsafe fn init_file(
6444 f: *mut FILE,
6445 fd: c_int,
6446 mode: *const c_char,
6447 close_fn: Option<unsafe extern "C" fn(*mut FILE) -> c_int>,
6448 buf_area: *mut u8,
6449 buf_sz: usize,
6450) {
6451 core::ptr::write_bytes(f as *mut u8, 0, core::mem::size_of::<FILE>());
6452 (*f).fd = fd;
6453 (*f).close = close_fn;
6454 (*f).lock = 0;
6455 (*f).lbf = -1;
6456 (*f).buf = buf_area;
6457 (*f).buf_size = buf_sz;
6458 (*f).read_fn = Some(__stdio_read);
6459 (*f).write_fn = Some(__stdio_write);
6460 (*f).seek_fn = Some(__stdio_seek);
6461 let m = *mode;
6462 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
6463 if m == b'r' as c_char && !has_plus {
6464 (*f).flags = F_NORD;
6465 } else if !has_plus {
6466 (*f).flags = F_NOWR;
6467 }
6468}
6469
6470unsafe extern "C" fn __stdio_close(f: *mut FILE) -> c_int {
6471 sys_close((*f).fd as i64);
6472 0
6473}
6474
6475unsafe fn fmodeflags(mode: *const c_char) -> c_int {
6476 let mut flags: c_int;
6477 let m = *mode;
6478 if !strchr(mode as *const u8, b'+' as c_int).is_null() {
6479 flags = O_RDWR;
6480 } else if m == b'r' as c_char {
6481 flags = O_RDONLY;
6482 } else {
6483 flags = O_WRONLY;
6484 }
6485 if !strchr(mode as *const u8, b'x' as c_int).is_null() { flags |= O_EXCL; }
6486 if !strchr(mode as *const u8, b'e' as c_int).is_null() { flags |= O_CLOEXEC; }
6487 if m != b'r' as c_char { flags |= O_CREAT; }
6488 if m == b'w' as c_char { flags |= O_TRUNC; }
6489 if m == b'a' as c_char { flags |= O_APPEND; }
6490 flags
6491}
6492
6493const O_ACCMODE: c_int = O_RDONLY | O_WRONLY | O_RDWR;
6494
6495unsafe fn flush_buf(f: *mut FILE) -> c_int {
6496 if (*f).wpos == (*f).wbase {
6497 if !(*f).wpos.is_null() {
6498 (*f).wend = (*f).buf.add((*f).buf_size);
6499 (*f).wpos = (*f).wbase;
6500 }
6501 return 0;
6502 }
6503 if let Some(wfunc) = (*f).write_fn {
6504 let ret = wfunc(f, core::ptr::null(), 0);
6505 if ret == 0 && (*f).wpos.is_null() { return -1; }
6506 return 0;
6507 }
6508 (*f).flags |= F_ERR;
6509 -1
6510}
6511
6512#[no_mangle]
6517pub unsafe extern "C" fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE {
6518 if filename.is_null() || mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
6519 let m = *mode;
6520 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
6521 ERRNO!() = EINVAL; return core::ptr::null_mut();
6522 }
6523 let flags = fmodeflags(mode);
6524 let fd = sys_open(filename as *const u8, flags as i64, 0o666);
6525 if fd < 0 { ERRNO!() = (-fd) as c_int; return core::ptr::null_mut(); }
6526 fdopen(fd as c_int, mode)
6527}
6528
6529#[no_mangle]
6530pub unsafe extern "C" fn fdopen(fd: c_int, mode: *const c_char) -> *mut FILE {
6531 if fd < 0 || mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
6532 let m = *mode;
6533 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
6534 ERRNO!() = EINVAL; return core::ptr::null_mut();
6535 }
6536 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
6537 if f.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
6538 let buf = buf_ptr(f);
6539 init_file(f, fd, mode, Some(__stdio_close), buf, BUFSIZ);
6540 if !strchr(mode as *const u8, b'a' as c_int).is_null() { (*f).flags |= F_APP; }
6541 if !strchr(mode as *const u8, b'e' as c_int).is_null() { sys_fcntl(fd, F_SETFD, FD_CLOEXEC as i64); }
6542 if (*f).flags & F_NOWR == 0 {
6543 let mut ws: winsize = core::mem::zeroed();
6544 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 {
6545 (*f).lbf = b'\n' as c_int;
6546 }
6547 }
6548 f
6549}
6550
6551#[no_mangle]
6552pub unsafe extern "C" fn freopen(
6553 filename: *const c_char, mode: *const c_char, f: *mut FILE,
6554) -> *mut FILE {
6555 fflush(f);
6556 if (*f).pipe_pid > 0 { let _ = __stdio_close(f); }
6557 if filename.is_null() {
6558 let flags = fmodeflags(mode);
6559 if flags == 0 { return core::ptr::null_mut(); }
6560 let mut fl = flags & !(O_CREAT | O_EXCL | O_CLOEXEC);
6561 if (*f).flags & F_APP != 0 { fl = (fl & !O_ACCMODE) | O_WRONLY | O_APPEND; }
6562 if sys_fcntl((*f).fd, F_SETFL, fl as i64) < 0 { return core::ptr::null_mut(); }
6563 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
6564 if has_plus {
6565 (*f).flags &= !(F_NORD | F_NOWR);
6566 } else if *mode == b'r' as c_char {
6567 (*f).flags = ((*f).flags & !F_NOWR) | F_NORD;
6568 } else {
6569 (*f).flags = ((*f).flags & !F_NORD) | F_NOWR;
6570 }
6571 return f;
6572 }
6573 let new_f = fopen(filename, mode);
6574 if new_f.is_null() { let _ = __stdio_close(f); return core::ptr::null_mut(); }
6575 if (*new_f).fd == (*f).fd {
6576 (*new_f).fd = -1;
6577 } else {
6578 sys_dup3((*new_f).fd, (*f).fd, 0);
6579 let _ = __stdio_close(new_f);
6580 }
6581 (*f).flags = (*new_f).flags;
6582 (*f).rpos = core::ptr::null_mut();
6583 (*f).rend = core::ptr::null_mut();
6584 (*f).wpos = core::ptr::null_mut();
6585 (*f).wbase = core::ptr::null_mut();
6586 (*f).wend = core::ptr::null_mut();
6587 (*f).lbf = (*new_f).lbf;
6588 (*f).pipe_pid = 0;
6589 free(new_f as *mut c_void);
6590 f
6591}
6592
6593#[no_mangle]
6594pub unsafe extern "C" fn fclose(f: *mut FILE) -> c_int {
6595 if f.is_null() { return -1; }
6596 let r = fflush(f);
6597 if let Some(close_fn) = (*f).close { let _ = close_fn(f); }
6598 if r != 0 { -1 } else { 0 }
6599}
6600
6601#[no_mangle]
6606pub unsafe extern "C" fn setvbuf(f: *mut FILE, buf: *mut c_char, mode: c_int, size: usize) -> c_int {
6607 if mode != _IOFBF && mode != _IOLBF && mode != _IONBF { return -1; }
6608 fflush(f);
6609 (*f).rpos = core::ptr::null_mut();
6610 (*f).rend = core::ptr::null_mut();
6611 (*f).wpos = core::ptr::null_mut();
6612 (*f).wbase = core::ptr::null_mut();
6613 (*f).wend = core::ptr::null_mut();
6614 if mode == _IONBF {
6615 (*f).buf_size = 0;
6616 } else if !buf.is_null() && size > 0 {
6617 (*f).buf = buf as *mut u8;
6618 (*f).buf_size = size;
6619 }
6620 (*f).lbf = if mode == _IOLBF { b'\n' as c_int } else { -1 };
6621 0
6622}
6623
6624#[no_mangle]
6625pub unsafe extern "C" fn setbuf(f: *mut FILE, buf: *mut c_char) {
6626 if buf.is_null() { setvbuf(f, core::ptr::null_mut(), _IONBF, 0); }
6627 else { setvbuf(f, buf, _IOFBF, BUFSIZ); }
6628}
6629
6630#[no_mangle]
6631pub unsafe extern "C" fn setbuffer(f: *mut FILE, buf: *mut c_char, size: usize) {
6632 if buf.is_null() { setvbuf(f, core::ptr::null_mut(), _IONBF, 0); }
6633 else { setvbuf(f, buf, _IOFBF, size); }
6634}
6635
6636#[no_mangle]
6637pub unsafe extern "C" fn fflush(f: *mut FILE) -> c_int {
6638 if f.is_null() {
6639 let mut r = 0;
6640 if !stdout.is_null() && !(*stdout).wpos.is_null() && (*stdout).wpos != (*stdout).wbase {
6641 if flush_buf(stdout) != 0 { r = -1; }
6642 }
6643 if !stderr.is_null() && !(*stderr).wpos.is_null() && (*stderr).wpos != (*stderr).wbase {
6644 if flush_buf(stderr) != 0 { r = -1; }
6645 }
6646 return r;
6647 }
6648 if !(*f).wpos.is_null() && (*f).wpos != (*f).wbase {
6649 return flush_buf(f);
6650 }
6651 0
6652}
6653
6654#[no_mangle]
6659pub unsafe extern "C" fn fwide(_f: *mut FILE, mode: c_int) -> c_int { mode }
6660
6661#[no_mangle]
6662pub unsafe extern "C" fn feof(f: *mut FILE) -> c_int { if (*f)._eof != 0 { 1 } else { 0 } }
6663
6664#[no_mangle]
6665pub unsafe extern "C" fn ferror(f: *mut FILE) -> c_int { if (*f)._err != 0 { 1 } else { 0 } }
6666
6667#[no_mangle]
6668pub unsafe extern "C" fn clearerr(f: *mut FILE) { (*f)._eof = 0; (*f)._err = 0; }
6669
6670#[no_mangle]
6671pub unsafe extern "C" fn fileno(f: *mut FILE) -> c_int { (*f).fd }
6672
6673#[no_mangle]
6678pub unsafe extern "C" fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int {
6679 fseeko(stream, offset as i64, whence)
6680}
6681
6682#[no_mangle]
6683pub unsafe extern "C" fn ftell(stream: *mut FILE) -> c_long {
6684 ftello(stream) as c_long
6685}
6686
6687#[no_mangle]
6688pub unsafe extern "C" fn rewind(stream: *mut FILE) {
6689 fseek(stream, 0, SEEK_SET);
6690 (*stream)._eof = 0;
6691 (*stream)._err = 0;
6692}
6693
6694#[no_mangle]
6695pub unsafe extern "C" fn fseeko(stream: *mut FILE, offset: i64, whence: c_int) -> c_int {
6696 if whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END {
6697 ERRNO!() = EINVAL;
6698 return -1;
6699 }
6700 let f = &mut *stream;
6701 let mut adj_offset = offset;
6702 if whence == SEEK_CUR {
6703 if !f.rpos.is_null() {
6704 adj_offset -= f.rend as i64 - f.rpos as i64;
6705 }
6706 adj_offset -= f.ungotten_count as i64;
6707 }
6708 if !f.wpos.is_null() && f.wpos != f.wbase {
6709 if flush_buf(stream) != 0 { return -1; }
6710 }
6711 f.wpos = core::ptr::null_mut();
6712 f.wbase = core::ptr::null_mut();
6713 f.wend = core::ptr::null_mut();
6714 if let Some(sfunc) = f.seek_fn {
6715 let r = sfunc(stream, adj_offset, whence);
6716 if r < 0 { return -1; }
6717 } else {
6718 ERRNO!() = EINVAL;
6719 return -1;
6720 }
6721 f.rpos = core::ptr::null_mut();
6722 f.rend = core::ptr::null_mut();
6723 f._eof = 0;
6724 f.ungotten_count = 0;
6725 0
6726}
6727
6728#[no_mangle]
6729pub unsafe extern "C" fn ftello(stream: *mut FILE) -> i64 {
6730 let f = &mut *stream;
6731 if f.flags & F_APP != 0 && !f.wpos.is_null() && f.wpos != f.wbase {
6732 if fflush(stream) != 0 { return -1; }
6733 }
6734 let sfunc = match f.seek_fn { Some(s) => s, None => return -1 };
6735 let pos = sfunc(stream, 0,
6736 if (f.flags & F_APP) != 0 && !f.wpos.is_null() && f.wpos != f.wbase { SEEK_END } else { SEEK_CUR });
6737 if pos < 0 { return -1; }
6738 let mut pos = pos;
6739 if !f.rpos.is_null() {
6740 pos += f.rpos as i64 - f.rend as i64;
6741 } else if !f.wbase.is_null() {
6742 pos += f.wpos as i64 - f.wbase as i64;
6743 }
6744 pos - f.ungotten_count as i64
6745}
6746
6747#[no_mangle]
6748pub unsafe extern "C" fn fgetpos(stream: *mut FILE, pos: *mut i64) -> c_int {
6749 let off = ftello(stream);
6750 if off < 0 { return -1; }
6751 *pos = off;
6752 0
6753}
6754
6755#[no_mangle]
6756pub unsafe extern "C" fn fsetpos(stream: *mut FILE, pos: *const i64) -> c_int {
6757 fseeko(stream, *pos, SEEK_SET)
6758}
6759
6760#[no_mangle]
6765pub unsafe extern "C" fn fgetc(stream: *mut FILE) -> c_int {
6766 let f = &mut *stream;
6767 if f.ungotten_count > 0 {
6768 f.ungotten_count -= 1;
6769 return f.ungotten[f.ungotten_count as usize];
6770 }
6771 if !f.rpos.is_null() && f.rpos < f.rend {
6772 let c = *f.rpos;
6773 f.rpos = f.rpos.add(1);
6774 return c as c_int;
6775 }
6776 if f._eof != 0 { return -1; }
6777 if let Some(rfunc) = f.read_fn {
6778 if !f.buf.is_null() && f.buf_size > 1 {
6782 let n = rfunc(stream, f.buf, f.buf_size);
6783 if n == 0 {
6784 if f.flags & F_ERR != 0 { f._err = 1; } else { f._eof = 1; }
6785 return -1;
6786 }
6787 f.rpos = f.buf;
6788 f.rend = f.buf.add(n);
6789 let c = *f.rpos;
6790 f.rpos = f.rpos.add(1);
6791 return c as c_int;
6792 }
6793 let mut buf = [0u8; 1];
6794 let n = rfunc(stream, buf.as_mut_ptr(), 1);
6795 if n == 0 {
6796 if f.flags & F_ERR != 0 { f._err = 1; } else { f._eof = 1; }
6797 return -1;
6798 }
6799 buf[0] as c_int
6800 } else {
6801 f._eof = 1;
6802 -1
6803 }
6804}
6805
6806#[no_mangle]
6807pub unsafe extern "C" fn getc(stream: *mut FILE) -> c_int { fgetc(stream) }
6808
6809#[no_mangle]
6810pub unsafe extern "C" fn getchar() -> c_int { fgetc(stdin) }
6811
6812#[no_mangle]
6813pub unsafe extern "C" fn ungetc(c: c_int, stream: *mut FILE) -> c_int {
6814 if c == -1 { return -1; }
6815 let f = &mut *stream;
6816 if f.ungotten_count >= UNGET as c_int { return -1; }
6817 f.ungotten[f.ungotten_count as usize] = c;
6818 f.ungotten_count += 1;
6819 f._eof = 0;
6820 c
6821}
6822
6823#[no_mangle]
6828pub unsafe extern "C" fn fgets(s: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char {
6829 if n <= 0 { return null_mut(); }
6830 let max = (n - 1) as usize;
6831 let mut i = 0usize;
6832 while i < max {
6833 let c = fgetc(stream);
6834 if c == -1 { if i == 0 { return null_mut(); } break; }
6835 *s.add(i) = c as c_char;
6836 i += 1;
6837 if c == b'\n' as c_int { break; }
6838 }
6839 *s.add(i) = 0;
6840 s
6841}
6842
6843#[no_mangle]
6845pub unsafe extern "C" fn gets(s: *mut c_char) -> *mut c_char {
6846 let mut i = 0usize;
6847 loop {
6848 let c = fgetc(stdin);
6849 if c == -1 { if i == 0 { return null_mut(); } break; }
6850 if c == b'\n' as c_int { break; }
6851 *s.add(i) = c as c_char;
6852 i += 1;
6853 }
6854 *s.add(i) = 0;
6855 s
6856}
6857
6858#[no_mangle]
6859pub unsafe extern "C" fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut FILE {
6860 fopen(filename, mode)
6861}
6862
6863const PERROR_BUF_SIZE: usize = 64;
6865static mut PERROR_BUF: [u8; PERROR_BUF_SIZE] = [0; PERROR_BUF_SIZE];
6866
6867#[no_mangle]
6868pub unsafe extern "C" fn perror(msg: *const c_char) {
6869 let fd = (*stderr).fd;
6870 if !msg.is_null() && *msg != 0 {
6871 let len = strlen(msg as *const c_char);
6872 write_str(fd, msg as *const u8, len);
6873 write_str(fd, b": ".as_ptr(), 2);
6874 }
6875 let e = ERRNO!();
6876 let text = strerror(e) as *const u8;
6877 write_str(fd, text, strlen(text as *const c_char));
6878 write_str(fd, b"\n".as_ptr(), 1);
6879}
6880
6881#[no_mangle]
6882pub unsafe extern "C" fn fread(
6883 ptr: *mut c_void, size: SizeT, nmemb: SizeT, stream: *mut FILE,
6884) -> SizeT {
6885 if size == 0 || nmemb == 0 { return 0; }
6886 let total = size * nmemb;
6887 let mut rd = 0usize;
6888 while rd < total {
6889 let c = fgetc(stream);
6890 if c == -1 { break; }
6891 *(ptr as *mut u8).add(rd) = c as u8;
6892 rd += 1;
6893 }
6894 rd / size
6895}
6896
6897unsafe fn write_str(fd: c_int, s: *const u8, len: usize) {
6902 let mut written = 0usize;
6903 while written < len {
6904 let n = sys_write(fd as i64, s.add(written), len - written);
6905 if n <= 0 { break; }
6906 written += n as usize;
6907 }
6908}
6909
6910#[no_mangle]
6911unsafe fn __overflow(f: *mut FILE, c: c_int) -> c_int {
6912 if (*f).wpos.is_null() {
6913 (*f).wbase = (*f).buf;
6914 (*f).wpos = (*f).buf;
6915 (*f).wend = (*f).buf.add((*f).buf_size);
6916 }
6917 if flush_buf(f) == -1 { return -1; }
6918 if (*f).wpos >= (*f).wend {
6919 if let Some(wfunc) = (*f).write_fn {
6920 let byte = c as u8;
6921 let ret = wfunc(f, &byte as *const u8, 1);
6922 if ret == 0 { return -1; }
6923 }
6924 return c;
6925 }
6926 *(*f).wpos = c as u8;
6927 (*f).wpos = (*f).wpos.add(1);
6928 if c == (*f).lbf || (*f).wpos >= (*f).wend { let _ = flush_buf(f); }
6929 c
6930}
6931
6932#[no_mangle]
6933pub unsafe extern "C" fn puts(s: *const c_char) -> c_int {
6934 let len = strlen(s as *const c_char);
6935 let _ = fwrite(s as *const c_void, 1, len, stdout);
6936 let _ = fwrite(b"\n".as_ptr() as *const c_void, 1, 1, stdout);
6937 let f = &mut *stdout;
6938 if f.lbf >= 0 { let _ = flush_buf(stdout); }
6939 (len + 1) as c_int
6940}
6941
6942#[no_mangle]
6943pub unsafe extern "C" fn fputs(s: *const c_char, stream: *mut FILE) -> c_int {
6944 let len = strlen(s as *const c_char);
6945 fwrite(s as *const c_void, 1, len, stream) as c_int
6946}
6947
6948#[no_mangle]
6949pub unsafe extern "C" fn fputc(c: c_int, stream: *mut FILE) -> c_int {
6950 let f = &mut *stream;
6951 if f.wpos.is_null() || f.wpos >= f.wend {
6952 if __overflow(f, c) == -1 { return -1; }
6953 return c;
6954 }
6955 *f.wpos = c as u8;
6956 f.wpos = f.wpos.add(1);
6957 if c == f.lbf || f.wpos >= f.wend { let _ = flush_buf(f); }
6958 c
6959}
6960
6961#[no_mangle]
6962pub unsafe extern "C" fn putc(c: c_int, stream: *mut FILE) -> c_int { fputc(c, stream) }
6963
6964#[no_mangle]
6965pub unsafe extern "C" fn putchar(c: c_int) -> c_int { fputc(c, stdout) }
6966
6967#[no_mangle]
6968pub unsafe extern "C" fn fwrite(
6969 ptr: *const c_void, size: SizeT, nmemb: SizeT, stream: *mut FILE,
6970) -> SizeT {
6971 if size == 0 || nmemb == 0 { return 0; }
6972 let total = size * nmemb;
6973 let f = &mut *stream;
6974 if f.buf_size == 0 {
6975 if let Some(wfunc) = f.write_fn {
6976 let ret = wfunc(stream, ptr as *const u8, total);
6977 return ret / size;
6978 }
6979 return 0;
6980 }
6981 if f.wpos.is_null() {
6982 f.wbase = f.buf;
6983 f.wpos = f.buf;
6984 f.wend = f.buf.add(f.buf_size);
6985 }
6986 let mut remaining = total;
6987 let mut src = ptr as *const u8;
6988 while remaining > 0 {
6989 let space = f.wend as usize - f.wpos as usize;
6990 if space == 0 {
6991 if flush_buf(f as *mut FILE) == -1 { break; }
6992 continue;
6993 }
6994 let n = if remaining < space { remaining } else { space };
6995 core::ptr::copy_nonoverlapping(src, f.wpos, n);
6996 f.wpos = f.wpos.add(n);
6997 src = src.add(n);
6998 remaining -= n;
6999 if f.wpos >= f.wend { let _ = flush_buf(f as *mut FILE); }
7000 }
7001 if f.lbf >= 0 { let _ = flush_buf(f as *mut FILE); }
7002 (total - remaining) / size
7003}
7004
7005unsafe fn wide_to_mb(dst: *mut u8, cap: usize, src: *const wchar_t) -> usize {
7010 let mut o = 0usize;
7011 let mut i = 0usize;
7012 let mut st: c_uint = 0;
7013 while *src.add(i) != 0 {
7014 let mut tmp = [0u8; 8];
7015 let n = wcrtomb(tmp.as_mut_ptr() as *mut c_char, *src.add(i), &mut st);
7016 if n == !0usize || n == 0 { break; }
7017 if o + n > cap { break; }
7018 core::ptr::copy_nonoverlapping(tmp.as_ptr(), dst.add(o), n);
7019 o += n;
7020 i += 1;
7021 }
7022 o
7023}
7024
7025macro_rules! impl_format {
7026 ($fmt:expr, $args:expr, $write_char:expr, $write_str:expr) => {{
7027 let fmt = $fmt;
7028 let args = &mut $args;
7029 let mut count: usize = 0;
7030 let mut i = 0usize;
7031 loop {
7032 let c = *fmt.add(i) as u8;
7033 if c == 0 { break; }
7034 if c != b'%' {
7035 ($write_char)(c);
7036 count += 1; i += 1; continue;
7037 }
7038 i += 1;
7039 let mut flags: u8 = 0;
7041 loop {
7042 let fc = *fmt.add(i) as u8;
7043 match fc {
7044 b'-' => { flags |= FLAG_MINUS; i += 1; }
7045 b'+' => { flags |= FLAG_PLUS; i += 1; }
7046 b' ' => { flags |= FLAG_SPACE; i += 1; }
7047 b'0' => { flags |= FLAG_ZERO; i += 1; }
7048 b'#' => { flags |= FLAG_HASH; i += 1; }
7049 _ => break,
7050 }
7051 }
7052 let mut width: usize = 0;
7054 if *fmt.add(i) as u8 == b'*' {
7055 width = args.next_arg::<c_int>() as usize; i += 1;
7056 } else {
7057 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
7058 width = width * 10 + ((*fmt.add(i) as u8) - b'0') as usize; i += 1;
7059 }
7060 }
7061 let mut precision: i32 = -1;
7063 if *fmt.add(i) as u8 == b'.' {
7064 i += 1;
7065 if *fmt.add(i) as u8 == b'*' {
7066 precision = args.next_arg::<c_int>(); i += 1;
7067 } else {
7068 precision = 0;
7069 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
7070 precision = precision * 10 + ((*fmt.add(i) as u8) - b'0') as i32; i += 1;
7071 }
7072 }
7073 }
7074 let len_mod = *fmt.add(i) as u8;
7076 let spec: u8;
7077 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' {
7078 i += 1;
7079 let len_mod2 = *fmt.add(i) as u8;
7080 if (len_mod == b'h' && len_mod2 == b'h') || (len_mod == b'l' && len_mod2 == b'l') {
7081 i += 1;
7082 spec = *fmt.add(i) as u8;
7083 match (len_mod, len_mod2, spec) {
7085 (b'h', b'h', b'n') => {
7086 let p = args.next_arg::<*mut c_void>();
7087 if !p.is_null() { *(p as *mut u8) = count as u8; }
7088 }
7089 (b'l', b'l', b'n') => {
7090 let p = args.next_arg::<*mut c_void>();
7091 if !p.is_null() { *(p as *mut c_longlong) = count as c_longlong; }
7092 }
7093 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
7094 let val = args.next_arg::<c_longlong>();
7095 let neg = val < 0;
7096 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
7097 let b = format_u64(abs);
7098 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7099 let mut fbuf = [0u8; 32];
7100 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7101 ($write_str)(fbuf.as_ptr(), len); count += len;
7102 }
7103 (b'l', b'l', b'u') => {
7104 let val = args.next_arg::<c_ulonglong>();
7105 let b = format_u64(val as u64);
7106 let mut fbuf = [0u8; 32];
7107 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7108 ($write_str)(fbuf.as_ptr(), len); count += len;
7109 }
7110 (b'l', b'l', b'o') => {
7111 let val = args.next_arg::<c_ulonglong>();
7112 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
7113 let mut fbuf = [0u8; 32];
7114 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7115 ($write_str)(fbuf.as_ptr(), len); count += len;
7116 }
7117 (b'l', b'l', b'x') => {
7118 let val = args.next_arg::<c_ulonglong>();
7119 let b = format_hex(val as u64, false);
7120 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7121 let mut fbuf = [0u8; 32];
7122 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7123 ($write_str)(fbuf.as_ptr(), len); count += len;
7124 }
7125 (b'l', b'l', b'X') => {
7126 let val = args.next_arg::<c_ulonglong>();
7127 let b = format_hex(val as u64, true);
7128 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7129 let mut fbuf = [0u8; 32];
7130 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7131 ($write_str)(fbuf.as_ptr(), len); count += len;
7132 }
7133 _ => { ($write_char)(b'%'); ($write_char)(len_mod); ($write_char)(len_mod2); ($write_char)(spec); count += 4; }
7134 }
7135 } else {
7136 spec = len_mod2;
7137 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
7140 match (lm, spec) {
7141 (b'h', b'n') => {
7142 let p = args.next_arg::<*mut c_void>();
7143 if !p.is_null() { *(p as *mut u16) = count as u16; }
7144 }
7145 (b'l', b'n') => {
7146 let p = args.next_arg::<*mut c_void>();
7147 if !p.is_null() { *(p as *mut c_long) = count as c_long; }
7148 }
7149 (b'z', b'n') | (b't', b'n') => {
7150 let p = args.next_arg::<*mut c_void>();
7151 if !p.is_null() { *(p as *mut usize) = count; }
7152 }
7153 (b'j', b'n') => {
7154 let p = args.next_arg::<*mut c_void>();
7155 if !p.is_null() { *(p as *mut c_ulonglong) = count as c_ulonglong; }
7156 }
7157 (b'l', b'd') | (b'l', b'i') => {
7158 let val = args.next_arg::<c_long>();
7159 let neg = val < 0;
7160 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
7161 let b = format_u64(abs);
7162 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7163 let mut fbuf = [0u8; 32];
7164 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7165 ($write_str)(fbuf.as_ptr(), len); count += len;
7166 }
7167 (b'l', b'u') => {
7168 let val = args.next_arg::<c_ulong>();
7169 let b = format_u64(val as u64);
7170 let mut fbuf = [0u8; 32];
7171 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7172 ($write_str)(fbuf.as_ptr(), len); count += len;
7173 }
7174 (b'l', b's') => {
7175 let p = args.next_arg::<*const wchar_t>();
7176 if p.is_null() {
7177 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
7178 let pad = width.saturating_sub(slen);
7179 if flags & FLAG_MINUS != 0 { ($write_str)(b"(null)".as_ptr(), slen); for _ in 0..pad { ($write_char)(b' '); } }
7180 else { for _ in 0..pad { ($write_char)(b' '); } ($write_str)(b"(null)".as_ptr(), slen); }
7181 count += slen + pad;
7182 } else {
7183 let mut mb = [0u8; 4096];
7184 let mut n = wide_to_mb(mb.as_mut_ptr(), mb.len(), p);
7185 if precision >= 0 && (precision as usize) < n { n = precision as usize; }
7186 let pad = width.saturating_sub(n);
7187 if flags & FLAG_MINUS != 0 { ($write_str)(mb.as_ptr(), n); for _ in 0..pad { ($write_char)(b' '); } }
7188 else { for _ in 0..pad { ($write_char)(b' '); } ($write_str)(mb.as_ptr(), n); }
7189 count += n + pad;
7190 }
7191 }
7192 (b'l', b'c') => {
7193 let ch = args.next_arg::<c_int>();
7194 let mut mb = [0u8; 8];
7195 let mut st: c_uint = 0;
7196 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, ch, &mut st);
7197 if n != !0usize { ($write_str)(mb.as_ptr(), n); count += n; }
7198 }
7199 (b'l', b'x') => {
7200 let val = args.next_arg::<c_ulong>();
7201 let b = format_hex(val as u64, false);
7202 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7203 let mut fbuf = [0u8; 32];
7204 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7205 ($write_str)(fbuf.as_ptr(), len); count += len;
7206 }
7207 (b'l', b'X') => {
7208 let val = args.next_arg::<c_ulong>();
7209 let b = format_hex(val as u64, true);
7210 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7211 let mut fbuf = [0u8; 32];
7212 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7213 ($write_str)(fbuf.as_ptr(), len); count += len;
7214 }
7215 (b'l', b'o') => {
7216 let val = args.next_arg::<c_ulong>();
7217 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
7218 let mut fbuf = [0u8; 32];
7219 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7220 ($write_str)(fbuf.as_ptr(), len); count += len;
7221 }
7222 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
7223 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
7224 let val = args.next_arg::<f64>();
7225 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7226 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7227 let mut fbuf = [0u8; 4224];
7228 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7229 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
7230 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
7231 ($write_str)(fbuf.as_ptr(), total); count += total;
7232 }
7233 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
7234 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
7235 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
7236 let val = {
7237 let lo: u64 = args.next_arg::<u64>();
7238 let hi: u64 = args.next_arg::<u64>();
7239 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
7240 f128::from_bits(combined) as f64
7241 };
7242 #[cfg(target_arch = "x86_64")]
7243 let val = args.next_arg::<f64>();
7244 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7245 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7246 let mut fbuf = [0u8; 4224];
7247 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7248 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
7249 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
7250 ($write_str)(fbuf.as_ptr(), total); count += total;
7251 }
7252 _ => { ($write_char)(b'%'); ($write_char)(len_mod); ($write_char)(spec); count += 3; }
7253 }
7254 }
7255 } else {
7256 spec = *fmt.add(i) as u8;
7257 match spec {
7258 b's' => {
7259 let s = args.next_arg::<*const c_char>();
7260 if s.is_null() {
7261 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
7262 let padded_len = if width > slen { width } else { slen };
7263 let pad = padded_len - slen;
7264 if flags & FLAG_MINUS != 0 {
7265 ($write_str)(b"(null)".as_ptr(), slen);
7266 for _ in 0..pad { ($write_char)(b' '); }
7267 } else {
7268 for _ in 0..pad { ($write_char)(b' '); }
7269 ($write_str)(b"(null)".as_ptr(), slen);
7270 }
7271 count += padded_len;
7272 } else {
7273 let full_len = strlen(s as *const c_char);
7274 let slen = if precision >= 0 { (precision as usize).min(full_len) } else { full_len };
7275 let padded_len = if width > slen { width } else { slen };
7276 let pad = padded_len - slen;
7277 if flags & FLAG_MINUS != 0 {
7278 ($write_str)(s as *const u8, slen);
7279 for _ in 0..pad { ($write_char)(b' '); }
7280 } else {
7281 for _ in 0..pad { ($write_char)(b' '); }
7282 ($write_str)(s as *const u8, slen);
7283 }
7284 count += padded_len;
7285 }
7286 }
7287 b'd' | b'i' => {
7288 let d = args.next_arg::<c_int>();
7289 let neg = d < 0;
7290 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
7291 let b = format_u64(abs);
7292 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7293 let mut fbuf = [0u8; 32];
7294 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7295 ($write_str)(fbuf.as_ptr(), len); count += len;
7296 }
7297 b'u' => {
7298 let u = args.next_arg::<c_uint>();
7299 let b = format_u64(u as u64);
7300 let mut fbuf = [0u8; 32];
7301 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7302 ($write_str)(fbuf.as_ptr(), len); count += len;
7303 }
7304 b'x' => {
7305 let x = args.next_arg::<c_uint>();
7306 let b = format_hex(x as u64, false);
7307 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7308 let mut fbuf = [0u8; 32];
7309 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7310 ($write_str)(fbuf.as_ptr(), len); count += len;
7311 }
7312 b'X' => {
7313 let x = args.next_arg::<c_uint>();
7314 let b = format_hex(x as u64, true);
7315 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7316 let mut fbuf = [0u8; 32];
7317 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7318 ($write_str)(fbuf.as_ptr(), len); count += len;
7319 }
7320 b'o' => {
7321 let o = args.next_arg::<c_uint>();
7322 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
7323 let mut fbuf = [0u8; 32];
7324 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7325 ($write_str)(fbuf.as_ptr(), len); count += len;
7326 }
7327 b'c' => {
7328 let ch = args.next_arg::<c_int>();
7329 if width > 1 {
7330 let pad = width - 1;
7331 if flags & FLAG_MINUS != 0 {
7332 ($write_char)(ch as u8); count += 1;
7333 for _ in 0..pad { ($write_char)(b' '); count += 1; }
7334 } else {
7335 for _ in 0..pad { ($write_char)(b' '); count += 1; }
7336 ($write_char)(ch as u8); count += 1;
7337 }
7338 } else {
7339 ($write_char)(ch as u8); count += 1;
7340 }
7341 }
7342 b'p' => {
7343 let p = args.next_arg::<*const c_void>();
7344 let mut fbuf = [0u8; 20];
7345 fbuf[0] = b'0'; fbuf[1] = b'x';
7346 let b = format_hex(p as u64, false);
7347 core::ptr::copy_nonoverlapping(b.0.as_ptr(), fbuf.as_mut_ptr().add(2), b.1);
7348 ($write_str)(fbuf.as_ptr(), b.1 + 2); count += b.1 + 2;
7349 }
7350 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
7351 let val = args.next_arg::<f64>();
7352 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7353 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7354 let mut fbuf = [0u8; 4224];
7355 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7356 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
7357 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
7358 ($write_str)(fbuf.as_ptr(), total); count += total;
7359 }
7360 b'%' => { ($write_char)(b'%'); count += 1; }
7361 b'n' => {
7362 let p = args.next_arg::<*mut c_void>();
7363 if !p.is_null() { *(p as *mut c_int) = count as c_int; }
7364 }
7365 _ => { ($write_char)(b'%'); ($write_char)(spec); count += 2; }
7366 }
7367 }
7368 i += 1;
7369 }
7370 count as c_int
7371 }};
7372}
7373
7374unsafe fn format_u64(mut val: u64) -> ([u8; 20], usize) {
7375 let mut buf = [0u8; 20];
7376 if val == 0 { buf[0] = b'0'; return (buf, 1); }
7377 let mut tmp = [0u8; 20];
7378 let mut pos = 20;
7379 while val > 0 { pos -= 1; tmp[pos] = b'0' + (val % 10) as u8; val /= 10; }
7380 let len = 20 - pos;
7381 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7382 (buf, len)
7383}
7384
7385unsafe fn format_i64(val: i64) -> ([u8; 21], usize) {
7386 let mut buf = [0u8; 21];
7387 if val < 0 {
7388 buf[0] = b'-';
7389 let (inner, len) = format_u64((-(val as i128)) as u64);
7390 core::ptr::copy_nonoverlapping(inner.as_ptr(), buf.as_mut_ptr().add(1), len);
7391 (buf, len + 1)
7392 } else {
7393 let (inner, len) = format_u64(val as u64);
7394 core::ptr::copy_nonoverlapping(inner.as_ptr(), buf.as_mut_ptr(), len);
7395 (buf, len)
7396 }
7397}
7398
7399unsafe fn format_hex(mut val: u64, uppercase: bool) -> ([u8; 16], usize) {
7400 let digits = if uppercase { b"0123456789ABCDEF" } else { b"0123456789abcdef" };
7401 let mut buf = [0u8; 16];
7402 if val == 0 { buf[0] = b'0'; return (buf, 1); }
7403 let mut tmp = [0u8; 16];
7404 let mut pos = 16;
7405 while val > 0 { pos -= 1; tmp[pos] = digits[(val & 0xf) as usize]; val >>= 4; }
7406 let len = 16 - pos;
7407 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7408 (buf, len)
7409}
7410
7411unsafe fn format_octal(mut val: u64, alt: bool) -> ([u8; 24], usize) {
7412 let mut buf = [0u8; 24];
7413 if val == 0 {
7414 buf[0] = b'0';
7415 return (buf, 1);
7416 }
7417 let mut tmp = [0u8; 24];
7418 let mut pos = 24;
7419 while val > 0 {
7420 pos -= 1;
7421 tmp[pos] = b'0' + (val & 7) as u8;
7422 val >>= 3;
7423 }
7424 let len = 24 - pos;
7425 if alt {
7426 tmp[pos - 1] = b'0';
7427 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos - 1), buf.as_mut_ptr(), len + 1);
7428 (buf, len + 1)
7429 } else {
7430 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7431 (buf, len)
7432 }
7433}
7434
7435unsafe fn format_int(
7436 dst: *mut u8,
7437 digits: *const u8,
7438 digits_len: usize,
7439 sign: Option<u8>,
7440 prefix: Option<u8>,
7441 precision: i32,
7442 width: usize,
7443 flags: u8,
7444 octal_alt: bool,
7445) -> usize {
7446 let num_digits = if precision == 0 && digits_len == 1 && *digits == b'0' && !octal_alt {
7447 0
7448 } else {
7449 digits_len
7450 };
7451 let prec = precision as usize;
7452 let zero_pad = if precision >= 0 && prec > num_digits { prec - num_digits } else { 0 };
7453
7454 let sign_len = sign.map_or(0, |_| 1);
7455 let prefix_len = prefix.map_or(0, |_| 2);
7456 let content_len = sign_len + prefix_len + zero_pad + num_digits;
7457
7458 let mut buf = [0u8; 32];
7459 let mut pos = 0usize;
7460 if let Some(c) = sign { buf[pos] = c; pos += 1; }
7461 if let Some(c) = prefix { buf[pos] = b'0'; pos += 1; buf[pos] = c; pos += 1; }
7462 for _ in 0..zero_pad { buf[pos] = b'0'; pos += 1; }
7463 if num_digits > 0 {
7464 core::ptr::copy_nonoverlapping(digits, buf.as_mut_ptr().add(pos), num_digits);
7465 }
7466
7467 if content_len >= width {
7468 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, content_len);
7469 return content_len;
7470 }
7471 let pad = width - content_len;
7472 if flags & FLAG_MINUS != 0 {
7473 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, content_len);
7474 for i in 0..pad { *dst.add(content_len + i) = b' '; }
7475 } else if flags & FLAG_ZERO != 0 && precision < 0 {
7476 let fixed = sign_len + prefix_len;
7477 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, fixed);
7478 for i in fixed..width - num_digits { *dst.add(i) = b'0'; }
7479 if num_digits > 0 {
7480 core::ptr::copy_nonoverlapping(digits, dst.add(width - num_digits), num_digits);
7481 }
7482 } else {
7483 for i in 0..pad { *dst.add(i) = b' '; }
7484 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst.add(pad), content_len);
7485 }
7486 width
7487}
7488
7489unsafe fn format_f64(val: f64) -> ([u8; 64], usize) {
7490 let mut buf = [0u8; 64];
7491 let mut pos = 0usize;
7492 let mut v = val;
7493 if v.is_nan() {
7494 let nan = b"nan";
7495 core::ptr::copy_nonoverlapping(nan.as_ptr(), buf.as_mut_ptr(), 3);
7496 return (buf, 3);
7497 }
7498 if v < 0.0 { buf[pos] = b'-'; pos += 1; v = -v; }
7499 if v.is_infinite() {
7500 let inf = b"inf";
7501 core::ptr::copy_nonoverlapping(inf.as_ptr(), buf.as_mut_ptr().add(pos), 3);
7502 return (buf, pos + 3);
7503 }
7504 let int_part = v as u64;
7505 let frac = v - int_part as f64;
7506 let (ibuf, ilen) = format_u64(int_part);
7507 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), buf.as_mut_ptr().add(pos), ilen);
7508 pos += ilen;
7509 buf[pos] = b'.';
7510 pos += 1;
7511 let mut f = frac;
7512 for _ in 0..6 { f *= 10.0; let digit = f as u8; buf[pos] = b'0' + digit; pos += 1; f -= digit as f64; }
7513 (buf, pos)
7514}
7515
7516const FMT_F: u8 = 0;
7518const FMT_E: u8 = 1;
7519const FMT_G: u8 = 2;
7520const FMT_A: u8 = 3;
7521
7522const FLAG_HASH: u8 = 1;
7523const FLAG_PLUS: u8 = 2;
7524const FLAG_SPACE: u8 = 4;
7525const FLAG_ZERO: u8 = 8;
7526const FLAG_MINUS: u8 = 16;
7527
7528unsafe fn bigint_to_decimal(buf: *mut u8, mant: u64, shift: u32) -> usize {
7533 let nlimbs = (2 + (shift + 31) / 32) as usize;
7535 let mut limbs = [0u32; 36];
7536 limbs[0] = mant as u32;
7537 limbs[1] = (mant >> 32) as u32;
7538
7539 let ws = (shift / 32) as usize;
7540 let bs = shift % 32;
7541
7542 if ws > 0 {
7544 let mut i = 1usize;
7545 loop {
7546 limbs[i + ws] = limbs[i];
7547 if i == 0 { break; }
7548 i -= 1;
7549 }
7550 for j in 0..ws { limbs[j] = 0; }
7551 }
7552 if bs > 0 {
7554 let mut carry = 0u32;
7555 let end = nlimbs.min(ws + 3);
7556 for i in ws..end {
7557 let new_val = (limbs[i] << bs) | carry;
7558 carry = limbs[i] >> (32 - bs);
7559 limbs[i] = new_val;
7560 }
7561 }
7562
7563 let mut used = nlimbs;
7565 while used > 0 && limbs[used - 1] == 0 { used -= 1; }
7566 if used == 0 { *buf = b'0'; return 1; }
7567
7568 let mut digits = [0u8; 400];
7570 let mut nd = 0usize;
7571 loop {
7572 let mut all_zero = true;
7573 for i in 0..used { if limbs[i] != 0 { all_zero = false; break; } }
7574 if all_zero { break; }
7575 let mut rem = 0u64;
7576 for i in (0..used).rev() {
7577 let val = (rem << 32) | limbs[i] as u64;
7578 limbs[i] = (val / 10) as u32;
7579 rem = val % 10;
7580 }
7581 digits[nd] = rem as u8;
7582 nd += 1;
7583 }
7584 for i in 0..nd { *buf.add(i) = b'0' + digits[nd - 1 - i]; }
7586 nd
7587}
7588
7589unsafe fn frac_digits_u128(buf: *mut u8, frac_bits: u64, shift: u32, count: usize) -> bool {
7592 let mask: u128 = (1u128 << shift) - 1;
7593 let mut rem = frac_bits as u128;
7594 for i in 0..count {
7595 rem *= 10;
7596 let digit = (rem >> shift) as u8;
7597 rem &= mask;
7598 *buf.add(i) = digit;
7599 }
7600 rem != 0
7601}
7602
7603unsafe fn frac_digits_bigint(buf: *mut u8, frac_bits: u64, shift: u32, count: usize) -> bool {
7606 let nlimbs = ((shift + 31) / 32) as usize;
7607 let mut rem = [0u32; 36]; rem[0] = frac_bits as u32;
7609 if nlimbs > 1 { rem[1] = (frac_bits >> 32) as u32; }
7610 let hi_word = (shift / 32) as usize;
7612 let hi_bit = shift % 32;
7613 if hi_bit > 0 && hi_word < nlimbs {
7614 rem[hi_word] &= (1u32 << hi_bit) - 1;
7615 }
7616 let clear_from = if hi_bit > 0 { hi_word + 1 } else { hi_word };
7618 for j in clear_from..nlimbs { rem[j] = 0; }
7619
7620 for i in 0..count {
7621 let mut carry = 0u64;
7623 for j in 0..nlimbs {
7624 let val = rem[j] as u64 * 10 + carry;
7625 rem[j] = val as u32;
7626 carry = val >> 32;
7627 }
7628 let digit: u32;
7630 if hi_bit == 0 {
7631 digit = if hi_word < nlimbs { rem[hi_word] } else { carry as u32 };
7632 } else {
7633 let mut d = if hi_word < nlimbs { rem[hi_word] >> hi_bit } else { 0 };
7634 if hi_word + 1 < nlimbs {
7635 d |= rem[hi_word + 1] << (32 - hi_bit);
7636 } else if carry > 0 {
7637 d |= (carry as u32) << (32 - hi_bit);
7638 }
7639 digit = d;
7640 }
7641 *buf.add(i) = digit.min(9) as u8;
7642 if hi_bit == 0 {
7644 if hi_word < nlimbs { rem[hi_word] = 0; }
7645 } else {
7646 if hi_word < nlimbs {
7647 rem[hi_word] &= (1u32 << hi_bit) - 1;
7648 }
7649 for j in (hi_word + 1)..nlimbs { rem[j] = 0; }
7650 }
7651 }
7652 for i in 0..nlimbs { if rem[i] != 0 { return true; } }
7654 false
7655}
7656
7657unsafe fn increment_decimal(buf: *mut u8, len: &mut usize) {
7659 let mut j = *len;
7660 loop {
7661 if j == 0 {
7662 let l = *len;
7664 for i in (0..l).rev() { *buf.add(i + 1) = *buf.add(i); }
7665 *buf = b'1';
7666 *len = l + 1;
7667 return;
7668 }
7669 j -= 1;
7670 let d = *buf.add(j);
7671 if d < b'9' { *buf.add(j) = d + 1; return; }
7672 *buf.add(j) = b'0';
7673 }
7674}
7675
7676unsafe fn format_f64_full(
7678 dst: *mut u8, val: f64, fmt_type: u8, precision: i32, flags: u8, uppercase: bool,
7679) -> usize {
7680 let mut pos = 0usize;
7681
7682 if val.is_nan() {
7684 let nan_s: &[u8] = if uppercase { b"NAN" } else { b"nan" };
7685 core::ptr::copy_nonoverlapping(nan_s.as_ptr(), dst, 3);
7686 return 3;
7687 }
7688 let neg = val.is_sign_negative();
7689 let v = if neg { -val } else { val };
7690
7691 if v.is_infinite() {
7693 if neg { *dst.add(pos) = b'-'; pos += 1; }
7694 else if flags & FLAG_PLUS != 0 { *dst.add(pos) = b'+'; pos += 1; }
7695 else if flags & FLAG_SPACE != 0 { *dst.add(pos) = b' '; pos += 1; }
7696 let inf_s: &[u8] = if uppercase { b"INF" } else { b"inf" };
7697 core::ptr::copy_nonoverlapping(inf_s.as_ptr(), dst.add(pos), 3);
7698 return pos + 3;
7699 }
7700
7701 if neg { *dst.add(pos) = b'-'; pos += 1; }
7703 else if flags & FLAG_PLUS != 0 { *dst.add(pos) = b'+'; pos += 1; }
7704 else if flags & FLAG_SPACE != 0 { *dst.add(pos) = b' '; pos += 1; }
7705
7706 if fmt_type == FMT_A {
7708 return pos + fmt_hex_float(dst.add(pos), val, precision, flags, uppercase);
7709 }
7710
7711 let p: usize;
7713 let mut exp: i32;
7714 let use_f: bool;
7715
7716 match fmt_type {
7717 FMT_G => {
7718 let gp = if precision < 0 { 6usize } else if precision == 0 { 1usize } else { precision as usize };
7719 exp = if v > 0.0 { compute_exp10(v) } else { 0 };
7720 use_f = exp >= -4 && exp < gp as i32;
7721 if use_f {
7722 p = if exp < 0 { gp + ((-exp) as usize - 1) }
7723 else if (exp as usize) < gp { gp - exp as usize - 1 }
7724 else { 0 };
7725 } else {
7726 p = gp - 1;
7727 }
7728 }
7729 FMT_E => {
7730 p = if precision < 0 { 6usize } else { precision as usize };
7731 exp = if v > 0.0 { compute_exp10(v) } else { 0 };
7732 use_f = false;
7733 }
7734 _ => {
7735 p = if precision < 0 { 6usize } else { precision as usize };
7736 exp = 0;
7737 use_f = true;
7738 }
7739 }
7740
7741 if v == 0.0 {
7742 *dst.add(pos) = b'0'; pos += 1;
7743 if !(fmt_type == FMT_G && flags & FLAG_HASH == 0) {
7744 if p > 0 || flags & FLAG_HASH != 0 {
7745 *dst.add(pos) = b'.'; pos += 1;
7746 for _ in 0..p { *dst.add(pos) = b'0'; pos += 1; }
7747 }
7748 }
7749 if !use_f {
7750 let ec = if uppercase { b'E' } else { b'e' };
7751 *dst.add(pos) = ec; pos += 1;
7752 *dst.add(pos) = b'+'; pos += 1;
7753 *dst.add(pos) = b'0'; pos += 1;
7754 *dst.add(pos) = b'0'; pos += 1;
7755 }
7756 return pos;
7757 }
7758
7759 if use_f {
7761 let bits = v.to_bits();
7762 let raw_mant = bits & 0x000FFFFFFFFFFFFF;
7763 let raw_exp_bits = ((bits >> 52) & 0x7FF) as i32;
7764 let (mant_b, bin_exp) = if raw_exp_bits == 0 {
7765 (raw_mant, -1022i32)
7766 } else {
7767 (raw_mant | (1u64 << 52), raw_exp_bits - 1023)
7768 };
7769
7770 let mut ibuf = [0u8; 400];
7772 let mut ilen: usize;
7773 if bin_exp < 0 {
7774 ibuf[0] = b'0'; ilen = 1;
7775 } else if bin_exp <= 63 {
7776 let int_val = if bin_exp <= 52 { mant_b >> (52 - bin_exp) }
7777 else { mant_b << (bin_exp - 52) };
7778 let (buf2, len2) = format_u64(int_val);
7779 ibuf[..len2].copy_from_slice(&buf2[..len2]);
7780 ilen = len2;
7781 } else {
7782 ilen = bigint_to_decimal(ibuf.as_mut_ptr(), mant_b, (bin_exp - 52) as u32);
7783 }
7784
7785 let mut fbuf = [0u8; 1100];
7787 let mut has_rest = false;
7788 if p > 0 && bin_exp < 52 {
7789 let shift = (52 - bin_exp) as u32;
7790 let frac_bits = if bin_exp >= 0 { mant_b & ((1u64 << shift) - 1) } else { mant_b };
7791 if shift <= 124 {
7792 has_rest = frac_digits_u128(fbuf.as_mut_ptr(), frac_bits, shift, p + 1);
7793 } else {
7794 has_rest = frac_digits_bigint(fbuf.as_mut_ptr(), frac_bits, shift, p + 1);
7795 }
7796 }
7797
7798 if p > 0 && bin_exp < 52 {
7800 let next_d = fbuf[p];
7801 let last_d = fbuf[p - 1];
7802 if next_d > 5 || (next_d == 5 && (has_rest || last_d & 1 != 0)) {
7803 let mut carry = true;
7804 for j in (0..p).rev() {
7805 if !carry { break; }
7806 fbuf[j] += 1;
7807 if fbuf[j] < 10 { carry = false; break; }
7808 fbuf[j] = 0;
7809 }
7810 if carry { increment_decimal(ibuf.as_mut_ptr(), &mut ilen); }
7811 }
7812 } else if p == 0 {
7813 if bin_exp >= 0 && bin_exp < 52 {
7815 let shift = (52 - bin_exp) as u32;
7816 let frac_bits = mant_b & ((1u64 << shift) - 1);
7817 let half = 1u64 << (shift - 1);
7818 let last_d = ibuf[ilen - 1] - b'0';
7819 if frac_bits > half || (frac_bits == half && last_d & 1 != 0) {
7820 increment_decimal(ibuf.as_mut_ptr(), &mut ilen);
7821 }
7822 }
7823 }
7824
7825 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), dst.add(pos), ilen);
7827 pos += ilen;
7828 if p > 0 || flags & FLAG_HASH != 0 {
7829 *dst.add(pos) = b'.'; pos += 1;
7830 for i in 0..p { *dst.add(pos) = b'0' + fbuf[i]; pos += 1; }
7831 }
7832 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7833 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7834 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7835 }
7836 return pos;
7837 }
7838
7839 let mut fbuf = [0u8; 20];
7842 let mut int_part: u64;
7843 {
7844 let bits_v = v.to_bits();
7845 let raw_mant_v = bits_v & 0x000FFFFFFFFFFFFF;
7846 let raw_exp_v = ((bits_v >> 52) & 0x7FF) as i32;
7847 let (mant_b_v, bin_exp_v) = if raw_exp_v == 0 {
7848 (raw_mant_v, -1022i32)
7849 } else {
7850 (raw_mant_v | (1u64 << 52), raw_exp_v - 1023)
7851 };
7852
7853 let s: i32 = (p as i32) + 1 - exp;
7854 let bs: i32 = bin_exp_v - 52 + s;
7855
7856 let mut limbs = [0u32; 40];
7857 limbs[0] = mant_b_v as u32;
7858 limbs[1] = (mant_b_v >> 32) as u32;
7859 let mut nlimbs: usize = if limbs[1] != 0 { 2 } else { 1 };
7860
7861 if s > 0 {
7862 for _ in 0..(s as usize) {
7863 let mut carry = 0u64;
7864 for j in 0..nlimbs {
7865 let val = limbs[j] as u64 * 5 + carry;
7866 limbs[j] = val as u32;
7867 carry = val >> 32;
7868 }
7869 if carry > 0 { limbs[nlimbs] = carry as u32; nlimbs += 1; }
7870 }
7871 }
7872
7873 if bs > 0 {
7874 let ws = (bs as u32 / 32) as usize;
7875 let bit = bs as u32 % 32;
7876 if ws > 0 {
7877 let mut i = nlimbs;
7878 while i > 0 { i -= 1; if i + ws < 40 { limbs[i + ws] = limbs[i]; } limbs[i] = 0; }
7879 nlimbs += ws;
7880 }
7881 if bit > 0 {
7882 let mut carry = 0u32;
7883 for i in ws..nlimbs {
7884 let new_val = (limbs[i] << bit) | carry;
7885 carry = limbs[i] >> (32 - bit);
7886 limbs[i] = new_val;
7887 }
7888 if carry > 0 && nlimbs < 40 { limbs[nlimbs] = carry; nlimbs += 1; }
7889 }
7890 }
7891
7892 let mut has_rest = false;
7893 if s < 0 {
7894 for _ in 0..(-s as usize) {
7895 let mut rem = 0u64;
7896 for i in (0..nlimbs).rev() {
7897 let val = (rem << 32) | limbs[i] as u64;
7898 limbs[i] = (val / 5) as u32;
7899 rem = val % 5;
7900 }
7901 if rem != 0 { has_rest = true; }
7902 }
7903 }
7904
7905 if bs < 0 {
7906 let rshift = (-bs) as u32;
7907 let ws = (rshift / 32) as usize;
7908 let bit = rshift % 32;
7909 if ws > 0 {
7910 for j in 0..ws.min(nlimbs) { if limbs[j] != 0 { has_rest = true; } }
7911 for i in ws..nlimbs { limbs[i - ws] = limbs[i]; }
7912 nlimbs = nlimbs.saturating_sub(ws);
7913 }
7914 if bit > 0 && nlimbs > 0 {
7915 let mask = (1u32 << bit) - 1;
7916 if limbs[0] & mask != 0 { has_rest = true; }
7917 for i in 0..nlimbs - 1 {
7918 limbs[i] = (limbs[i] >> bit) | (limbs[i + 1] << (32 - bit));
7919 }
7920 limbs[nlimbs - 1] >>= bit;
7921 }
7922 }
7923
7924 while nlimbs > 0 && limbs[nlimbs - 1] == 0 { nlimbs -= 1; }
7925
7926 let ndigits = p + 2;
7927 let mut all_digits = [0u8; 25];
7928 let mut nd = 0usize;
7929 if nlimbs > 0 {
7930 loop {
7931 let mut all_zero = true;
7932 for i in 0..nlimbs { if limbs[i] != 0 { all_zero = false; break; } }
7933 if all_zero { break; }
7934 let mut rem64 = 0u64;
7935 for i in (0..nlimbs).rev() {
7936 let val = (rem64 << 32) | limbs[i] as u64;
7937 limbs[i] = (val / 10) as u32;
7938 rem64 = val % 10;
7939 }
7940 if nd < 25 { all_digits[nd] = rem64 as u8; }
7941 nd += 1;
7942 }
7943 }
7944
7945 if nd >= ndigits {
7946 for i in 0..ndigits { fbuf[ndigits - 1 - i] = all_digits[i]; }
7947 } else {
7948 for i in 0..nd { fbuf[ndigits - 1 - i] = all_digits[i]; }
7949 for i in nd..ndigits { fbuf[ndigits - 1 - i] = 0; }
7950 }
7951
7952 int_part = fbuf[0] as u64;
7953
7954 if p > 0 {
7956 let next_d = fbuf[p + 1];
7957 let last_d = fbuf[p];
7958 if next_d > 5 || (next_d == 5 && (has_rest || last_d & 1 != 0)) {
7959 let mut carry = true;
7960 for j in (1..=p).rev() {
7961 if !carry { break; }
7962 let d = fbuf[j] + 1;
7963 if d < 10 { fbuf[j] = d; carry = false; break; }
7964 fbuf[j] = 0;
7965 }
7966 if carry { int_part += 1; }
7967 }
7968 } else {
7969 let next_d = fbuf[1];
7970 if next_d > 5 || (next_d == 5 && (has_rest || int_part & 1 != 0)) {
7971 int_part += 1;
7972 }
7973 }
7974
7975 for i in 0..p { fbuf[i] = fbuf[i + 1]; }
7978 }
7979
7980 if !use_f && int_part >= 10 {
7981 exp += 1;
7982 int_part = 1;
7983 }
7984
7985 if use_f {
7987 let (ibuf, ilen) = format_u64(int_part);
7989 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), dst.add(pos), ilen);
7990 pos += ilen;
7991 if p > 0 || flags & FLAG_HASH != 0 {
7992 *dst.add(pos) = b'.'; pos += 1;
7993 for idx in 0..p { *dst.add(pos) = b'0' + fbuf[idx]; pos += 1; }
7994 }
7995 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7996 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7997 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7998 }
7999 } else {
8000 *dst.add(pos) = b'0' + int_part as u8; pos += 1;
8002 if p > 0 || flags & FLAG_HASH != 0 {
8003 *dst.add(pos) = b'.'; pos += 1;
8004 for idx in 0..p { *dst.add(pos) = b'0' + fbuf[idx]; pos += 1; }
8005 }
8006 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
8007 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
8008 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
8009 }
8010 let ec = if uppercase { b'E' } else { b'e' };
8011 *dst.add(pos) = ec; pos += 1;
8012 *dst.add(pos) = if exp < 0 { b'-' } else { b'+' }; pos += 1;
8013 let eabs = if exp < 0 { (-exp) as u32 } else { exp as u32 };
8014 if eabs < 10 { *dst.add(pos) = b'0'; pos += 1; }
8015 let (ebuf, elen) = format_u64(eabs as u64);
8016 core::ptr::copy_nonoverlapping(ebuf.as_ptr(), dst.add(pos), elen);
8017 pos += elen;
8018 }
8019
8020 pos
8021}
8022
8023unsafe fn compute_exp10(v: f64) -> i32 {
8025 let e = libm::floor(libm::log10(v)) as i32;
8026 let probe = v / libm::pow(10.0, e as f64);
8027 if probe >= 10.0 { e + 1 }
8028 else if probe < 1.0 { e - 1 }
8029 else { e }
8030}
8031
8032unsafe fn fmt_hex_float(dst: *mut u8, val: f64, precision: i32, _flags: u8, uppercase: bool) -> usize {
8034 if val.to_bits() & 0x7FFFFFFFFFFFFFFF == 0 {
8036 let lc = !uppercase;
8037 let pfx: &[u8] = if lc { b"0x" } else { b"0X" };
8038 let p = if precision < 0 { 0usize } else { precision as usize };
8039 let mut pos = 0usize;
8040 core::ptr::copy_nonoverlapping(pfx.as_ptr(), dst.add(pos), 2); pos += 2;
8041 *dst.add(pos) = b'0'; pos += 1;
8042 if p > 0 {
8043 *dst.add(pos) = b'.'; pos += 1;
8044 for _ in 0..p { *dst.add(pos) = b'0'; pos += 1; }
8045 }
8046 let pc = if lc { b'p' } else { b'P' };
8047 *dst.add(pos) = pc; pos += 1;
8048 *dst.add(pos) = b'+'; pos += 1;
8049 *dst.add(pos) = b'0'; pos += 1;
8050 return pos;
8051 }
8052 let bits = val.to_bits();
8053 let exp_bits = ((bits >> 52) & 0x7FF) as i32;
8054 let mant_bits = bits & 0x000FFFFFFFFFFFFF;
8055 let (mut e, mut m) = if exp_bits == 0 { (1 - 1023, mant_bits) } else { (exp_bits - 1023, mant_bits | (1u64 << 52)) };
8056 if exp_bits == 0 && m != 0 {
8059 let shift = m.leading_zeros() as i32 - 11;
8060 m <<= shift;
8061 e -= shift;
8062 }
8063 let explicit = precision >= 0;
8064 let p = if explicit { precision as usize } else { 13usize };
8065 let mut pos = 0usize;
8066 let lc = !uppercase;
8067 let pfx: &[u8] = if lc { b"0x" } else { b"0X" };
8068 core::ptr::copy_nonoverlapping(pfx.as_ptr(), dst.add(pos), 2); pos += 2;
8069
8070 let lead_pos = pos;
8072 let mut lead = ((m >> 52) & 0xF) as u8;
8073 *dst.add(pos) = hex_digit_char(lead, lc); pos += 1;
8074 let mut frac_start = pos;
8075 if p > 0 {
8076 *dst.add(pos) = b'.'; pos += 1;
8077 frac_start = pos;
8078 }
8079
8080 let mut rm = m;
8082 for _ in 0..p {
8083 let nib = ((rm >> 48) & 0xF) as u8;
8084 *dst.add(pos) = hex_digit_char(nib, lc); pos += 1;
8085 rm <<= 4;
8086 }
8087
8088 let round_nib = ((rm >> 48) & 0xF) as u8;
8090 let rest = rm & 0x0000FFFFFFFFFFFF;
8091 let last_nib = if p > 0 {
8092 hex_char_val(*dst.add(pos - 1))
8093 } else {
8094 lead
8095 };
8096 let should_round = round_nib > 8 || (round_nib == 8 && (rest != 0 || (last_nib & 1) != 0));
8097 if should_round {
8098 let mut j = pos;
8099 loop {
8100 if j == frac_start {
8101 lead += 1;
8103 *dst.add(lead_pos) = hex_digit_char(lead, lc);
8104 break;
8105 }
8106 j -= 1;
8107 let v = hex_char_val(*dst.add(j));
8108 if v < 15 {
8109 *dst.add(j) = hex_digit_char(v + 1, lc);
8110 break;
8111 }
8112 *dst.add(j) = b'0';
8113 }
8114 }
8115
8116 if !explicit {
8119 while pos > frac_start && *dst.add(pos - 1) == b'0' {
8120 pos -= 1;
8121 }
8122 if pos == frac_start {
8123 pos = frac_start - 1;
8124 }
8125 }
8126
8127 let pc = if lc { b'p' } else { b'P' };
8129 *dst.add(pos) = pc; pos += 1;
8130 *dst.add(pos) = if e < 0 { b'-' } else { b'+' }; pos += 1;
8131 let eabs = if e < 0 { (-e) as u32 } else { e as u32 };
8132 let (ebuf, elen) = format_u64(eabs as u64);
8133 core::ptr::copy_nonoverlapping(ebuf.as_ptr(), dst.add(pos), elen);
8134 pos += elen;
8135 pos
8136}
8137
8138#[inline]
8139fn hex_digit_char(v: u8, lowercase: bool) -> u8 {
8140 if v < 10 { b'0' + v }
8141 else if lowercase { b'a' + v - 10 }
8142 else { b'A' + v - 10 }
8143}
8144
8145#[inline]
8146fn hex_char_val(c: u8) -> u8 {
8147 if c >= b'0' && c <= b'9' { c - b'0' }
8148 else if c >= b'a' && c <= b'f' { c - b'a' + 10 }
8149 else if c >= b'A' && c <= b'F' { c - b'A' + 10 }
8150 else { 0 }
8151}
8152
8153unsafe fn apply_width_flags(
8156 dst: *mut u8, buf: *const u8, len: usize, width: usize, flags: u8,
8157) -> usize {
8158 if len >= width {
8159 core::ptr::copy_nonoverlapping(buf, dst, len);
8160 return len;
8161 }
8162 let pad = width - len;
8163 let pad_char = if flags & FLAG_ZERO != 0 && flags & FLAG_MINUS == 0 { b'0' } else { b' ' };
8164 if flags & FLAG_MINUS != 0 {
8165 core::ptr::copy_nonoverlapping(buf, dst, len);
8167 for i in 0..pad { *dst.add(len + i) = pad_char; }
8168 } else {
8169 if flags & FLAG_ZERO != 0 && len > 0 {
8172 let first = *buf;
8173 if first == b'-' || first == b'+' || first == b' ' {
8174 *dst = first;
8175 for i in 0..pad { *dst.add(1 + i) = pad_char; }
8176 core::ptr::copy_nonoverlapping(buf.add(1), dst.add(1 + pad), len - 1);
8177 return width;
8178 }
8179 }
8180 for i in 0..pad { *dst.add(i) = pad_char; }
8181 core::ptr::copy_nonoverlapping(buf, dst.add(pad), len);
8182 }
8183 width
8184}
8185
8186#[no_mangle]
8187pub unsafe extern "C" fn vprintf(fmt: *const c_char, mut args: VaList) -> c_int {
8188 impl_format!(fmt, args,
8189 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stdout); },
8190 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stdout); }
8191 )
8192}
8193
8194#[no_mangle]
8195pub unsafe extern "C" fn vfprintf(stream: *mut FILE, fmt: *const c_char, mut args: VaList) -> c_int {
8196 impl_format!(fmt, args,
8197 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stream); },
8198 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stream); }
8199 )
8200}
8201
8202#[no_mangle]
8203pub unsafe extern "C" fn printf(fmt: *const c_char, mut args: ...) -> c_int {
8204 impl_format!(fmt, args,
8205 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stdout); },
8206 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stdout); }
8207 )
8208}
8209
8210#[no_mangle]
8211pub unsafe extern "C" fn fprintf(stream: *mut FILE, fmt: *const c_char, mut args: ...) -> c_int {
8212 impl_format!(fmt, args,
8213 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stream); },
8214 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stream); }
8215 )
8216}
8217
8218#[no_mangle]
8219unsafe fn format_write_fd(fd: c_int, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
8220 let mut stack = [0u8; 4096];
8223 let mut a1 = args.clone();
8224 let n = format_to_buf(stack.as_mut_ptr(), stack.len(), fmt, &mut a1);
8225 if n < 0 { return -1; }
8226 if (n as usize) < stack.len() {
8227 let w = crate::write(fd, stack.as_ptr() as *const c_void, n as usize);
8228 if w < 0 { return -1; }
8229 return n;
8230 }
8231 let heap = crate::malloc(n as usize + 1) as *mut u8;
8232 if heap.is_null() { return -1; }
8233 let mut a2 = args.clone();
8234 let n2 = format_to_buf(heap, n as usize + 1, fmt, &mut a2);
8235 if n2 < 0 { crate::free(heap as *mut c_void); return -1; }
8236 let w = crate::write(fd, heap as *const c_void, n2 as usize);
8237 crate::free(heap as *mut c_void);
8238 if w < 0 { return -1; }
8239 n2
8240}
8241
8242#[no_mangle]
8243pub unsafe extern "C" fn dprintf(fd: c_int, fmt: *const c_char, mut args: ...) -> c_int {
8244 format_write_fd(fd, fmt, &mut args)
8245}
8246
8247#[no_mangle]
8248pub unsafe extern "C" fn vdprintf(fd: c_int, fmt: *const c_char, mut args: VaList) -> c_int {
8249 format_write_fd(fd, fmt, &mut args)
8250}
8251
8252unsafe fn format_to_buf(buf: *mut u8, cap: usize, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
8257 let mut pos = 0usize;
8258 let mut i = 0usize;
8259 let mut count = 0usize;
8260 macro_rules! wc {
8261 ($c:expr) => { if pos < cap { *buf.add(pos) = $c; } pos += 1; count += 1; }
8262 }
8263 macro_rules! ws {
8264 ($s:expr, $len:expr) => {{
8265 let __len = $len;
8266 for k in 0..__len { if pos + k < cap { *buf.add(pos + k) = *$s.add(k); } }
8267 pos += __len; count += __len;
8268 }}
8269 }
8270 macro_rules! ws_buf {
8272 ($src:expr, $len:expr) => {{
8273 let __len = $len;
8274 for k in 0..__len { if pos + k < cap { *buf.add(pos + k) = *$src.add(k); } }
8275 pos += __len; count += __len;
8276 }}
8277 }
8278 loop {
8279 let c = *fmt.add(i) as u8;
8280 if c == 0 { break; }
8281 if c != b'%' { wc!(c); i += 1; continue; }
8282 i += 1;
8283 let mut flags: u8 = 0;
8285 loop {
8286 let fc = *fmt.add(i) as u8;
8287 match fc {
8288 b'-' => { flags |= FLAG_MINUS; i += 1; }
8289 b'+' => { flags |= FLAG_PLUS; i += 1; }
8290 b' ' => { flags |= FLAG_SPACE; i += 1; }
8291 b'0' => { flags |= FLAG_ZERO; i += 1; }
8292 b'#' => { flags |= FLAG_HASH; i += 1; }
8293 _ => break,
8294 }
8295 }
8296 let mut width: usize = 0;
8298 if *fmt.add(i) as u8 == b'*' {
8299 width = args.next_arg::<c_int>() as usize; i += 1;
8300 } else {
8301 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
8302 width = width * 10 + ((*fmt.add(i) as u8) - b'0') as usize; i += 1;
8303 }
8304 }
8305 let mut precision: i32 = -1;
8307 if *fmt.add(i) as u8 == b'.' {
8308 i += 1;
8309 if *fmt.add(i) as u8 == b'*' {
8310 precision = args.next_arg::<c_int>(); i += 1;
8311 } else {
8312 precision = 0;
8313 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
8314 precision = precision * 10 + ((*fmt.add(i) as u8) - b'0') as i32; i += 1;
8315 }
8316 }
8317 }
8318 let len_mod = *fmt.add(i) as u8;
8320 let spec: u8;
8321 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' {
8322 i += 1;
8323 let len_mod2 = *fmt.add(i) as u8;
8324 if (len_mod == b'h' && len_mod2 == b'h') || (len_mod == b'l' && len_mod2 == b'l') {
8325 i += 1;
8326 spec = *fmt.add(i) as u8;
8327 match (len_mod, len_mod2, spec) {
8328 (b'h', b'h', b'n') => {
8329 let p = args.next_arg::<*mut c_void>();
8330 if !p.is_null() { *(p as *mut u8) = count as u8; }
8331 }
8332 (b'l', b'l', b'n') => {
8333 let p = args.next_arg::<*mut c_void>();
8334 if !p.is_null() { *(p as *mut c_longlong) = count as c_longlong; }
8335 }
8336 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
8337 let val = args.next_arg::<c_longlong>();
8338 let neg = val < 0;
8339 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
8340 let b = format_u64(abs);
8341 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8342 let mut fbuf = [0u8; 32];
8343 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8344 ws_buf!(fbuf.as_ptr(), len);
8345 }
8346 (b'l', b'l', b'u') => {
8347 let val = args.next_arg::<c_ulonglong>();
8348 let b = format_u64(val as u64);
8349 let mut fbuf = [0u8; 32];
8350 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8351 ws_buf!(fbuf.as_ptr(), len);
8352 }
8353 (b'l', b'l', b'o') => {
8354 let val = args.next_arg::<c_ulonglong>();
8355 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
8356 let mut fbuf = [0u8; 32];
8357 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8358 ws_buf!(fbuf.as_ptr(), len);
8359 }
8360 (b'l', b'l', b'x') | (b'l', b'l', b'X') => {
8361 let val = args.next_arg::<c_ulonglong>();
8362 let b = format_hex(val as u64, spec == b'X');
8363 let pc = if spec == b'X' { b'X' } else { b'x' };
8364 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(pc) } else { None };
8365 let mut fbuf = [0u8; 32];
8366 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8367 ws_buf!(fbuf.as_ptr(), len);
8368 }
8369 _ => { wc!(b'%'); wc!(len_mod); wc!(len_mod2); wc!(spec); }
8370 }
8371 } else {
8372 spec = len_mod2;
8373 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
8374 match (lm, spec) {
8375 (b'h', b'n') => {
8376 let p = args.next_arg::<*mut c_void>();
8377 if !p.is_null() { *(p as *mut u16) = count as u16; }
8378 }
8379 (b'l', b'n') => {
8380 let p = args.next_arg::<*mut c_void>();
8381 if !p.is_null() { *(p as *mut c_long) = count as c_long; }
8382 }
8383 (b'z', b'n') | (b't', b'n') => {
8384 let p = args.next_arg::<*mut c_void>();
8385 if !p.is_null() { *(p as *mut usize) = count; }
8386 }
8387 (b'j', b'n') => {
8388 let p = args.next_arg::<*mut c_void>();
8389 if !p.is_null() { *(p as *mut c_ulonglong) = count as c_ulonglong; }
8390 }
8391 (b'l', b'd') | (b'l', b'i') => {
8392 let val = args.next_arg::<c_long>();
8393 let neg = val < 0;
8394 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
8395 let b = format_u64(abs);
8396 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8397 let mut fbuf = [0u8; 32];
8398 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8399 ws_buf!(fbuf.as_ptr(), len);
8400 }
8401 (b'l', b'u') => {
8402 let val = args.next_arg::<c_ulong>();
8403 let b = format_u64(val as u64);
8404 let mut fbuf = [0u8; 32];
8405 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8406 ws_buf!(fbuf.as_ptr(), len);
8407 }
8408 (b'l', b's') => {
8409 let p = args.next_arg::<*const wchar_t>();
8410 if p.is_null() {
8411 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
8412 let pad = width.saturating_sub(slen);
8413 if flags & FLAG_MINUS != 0 { ws!(b"(null)".as_ptr(), slen); for _ in 0..pad { wc!(b' '); } }
8414 else { for _ in 0..pad { wc!(b' '); } ws!(b"(null)".as_ptr(), slen); }
8415 } else {
8416 let mut mb = [0u8; 4096];
8417 let mut n = wide_to_mb(mb.as_mut_ptr(), mb.len(), p);
8418 if precision >= 0 && (precision as usize) < n { n = precision as usize; }
8419 let pad = width.saturating_sub(n);
8420 if flags & FLAG_MINUS != 0 { ws!(mb.as_ptr(), n); for _ in 0..pad { wc!(b' '); } }
8421 else { for _ in 0..pad { wc!(b' '); } ws!(mb.as_ptr(), n); }
8422 }
8423 }
8424 (b'l', b'c') => {
8425 let ch = args.next_arg::<c_int>();
8426 let mut mb = [0u8; 8];
8427 let mut st: c_uint = 0;
8428 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, ch, &mut st);
8429 if n != !0usize { ws!(mb.as_ptr(), n); }
8430 }
8431 (b'l', b'x') => {
8432 let val = args.next_arg::<c_ulong>();
8433 let b = format_hex(val as u64, false);
8434 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
8435 let mut fbuf = [0u8; 32];
8436 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8437 ws_buf!(fbuf.as_ptr(), len);
8438 }
8439 (b'l', b'X') => {
8440 let val = args.next_arg::<c_ulong>();
8441 let b = format_hex(val as u64, true);
8442 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
8443 let mut fbuf = [0u8; 32];
8444 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8445 ws_buf!(fbuf.as_ptr(), len);
8446 }
8447 (b'l', b'o') => {
8448 let val = args.next_arg::<c_ulong>();
8449 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
8450 let mut fbuf = [0u8; 32];
8451 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8452 ws_buf!(fbuf.as_ptr(), len);
8453 }
8454 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
8455 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
8456 let val = args.next_arg::<f64>();
8457 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8458 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8459 let mut fbuf = [0u8; 4224];
8460 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8461 let mut wbuf = [0u8; 4224];
8462 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8463 ws_buf!(wbuf.as_ptr(), wlen);
8464 }
8465 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
8466 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
8467 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
8468 let val = {
8469 let lo: u64 = args.next_arg::<u64>();
8470 let hi: u64 = args.next_arg::<u64>();
8471 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
8472 f128::from_bits(combined) as f64
8473 };
8474 #[cfg(target_arch = "x86_64")]
8475 let val = args.next_arg::<f64>();
8476 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8477 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8478 let mut fbuf = [0u8; 4224];
8479 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8480 let mut wbuf = [0u8; 4224];
8481 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8482 ws_buf!(wbuf.as_ptr(), wlen);
8483 }
8484 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
8485 }
8486 }
8487 } else {
8488 spec = *fmt.add(i) as u8;
8489 match spec {
8490 b's' => {
8491 let s = args.next_arg::<*const c_char>();
8492 if s.is_null() {
8493 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
8494 let padded_len = if width > slen { width } else { slen };
8495 let pad = padded_len - slen;
8496 if flags & FLAG_MINUS != 0 {
8497 ws!(b"(null)".as_ptr(), slen);
8498 for _ in 0..pad { wc!(b' '); }
8499 } else {
8500 for _ in 0..pad { wc!(b' '); }
8501 ws!(b"(null)".as_ptr(), slen);
8502 }
8503 } else {
8504 let full_len = strlen(s as *const c_char);
8505 let slen = if precision >= 0 { (precision as usize).min(full_len) } else { full_len };
8506 let padded_len = if width > slen { width } else { slen };
8507 let pad = padded_len - slen;
8508 if flags & FLAG_MINUS != 0 {
8509 ws!(s as *const u8, slen);
8510 for _ in 0..pad { wc!(b' '); }
8511 } else {
8512 for _ in 0..pad { wc!(b' '); }
8513 ws!(s as *const u8, slen);
8514 }
8515 }
8516 }
8517 b'd' | b'i' => {
8518 let d = args.next_arg::<c_int>();
8519 let neg = d < 0;
8520 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
8521 let b = format_u64(abs);
8522 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8523 let mut fbuf = [0u8; 32];
8524 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8525 ws_buf!(fbuf.as_ptr(), len);
8526 }
8527 b'u' => {
8528 let u = args.next_arg::<c_uint>();
8529 let b = format_u64(u as u64);
8530 let mut fbuf = [0u8; 32];
8531 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8532 ws_buf!(fbuf.as_ptr(), len);
8533 }
8534 b'x' => {
8535 let x = args.next_arg::<c_uint>();
8536 let b = format_hex(x as u64, false);
8537 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
8538 let mut fbuf = [0u8; 32];
8539 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8540 ws_buf!(fbuf.as_ptr(), len);
8541 }
8542 b'X' => {
8543 let x = args.next_arg::<c_uint>();
8544 let b = format_hex(x as u64, true);
8545 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
8546 let mut fbuf = [0u8; 32];
8547 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8548 ws_buf!(fbuf.as_ptr(), len);
8549 }
8550 b'o' => {
8551 let o = args.next_arg::<c_uint>();
8552 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
8553 let mut fbuf = [0u8; 32];
8554 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8555 ws_buf!(fbuf.as_ptr(), len);
8556 }
8557 b'c' => {
8558 let ch = args.next_arg::<c_int>();
8559 if width > 1 {
8560 let pad = width - 1;
8561 if flags & FLAG_MINUS != 0 {
8562 wc!(ch as u8);
8563 for _ in 0..pad { wc!(b' '); }
8564 } else {
8565 for _ in 0..pad { wc!(b' '); }
8566 wc!(ch as u8);
8567 }
8568 } else {
8569 wc!(ch as u8);
8570 }
8571 }
8572 b'p' => {
8573 wc!(b'0'); wc!(b'x');
8574 let p = args.next_arg::<*const c_void>();
8575 let b = format_hex(p as u64, false);
8576 ws!(b.0.as_ptr(), b.1);
8577 }
8578 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
8579 let val = args.next_arg::<f64>();
8580 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8581 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8582 let mut fbuf = [0u8; 4224];
8583 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8584 let mut wbuf = [0u8; 4224];
8585 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8586 ws_buf!(wbuf.as_ptr(), wlen);
8587 }
8588 b'%' => { wc!(b'%'); }
8589 b'n' => {
8590 let p = args.next_arg::<*mut c_void>();
8591 if !p.is_null() { *(p as *mut c_int) = count as c_int; }
8592 }
8593 _ => { wc!(b'%'); wc!(spec); }
8594 }
8595 }
8596 i += 1;
8597 }
8598 if cap > 0 { let null_pos = if pos < cap { pos } else { cap - 1 }; *buf.add(null_pos) = 0; }
8599 count as c_int
8600}
8601
8602#[no_mangle]
8603pub unsafe extern "C" fn vsprintf(buf: *mut c_char, fmt: *const c_char, mut args: VaList) -> c_int {
8604 format_to_buf(buf as *mut u8, usize::MAX, fmt, &mut args)
8605}
8606
8607#[no_mangle]
8608pub unsafe extern "C" fn vsnprintf(buf: *mut c_char, size: usize, fmt: *const c_char, mut args: VaList) -> c_int {
8609 format_to_buf(buf as *mut u8, size, fmt, &mut args)
8610}
8611
8612#[no_mangle]
8613pub unsafe extern "C" fn sprintf(buf: *mut c_char, fmt: *const c_char, mut args: ...) -> c_int {
8614 format_to_buf(buf as *mut u8, usize::MAX, fmt, &mut args)
8615}
8616
8617#[no_mangle]
8618pub unsafe extern "C" fn snprintf(buf: *mut c_char, size: usize, fmt: *const c_char, mut args: ...) -> c_int {
8619 format_to_buf(buf as *mut u8, size, fmt, &mut args)
8620}
8621
8622#[no_mangle]
8623pub unsafe extern "C" fn vasprintf(strp: *mut *mut c_char, fmt: *const c_char, ap: VaList) -> c_int {
8624 let len = vsnprintf(core::ptr::null_mut(), 0, fmt, ap.clone());
8625 if len < 0 {
8626 *strp = core::ptr::null_mut();
8627 return -1;
8628 }
8629 let p = malloc((len as usize) + 1) as *mut c_char;
8630 if p.is_null() {
8631 *strp = core::ptr::null_mut();
8632 return -1;
8633 }
8634 let ret = vsnprintf(p, (len as usize) + 1, fmt, ap.clone());
8635 if ret < 0 {
8636 free(p as *mut c_void);
8637 *strp = core::ptr::null_mut();
8638 return -1;
8639 }
8640 *strp = p;
8641 ret
8642}
8643
8644#[no_mangle]
8645pub unsafe extern "C" fn asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int {
8646 vasprintf(strp, fmt, args)
8647}
8648
8649unsafe fn skip_ws(p: *const u8) -> *const u8 {
8654 let mut q = p;
8655 while *q == b' ' || *q == b'\t' || *q == b'\n' || *q == b'\r' { q = q.add(1); }
8656 q
8657}
8658
8659#[inline]
8660fn is_ws_byte(c: u8) -> bool {
8661 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0b || c == 0x0c
8662}
8663
8664unsafe fn scan_int_val(
8667 buf: *const u8, pos: &mut usize, buf_len: usize, base: u32, width: usize,
8668) -> (u64, bool, bool) {
8669 let start = *pos;
8670 let max = if width > 0 { (start + width).min(buf_len) } else { buf_len };
8671 let neg = if *pos < max && *buf.add(*pos) == b'-' { *pos += 1; true }
8672 else if *pos < max && *buf.add(*pos) == b'+' { *pos += 1; false }
8673 else { false };
8674 if *pos >= max { *pos = start; return (0, false, false); }
8675 let mut base = base;
8676 let mut val: u64 = 0;
8677 if (base == 0 || base == 16) && *pos < max && *buf.add(*pos) == b'0' {
8679 *pos += 1;
8680 if *pos < max && (*buf.add(*pos) == b'x' || *buf.add(*pos) == b'X') {
8681 *pos += 1;
8682 if *pos < max {
8683 if let Some(d) = hex_val(*buf.add(*pos)) {
8684 val = d as u64; *pos += 1;
8685 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; } }
8686 return (val, neg, true);
8687 }
8688 }
8689 return (0, neg, false);
8690 } else if base == 0 {
8691 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; } }
8692 return (val, neg, true);
8693 } else {
8694 while *pos < max {
8697 if let Some(d) = hex_val(*buf.add(*pos)) {
8698 val = val.wrapping_mul(16).wrapping_add(d as u64);
8699 *pos += 1;
8700 } else {
8701 break;
8702 }
8703 }
8704 return (val, neg, true);
8705 }
8706 }
8707 if base == 0 { base = 10; }
8708 let mut found = false;
8709 while *pos < max {
8710 let c = *buf.add(*pos);
8711 let d: Option<u64> = match base {
8712 8 => if c >= b'0' && c <= b'7' { Some((c - b'0') as u64) } else { None },
8713 10 => if c >= b'0' && c <= b'9' { Some((c - b'0') as u64) } else { None },
8714 16 => hex_val(c).map(|v| v as u64),
8715 _ => None,
8716 };
8717 match d { Some(digit) => { val = val.wrapping_mul(base as u64).wrapping_add(digit); *pos += 1; found = true; } None => break }
8718 }
8719 if !found { *pos = start; return (0, false, false); }
8720 (val, neg, true)
8721}
8722
8723unsafe fn scan_float_val(
8725 buf: *const u8, pos: &mut usize, buf_len: usize, width: usize,
8726) -> (f64, bool) {
8727 let start = *pos;
8728 let max = if width > 0 { (start + width).min(buf_len) } else { buf_len };
8729 let neg = if *pos < max && *buf.add(*pos) == b'-' { *pos += 1; true }
8730 else if *pos < max && *buf.add(*pos) == b'+' { *pos += 1; false }
8731 else { false };
8732 if *pos + 2 < max {
8734 let (c0,c1,c2) = (*buf.add(*pos), *buf.add(*pos+1), *buf.add(*pos+2));
8735 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); }
8736 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); }
8737 }
8738 if *pos+1 < max && *buf.add(*pos)==b'0' && (*buf.add(*pos+1)==b'x'||*buf.add(*pos+1)==b'X') {
8740 *pos += 2;
8741 let mut val: f64 = 0.0; let mut found = false; let mut frac_scale = 1.0f64; let mut in_frac = false;
8742 while *pos < max {
8743 if let Some(d) = hex_val(*buf.add(*pos)) {
8744 if in_frac { frac_scale /= 16.0; val += d as f64 * frac_scale; } else { val = val * 16.0 + d as f64; }
8745 *pos += 1; found = true;
8746 } else if *buf.add(*pos)==b'.' && !in_frac { in_frac = true; *pos += 1; } else { break; }
8747 }
8748 if !found { *pos = start; return (0.0, false); }
8749 if *pos < max && (*buf.add(*pos)==b'p'||*buf.add(*pos)==b'P') {
8751 *pos += 1;
8752 let mut eneg = false;
8753 if *pos<max && *buf.add(*pos)==b'-' { eneg=true; *pos+=1; }
8754 else if *pos<max && *buf.add(*pos)==b'+' { *pos+=1; }
8755 let mut ev: i32 = 0; let mut ef = false;
8756 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; }
8757 if !ef { return (0.0, false); }
8758 if eneg { ev = -ev; }
8759 val *= libm::pow(2.0, ev as f64);
8760 }
8761 return (if neg{-val}else{val}, true);
8762 }
8763 let token_start = start;
8764 let mut i = start;
8765 let mut saw_digit = false;
8766 let mut saw_dot = false;
8767 let mut saw_exp = false;
8768 let mut first = true;
8769 while i < max {
8770 let c = *buf.add(i);
8771 if (c == b'+' || c == b'-') && first {
8772 i += 1; first = false; continue;
8773 }
8774 if c >= b'0' && c <= b'9' {
8775 saw_digit = true; i += 1; first = false; continue;
8776 }
8777 if c == b'.' && !saw_dot && !saw_exp {
8778 saw_dot = true; i += 1; first = false; continue;
8779 }
8780 if (c == b'e' || c == b'E') && !saw_exp && saw_digit {
8781 saw_exp = true; i += 1; first = true; continue;
8782 }
8783 break;
8784 }
8785 if !saw_digit { return (0.0, false); }
8786 let s = core::str::from_utf8_unchecked(core::slice::from_raw_parts(buf.add(token_start), i - token_start));
8787 match <f64 as core::str::FromStr>::from_str(s) {
8788 Ok(v) => { *pos = i; return (v, true); }
8789 Err(_) => { return (0.0, false); }
8790 }
8791}
8792
8793unsafe fn store_scan_int(dest: *mut c_void, len_mod: u8, val: u64, neg: bool) {
8798 let sv: i64 = if neg { (val as i64).wrapping_neg() } else { val as i64 };
8799 match len_mod {
8800 2 => *(dest as *mut i8) = sv as i8,
8801 1 => *(dest as *mut i16) = sv as i16,
8802 3 | 4 => *(dest as *mut i64) = sv,
8803 _ => *(dest as *mut i32) = sv as i32,
8804 }
8805}
8806
8807unsafe fn do_vsscanf(
8808 buf: *const u8, buf_len: usize, fmt: *const c_char, args: &mut VaList<'_>, consumed: *mut usize,
8809) -> c_int {
8810 let mut p = 0usize;
8811 let mut fi = 0usize;
8812 let mut assigned = 0i32;
8813 let mut input_eof = false;
8814 loop {
8815 let fc = *fmt.add(fi) as u8;
8816 if fc == 0 { break; }
8817 if is_ws_byte(fc) {
8818 while is_ws_byte(*fmt.add(fi) as u8) { fi += 1; }
8819 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8820 continue;
8821 }
8822 if fc != b'%' {
8823 if p >= buf_len { input_eof = true; break; }
8824 if *buf.add(p) != fc { break; }
8825 p += 1; fi += 1; continue;
8826 }
8827 fi += 1;
8828 if *fmt.add(fi) as u8 == b'%' {
8830 if p >= buf_len { input_eof = true; break; }
8831 if *buf.add(p) != b'%' { break; }
8832 p += 1; fi += 1; continue;
8833 }
8834 let suppress = if *fmt.add(fi) as u8 == b'*' { fi += 1; true } else { false };
8835 let mut width: usize = 0;
8836 while (*fmt.add(fi) as u8) >= b'0' && (*fmt.add(fi) as u8) <= b'9' {
8837 width = width * 10 + ((*fmt.add(fi) as u8) - b'0') as usize; fi += 1;
8838 }
8839 if *fmt.add(fi) as u8 == b'm' { fi += 1; }
8840 let mut len_mod = 0u8;
8841 match *fmt.add(fi) as u8 {
8842 b'h' => { fi += 1; if *fmt.add(fi) as u8 == b'h' { fi += 1; len_mod = 2; } else { len_mod = 1; } }
8843 b'l' => { fi += 1; if *fmt.add(fi) as u8 == b'l' { fi += 1; len_mod = 4; } else { len_mod = 3; } }
8844 b'j' => { fi += 1; len_mod = 4; }
8845 b'z' | b't' => { fi += 1; len_mod = 3; }
8846 b'L' => { fi += 1; len_mod = 5; }
8847 _ => {}
8848 }
8849 let spec = *fmt.add(fi) as u8;
8850 let (real_spec, _real_len) = if spec==b'C' {(b'c',3u8)} else if spec==b'S' {(b's',3u8)} else {(spec,len_mod)};
8851 match real_spec {
8852 b'n' => {
8853 if !suppress {
8854 let out = args.next_arg::<*mut c_void>();
8855 if !out.is_null() {
8856 match len_mod {
8857 1 => *(out as *mut i16) = p as i16,
8858 2 => *(out as *mut i8) = p as i8,
8859 3 | 4 => *(out as *mut i64) = p as i64,
8860 _ => *(out as *mut c_int) = p as c_int,
8861 }
8862 }
8863 }
8864 }
8865 b'd' | b'u' => {
8866 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8867 if p >= buf_len { input_eof = true; break; }
8868 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8869 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 10, width);
8870 if !ok { break; }
8871 if let Some(out) = dest { if !out.is_null() {
8872 store_scan_int(out, len_mod, val, neg);
8873 }}
8874 if !suppress { assigned += 1; }
8875 }
8876 b'i' => {
8877 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8878 if p >= buf_len { input_eof = true; break; }
8879 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8880 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 0, width);
8881 if !ok { break; }
8882 if let Some(out) = dest { if !out.is_null() { store_scan_int(out, len_mod, val, neg); } }
8883 if !suppress { assigned += 1; }
8884 }
8885 b'o' => {
8886 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8887 if p >= buf_len { input_eof = true; break; }
8888 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8889 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 8, width);
8890 if !ok { break; }
8891 if let Some(out) = dest { if !out.is_null() { store_scan_int(out, len_mod, val, neg); } }
8892 if !suppress { assigned += 1; }
8893 }
8894 b'x' | b'X' => {
8895 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8896 if p >= buf_len { input_eof = true; break; }
8897 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8898 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 16, width);
8899 if !ok { break; }
8900 if let Some(out) = dest { if !out.is_null() { store_scan_int(out, len_mod, val, neg); } }
8901 if !suppress { assigned += 1; }
8902 }
8903 b'p' => {
8904 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8905 if p >= buf_len { input_eof = true; break; }
8906 let dest = if !suppress { Some(args.next_arg::<*mut *mut c_void>()) } else { None };
8907 let (val, _, ok) = scan_int_val(buf, &mut p, buf_len, 16, width);
8908 if !ok { break; }
8909 if let Some(out) = dest { if !out.is_null() { *out = val as usize as *mut c_void; } }
8910 if !suppress { assigned += 1; }
8911 }
8912 b'a' | b'e' | b'f' | b'g' | b'A' | b'E' | b'F' | b'G' => {
8913 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8914 if p >= buf_len { input_eof = true; break; }
8915 let (val, ok) = scan_float_val(buf, &mut p, buf_len, width);
8916 if !ok { break; }
8917 if !suppress {
8918 if _real_len == 3 {
8919 let out = args.next_arg::<*mut f64>(); if !out.is_null() { *out = val; }
8920 } else if _real_len == 5 {
8921 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
8922 { let out = args.next_arg::<*mut f128>(); if !out.is_null() { *out = val as f128; } }
8923 #[cfg(target_arch = "x86_64")]
8924 { let out = args.next_arg::<*mut f64>(); if !out.is_null() { *out = val; } }
8925 } else {
8926 let out = args.next_arg::<*mut f32>(); if !out.is_null() { *out = val as f32; }
8927 }
8928 }
8929 if !suppress { assigned += 1; }
8930 }
8931 b'c' => {
8932 let w = if width > 0 { width } else { 1 };
8933 if p >= buf_len { input_eof = true; break; }
8934 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8935 let start_p = p;
8936 let mut j = 0usize;
8937 while j < w && p < buf_len {
8938 if !dest_ptr.is_null() { *dest_ptr.add(j) = *buf.add(p) as c_char; }
8939 p += 1; j += 1;
8940 }
8941 if j != w { p = start_p; input_eof = true; break; }
8942 if !suppress { assigned += 1; }
8943 }
8944 b's' => {
8945 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8946 if p >= buf_len { input_eof = true; break; }
8947 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8948 let w = if width > 0 { width } else { usize::MAX };
8949 let mut j = 0usize;
8950 while p < buf_len && *buf.add(p) != 0 && !is_ws_byte(*buf.add(p)) && j < w {
8951 if !dest_ptr.is_null() { *dest_ptr.add(j) = *buf.add(p) as c_char; }
8952 p += 1; j += 1;
8953 }
8954 if j == 0 { break; }
8955 if !dest_ptr.is_null() { *dest_ptr.add(j) = 0; }
8956 if !suppress { assigned += 1; }
8957 }
8958 b'[' => {
8959 fi += 1;
8960 let negate = if *fmt.add(fi) as u8 == b'^' { fi += 1; true } else { false };
8961 let mut charset = [0u8; 256];
8962 let mut prev: Option<u8> = None;
8963 if *fmt.add(fi) as u8 == b']' {
8964 charset[b']' as usize] = 1;
8965 prev = Some(b']');
8966 fi += 1;
8967 }
8968 loop {
8969 let c = *fmt.add(fi) as u8;
8970 if c == b']' || c == 0 { break; }
8971 if c == b'-' && prev.is_some() {
8974 let hi = *fmt.add(fi + 1) as u8;
8975 if hi != b']' && hi != 0 {
8976 let lo = prev.unwrap();
8977 let mut k = lo;
8978 while k <= hi {
8979 charset[k as usize] = 1;
8980 if k == 255 { break; }
8981 k += 1;
8982 }
8983 prev = None;
8984 fi += 2;
8985 continue;
8986 }
8987 }
8988 charset[c as usize] = 1;
8989 prev = Some(c);
8990 fi += 1;
8991 }
8992 if *fmt.add(fi) as u8 == b']' { fi += 1; }
8993 fi -= 1; if p >= buf_len { input_eof = true; break; }
8995 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8996 let w = if width > 0 { width } else { usize::MAX };
8997 let mut j = 0usize;
8998 while p < buf_len && *buf.add(p) != 0 && j < w {
8999 let c = *buf.add(p);
9000 let in_set = charset[c as usize] != 0;
9001 if negate { if in_set { break; } } else { if !in_set { break; } }
9002 if !dest_ptr.is_null() { *dest_ptr.add(j) = c as c_char; }
9003 p += 1; j += 1;
9004 }
9005 if j == 0 { break; }
9006 if !dest_ptr.is_null() { *dest_ptr.add(j) = 0; }
9007 if !suppress { assigned += 1; }
9008 }
9009 _ => break,
9010 }
9011 fi += 1;
9012 }
9013 if !consumed.is_null() { *consumed = p; }
9014 if assigned == 0 && input_eof { -1 } else { assigned }
9015}
9016
9017unsafe fn vsscanf_inner(buf: *const u8, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
9018 let len = strlen(buf as *const c_char);
9019 do_vsscanf(buf, len, fmt, args, core::ptr::null_mut())
9020}
9021
9022#[no_mangle]
9023pub unsafe extern "C" fn vsscanf(buf: *const c_char, fmt: *const c_char, mut args: VaList) -> c_int {
9024 vsscanf_inner(buf as *const u8, fmt, &mut args)
9025}
9026
9027#[no_mangle]
9028pub unsafe extern "C" fn vfscanf(stream: *mut FILE, fmt: *const c_char, mut args: VaList) -> c_int {
9029 let f = &mut *stream;
9030 let start_ungotten_count = f.ungotten_count as usize;
9031 let ungotten_saved = f.ungotten;
9032 let sfunc = f.seek_fn;
9033 let start_pos = if sfunc.is_some() { ftello(stream) } else { -1 };
9035
9036 let mut line = [0u8; 4096];
9037 let mut pos = 0usize;
9038
9039 if start_pos >= 0 {
9040 while pos < line.len() - 1 {
9042 let c = fgetc(stream);
9043 if c == -1 { break; }
9044 line[pos] = c as u8;
9045 pos += 1;
9046 if c == b'\n' as c_int { break; }
9047 }
9048 } else {
9049 while f.ungotten_count > 0 && pos < line.len() - 1 {
9054 f.ungotten_count -= 1;
9055 line[pos] = f.ungotten[f.ungotten_count as usize] as u8;
9056 pos += 1;
9057 }
9058 while !f.rpos.is_null() && f.rpos < f.rend && pos < line.len() - 1 {
9060 line[pos] = *f.rpos;
9061 f.rpos = f.rpos.add(1);
9062 pos += 1;
9063 }
9064 let fd = f.fd;
9068 if pos == 0 {
9069 let n = sys_read(fd as i64, line.as_mut_ptr(), 1);
9070 if n == 1 { pos = 1; }
9071 }
9072 let old_flags = sys_fcntl(fd, F_GETFL, 0);
9073 if old_flags >= 0 {
9074 let _ = sys_fcntl(fd, F_SETFL, old_flags | O_NONBLOCK as i64);
9075 }
9076 while pos < line.len() - 1 {
9077 let n = sys_read(fd as i64, line.as_mut_ptr().add(pos), line.len() - 1 - pos);
9078 if n <= 0 { break; }
9079 pos += n as usize;
9080 }
9081 if old_flags >= 0 {
9082 let _ = sys_fcntl(fd, F_SETFL, old_flags);
9083 }
9084 f._eof = 0;
9086 f._err = 0;
9087 f.flags &= !(F_EOF | F_ERR);
9088 }
9089
9090 line[pos] = 0;
9091 if pos == 0 { return 0; }
9092
9093 let mut consumed = 0usize;
9094 let assigned = do_vsscanf(line.as_ptr(), pos, fmt, &mut args, &mut consumed);
9095
9096 if start_pos >= 0 {
9097 let remaining = start_ungotten_count.saturating_sub(consumed);
9100 let target = start_pos + consumed as i64 + remaining as i64;
9103 if let Some(sfunc) = sfunc {
9104 sfunc(stream, target, SEEK_SET);
9105 }
9106 f.rpos = core::ptr::null_mut();
9107 f.rend = core::ptr::null_mut();
9108 if consumed < pos { f._eof = 0; }
9109 f.ungotten_count = 0;
9110 for i in 0..remaining {
9111 f.ungotten[f.ungotten_count as usize] = ungotten_saved[i];
9112 f.ungotten_count += 1;
9113 }
9114 } else {
9115 let unconsumed = pos.saturating_sub(consumed);
9117 if unconsumed > 0 && !f.buf.is_null() {
9118 let copy_count = core::cmp::min(unconsumed, f.buf_size);
9119 core::ptr::copy(
9120 line.as_ptr().add(consumed),
9121 f.buf,
9122 copy_count,
9123 );
9124 f.rpos = f.buf;
9125 f.rend = f.buf.add(copy_count);
9126 }
9127 f.ungotten_count = 0;
9128 f._eof = 0;
9129 f.flags &= !F_EOF;
9130 }
9131 assigned
9132}
9133
9134#[no_mangle]
9135pub unsafe extern "C" fn vscanf(fmt: *const c_char, args: VaList) -> c_int {
9136 vfscanf(stdin, fmt, args)
9137}
9138
9139#[no_mangle]
9140pub unsafe extern "C" fn sscanf(buf: *const c_char, fmt: *const c_char, mut args: ...) -> c_int {
9141 vsscanf_inner(buf as *const u8, fmt, &mut args)
9142}
9143
9144#[no_mangle]
9145pub unsafe extern "C" fn fscanf(stream: *mut FILE, fmt: *const c_char, args: ...) -> c_int {
9146 vfscanf(stream, fmt, args)
9147}
9148
9149#[no_mangle]
9150pub unsafe extern "C" fn scanf(fmt: *const c_char, args: ...) -> c_int {
9151 vfscanf(stdin, fmt, args)
9152}
9153
9154#[no_mangle]
9159pub unsafe extern "C" fn getdelim(
9160 lineptr: *mut *mut c_char, n: *mut usize, delim: c_int, stream: *mut FILE,
9161) -> isize {
9162 if lineptr.is_null() || n.is_null() { return -1; }
9163 let mut cap = *n;
9164 let mut buf = *lineptr;
9165 if buf.is_null() || cap == 0 {
9166 cap = 128;
9167 buf = realloc(buf as *mut c_void, cap) as *mut c_char;
9168 if buf.is_null() { return -1; }
9169 *lineptr = buf;
9170 *n = cap;
9171 }
9172 let mut len = 0usize;
9173 loop {
9174 let c = fgetc(stream);
9175 if c == -1 { if len == 0 { return -1; } break; }
9176 if len + 1 >= cap {
9177 let new_cap = cap.wrapping_mul(2);
9178 let new_buf = realloc(buf as *mut c_void, new_cap) as *mut c_char;
9179 if new_buf.is_null() { return -1; }
9180 buf = new_buf; cap = new_cap;
9181 *lineptr = buf; *n = cap;
9182 }
9183 *buf.add(len) = c as c_char;
9184 len += 1;
9185 if c == delim { break; }
9186 }
9187 *buf.add(len) = 0;
9188 len as isize
9189}
9190
9191#[no_mangle]
9192pub unsafe extern "C" fn getline(lineptr: *mut *mut c_char, n: *mut usize, stream: *mut FILE) -> isize {
9193 getdelim(lineptr, n, b'\n' as c_int, stream)
9194}
9195
9196#[no_mangle]
9201pub unsafe extern "C" fn popen(cmd: *const c_char, mode: *const c_char) -> *mut FILE {
9202 if cmd.is_null() || mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
9203 let m = *mode;
9204 if m != b'r' as c_char && m != b'w' as c_char { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
9205 let mut p: [c_int; 2] = [0; 2];
9206 if sys_pipe2(p.as_mut_ptr(), O_CLOEXEC) < 0 { return core::ptr::null_mut(); }
9207 let op = if m == b'r' as c_char { 0 } else { 1 };
9208 let child_fd = p[1 - op];
9209 let f = fdopen(p[op], mode);
9210 if f.is_null() { sys_close(p[0] as i64); sys_close(p[1] as i64); return core::ptr::null_mut(); }
9211 let pid = sys_fork();
9212 if pid < 0 { fclose(f); sys_close(child_fd as i64); return core::ptr::null_mut(); }
9213 if pid == 0 {
9214 sys_close(p[op] as i64);
9215 if child_fd != (1 - op) as c_int { sys_dup3(child_fd, (1 - op) as c_int, 0); sys_close(child_fd as i64); }
9216 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
9217 let argv = [b"sh\0".as_ptr() as *const c_char, b"-c\0".as_ptr() as *const c_char, cmd, core::ptr::null()];
9218 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
9219 _exit(127);
9220 }
9221 sys_close(child_fd as i64);
9222 (*f).pipe_pid = pid as c_int;
9223 f
9224}
9225
9226#[no_mangle]
9227pub unsafe extern "C" fn pclose(f: *mut FILE) -> c_int {
9228 let pid = (*f).pipe_pid;
9229 let r = fclose(f);
9230 if pid <= 0 { return -1; }
9231 let mut status: c_int = 0;
9232 let mut w: c_int;
9233 loop {
9234 w = waitpid(pid, &mut status, 0);
9235 if w >= 0 || ERRNO!() != EINTR_VAL { break; }
9236 }
9237 if w < 0 || r != 0 { return -1; }
9238 status
9239}
9240
9241const L_TMPNAM: usize = 20;
9246static mut TMPNAM_COUNTER: c_uint = 0;
9247
9248unsafe fn fill_tmpname(out: *mut c_char, seed: c_uint) {
9249 let prefix = b"/tmp/tmp\0";
9250 let mut k = 0;
9251 while k < prefix.len() - 1 { *out.add(k) = prefix[k] as c_char; k += 1; }
9252 let (buf, len) = format_hex(seed as u64, false);
9253 for j in 0..len.min(L_TMPNAM - k - 1) { *out.add(k + j) = buf[j] as c_char; k += 1; }
9254 *out.add(k) = 0;
9255}
9256
9257#[no_mangle]
9258pub unsafe extern "C" fn tmpfile() -> *mut FILE {
9259 let mut name = [0u8; L_TMPNAM];
9260 let mut ctr: c_uint = 0;
9261 loop {
9262 ctr = ctr.wrapping_add(1);
9263 let mut ts: timespec = core::mem::zeroed();
9264 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
9265 let seed = (ts.tv_nsec as c_uint).wrapping_add(ctr);
9266 fill_tmpname(name.as_mut_ptr() as *mut c_char, seed);
9267 let fd = sys_open(name.as_ptr(), (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
9268 if fd >= 0 {
9269 sys_unlinkat(AT_FDCWD, name.as_ptr(), 0);
9270 let f = fdopen(fd as c_int, b"w+\0".as_ptr() as *const c_char);
9271 if f.is_null() { sys_close(fd); }
9272 return f;
9273 }
9274 if ctr > 100 { return core::ptr::null_mut(); }
9275 }
9276}
9277
9278#[no_mangle]
9279pub unsafe extern "C" fn tmpnam(s: *mut c_char) -> *mut c_char {
9280 static mut BUF: [c_char; L_TMPNAM] = [0; L_TMPNAM];
9281 let out = if s.is_null() { core::ptr::addr_of_mut!(BUF) as *mut c_char } else { s };
9282 TMPNAM_COUNTER = TMPNAM_COUNTER.wrapping_add(1);
9283 let mut ts: timespec = core::mem::zeroed();
9284 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
9285 let seed = (ts.tv_nsec as c_uint).wrapping_add(TMPNAM_COUNTER);
9286 fill_tmpname(out, seed);
9287 out
9288}
9289
9290#[no_mangle]
9291pub unsafe extern "C" fn remove(path: *const c_char) -> c_int {
9292 if path.is_null() { ERRNO!() = EINVAL; return -1; }
9293 let r = sys_unlinkat(AT_FDCWD, path as *const u8, 0);
9294 if r == 0 {
9295 return 0;
9296 }
9297 if (-r) as c_int == 21 {
9300 return rmdir(path);
9301 }
9302 ERRNO!() = (-r) as c_int;
9303 -1
9304}
9305
9306#[no_mangle]
9307pub unsafe extern "C" fn rename(old: *const c_char, new_: *const c_char) -> c_int {
9308 if old.is_null() || new_.is_null() { ERRNO!() = EINVAL; return -1; }
9309 let r = sys_renameat2(AT_FDCWD, old as *const u8, AT_FDCWD, new_ as *const u8, 0);
9310 if r == 0 { 0 } else { ERRNO!() = (-r) as c_int; -1 }
9311}
9312
9313const MMAP_FAILED: *mut u8 = !0usize as *mut u8;
9318const PAGE: usize = 4096;
9319
9320#[no_mangle]
9325pub unsafe extern "C" fn _exit(code: c_int) -> ! {
9326 sys_exit_group(code)
9327}
9328
9329#[inline]
9330unsafe fn sys_exit_group(code: c_int) -> ! {
9331 <Arch as Syscalls>::syscall_noreturn1(SYS_EXIT_GROUP, code as i64)
9332}
9333
9334#[inline]
9335unsafe fn sys_exit_thread(code: c_int) -> ! {
9336 <Arch as Syscalls>::syscall_noreturn1(SYS_EXIT, code as i64)
9337}
9338
9339#[no_mangle]
9340pub unsafe extern "C" fn _Exit(code: c_int) -> ! {
9341 _exit(code);
9342}
9343
9344#[no_mangle]
9345pub unsafe extern "C" fn exit(code: c_int) -> ! {
9346 fflush(core::ptr::null_mut());
9347 __funcs_on_exit();
9348 _exit(code);
9349}
9350
9351#[no_mangle]
9352pub unsafe extern "C" fn abort() -> ! {
9353 raise(6); _exit(128 + 6);
9355}
9356
9357#[no_mangle]
9360pub static mut __stack_chk_guard: usize = 0;
9361
9362#[no_mangle]
9363pub unsafe extern "C" fn __stack_chk_fail() -> ! {
9364 const MSG: &[u8] = b"*** stack smashing detected ***: terminated\n";
9365 let _ = sys_write(2, MSG.as_ptr(), MSG.len());
9366 abort();
9367}
9368
9369#[no_mangle]
9370pub unsafe extern "C" fn __stack_chk_fail_local() -> ! {
9371 __stack_chk_fail()
9372}
9373
9374type CmpRfn = unsafe extern "C" fn(*const c_void, *const c_void, *mut c_void) -> c_int;
9379
9380const AR_LEN: usize = 16 * core::mem::size_of::<usize>();
9381const AR_MASK: usize = AR_LEN - 1;
9382
9383unsafe fn qsort_pntz(p: &[usize; 2]) -> i32 {
9384 if p[0] != 1 {
9385 p[0].wrapping_sub(1).trailing_zeros() as i32
9386 } else if p[1] != 0 {
9387 (8 * core::mem::size_of::<usize>()) as i32 + p[1].trailing_zeros() as i32
9388 } else {
9389 0
9390 }
9391}
9392
9393unsafe fn qsort_cycle(width: usize, ar: &mut [*mut u8; AR_LEN], n: usize) {
9394 if n < 2 { return; }
9395 let mut tmp = [0u8; 256];
9396 ar[n] = tmp.as_mut_ptr();
9397 let mut w = width;
9398 while w > 0 {
9399 let l = if 256 < w { 256 } else { w };
9400 core::ptr::copy_nonoverlapping(ar[0], ar[n], l);
9401 for i in 0..n {
9402 core::ptr::copy_nonoverlapping(ar[i + 1], ar[i], l);
9403 ar[i] = ar[i].add(l);
9404 }
9405 w -= l;
9406 }
9407}
9408
9409unsafe fn qsort_shl(p: &mut [usize; 2], n: i32) {
9410 let bits = (8 * core::mem::size_of::<usize>()) as i32;
9411 if n >= bits {
9412 p[1] = p[0];
9413 p[0] = 0;
9414 let n = n - bits;
9415 if n == 0 { return; }
9416 }
9417 p[1] = (p[1] << n) | (p[0] >> (bits - n));
9418 p[0] <<= n;
9419}
9420
9421unsafe fn qsort_shr(p: &mut [usize; 2], n: i32) {
9422 let bits = (8 * core::mem::size_of::<usize>()) as i32;
9423 if n >= bits {
9424 p[0] = p[1];
9425 p[1] = 0;
9426 let n = n - bits;
9427 if n == 0 { return; }
9428 }
9429 p[0] = (p[0] >> n) | (p[1] << (bits - n));
9430 p[1] >>= n;
9431}
9432
9433unsafe fn qsort_sift(
9434 head: *mut u8, width: usize,
9435 cmp: CmpRfn, arg: *mut c_void,
9436 pshift: i32, lp: &[usize],
9437) {
9438 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
9439 ar[0] = head;
9440 let mut i = 1usize;
9441 let mut h = head;
9442 let mut ps = pshift;
9443
9444 while ps > 1 {
9445 let rt = h.sub(width);
9446 let lf = h.sub(width + lp[(ps - 2) as usize]);
9447
9448 if cmp(ar[0] as *const c_void, lf as *const c_void, arg) >= 0
9449 && cmp(ar[0] as *const c_void, rt as *const c_void, arg) >= 0
9450 {
9451 break;
9452 }
9453 if cmp(lf as *const c_void, rt as *const c_void, arg) >= 0 {
9454 ar[i & AR_MASK] = lf;
9455 i += 1;
9456 h = lf;
9457 ps -= 1;
9458 } else {
9459 ar[i & AR_MASK] = rt;
9460 i += 1;
9461 h = rt;
9462 ps -= 2;
9463 }
9464 }
9465 qsort_cycle(width, &mut ar, i & AR_MASK);
9466}
9467
9468unsafe fn qsort_trinkle(
9469 head: *mut u8, width: usize,
9470 cmp: CmpRfn, arg: *mut c_void,
9471 pp: &[usize; 2], pshift: i32, trusty: i32,
9472 lp: &[usize],
9473) {
9474 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
9475 let mut p = *pp;
9476 ar[0] = head;
9477 let mut i = 1usize;
9478 let mut h = head;
9479 let mut ps = pshift;
9480 let mut t = trusty;
9481
9482 while p[0] != 1 || p[1] != 0 {
9483 let stepson = h.sub(lp[ps as usize]);
9484 if cmp(stepson as *const c_void, ar[0] as *const c_void, arg) <= 0 {
9485 break;
9486 }
9487 if t == 0 && ps > 1 {
9488 let rt = h.sub(width);
9489 let lf = h.sub(width + lp[(ps - 2) as usize]);
9490 if cmp(rt as *const c_void, stepson as *const c_void, arg) >= 0
9491 || cmp(lf as *const c_void, stepson as *const c_void, arg) >= 0
9492 {
9493 break;
9494 }
9495 }
9496
9497 ar[i & AR_MASK] = stepson;
9498 i += 1;
9499 h = stepson;
9500 let trail = qsort_pntz(&p);
9501 qsort_shr(&mut p, trail);
9502 ps += trail;
9503 t = 0;
9504 }
9505 if t == 0 {
9506 qsort_cycle(width, &mut ar, i & AR_MASK);
9507 qsort_sift(h, width, cmp, arg, ps, lp);
9508 }
9509}
9510
9511#[no_mangle]
9512pub unsafe extern "C" fn __qsort_r(
9513 base: *mut c_void,
9514 nel: usize,
9515 width: usize,
9516 cmp: CmpRfn,
9517 arg: *mut c_void,
9518) {
9519 let size = width * nel;
9520 if size == 0 { return; }
9521
9522 let mut lp = [0usize; 96];
9523 lp[0] = width;
9524 lp[1] = width;
9525 let mut li = 2;
9526 while {
9527 lp[li] = lp[li - 2] + lp[li - 1] + width;
9528 lp[li] < size
9529 } {
9530 li += 1;
9531 }
9532
9533 let mut head = base as *mut u8;
9534 let high = head.add(size - width);
9535 let mut p: [usize; 2] = [1, 0];
9536 let mut pshift: i32 = 1;
9537
9538 while head < high {
9539 if (p[0] & 3) == 3 {
9540 qsort_sift(head, width, cmp, arg, pshift, &lp);
9541 qsort_shr(&mut p, 2);
9542 pshift += 2;
9543 } else {
9544 if lp[(pshift - 1) as usize] >= (high as usize) - (head as usize) {
9545 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
9546 } else {
9547 qsort_sift(head, width, cmp, arg, pshift, &lp);
9548 }
9549
9550 if pshift == 1 {
9551 qsort_shl(&mut p, 1);
9552 pshift = 0;
9553 } else {
9554 qsort_shl(&mut p, pshift - 1);
9555 pshift = 1;
9556 }
9557 }
9558
9559 p[0] |= 1;
9560 head = head.add(width);
9561 }
9562
9563 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
9564
9565 while pshift != 1 || p[0] != 1 || p[1] != 0 {
9566 if pshift <= 1 {
9567 let trail = qsort_pntz(&p);
9568 qsort_shr(&mut p, trail);
9569 pshift += trail;
9570 } else {
9571 qsort_shl(&mut p, 2);
9572 pshift -= 2;
9573 p[0] ^= 7;
9574 qsort_shr(&mut p, 1);
9575 qsort_trinkle(
9576 head.sub(lp[pshift as usize] + width),
9577 width, cmp, arg, &p, pshift + 1, 1, &lp,
9578 );
9579 qsort_shl(&mut p, 1);
9580 p[0] |= 1;
9581 qsort_trinkle(head.sub(width), width, cmp, arg, &p, pshift, 1, &lp);
9582 }
9583 head = head.sub(width);
9584 }
9585}
9586
9587#[no_mangle]
9588pub unsafe extern "C" fn qsort_r(
9589 base: *mut c_void,
9590 nel: usize,
9591 width: usize,
9592 cmp: CmpRfn,
9593 arg: *mut c_void,
9594) {
9595 __qsort_r(base, nel, width, cmp, arg);
9596}
9597
9598unsafe extern "C" fn qsort_wrap_cmp(
9599 a: *const c_void,
9600 b: *const c_void,
9601 cmp_ctx: *mut c_void,
9602) -> c_int {
9603 let cmp: CmpFn = core::mem::transmute(cmp_ctx);
9604 cmp(a, b)
9605}
9606
9607#[no_mangle]
9608pub unsafe extern "C" fn qsort(
9609 base: *mut c_void,
9610 nel: usize,
9611 width: usize,
9612 cmp: CmpFn,
9613) {
9614 __qsort_r(base, nel, width, qsort_wrap_cmp, cmp as *mut c_void);
9615}
9616
9617const ATEXIT_COUNT: usize = 32;
9622
9623#[repr(C)]
9624struct AtExitBlock {
9625 next: *mut AtExitBlock,
9626 f: [Option<unsafe extern "C" fn(*mut c_void)>; ATEXIT_COUNT],
9627 a: [*mut c_void; ATEXIT_COUNT],
9628}
9629
9630static mut ATEXIT_BUILTIN: AtExitBlock = AtExitBlock {
9631 next: core::ptr::null_mut(),
9632 f: [None; ATEXIT_COUNT],
9633 a: [core::ptr::null_mut(); ATEXIT_COUNT],
9634};
9635static mut ATEXIT_HEAD: *mut AtExitBlock = core::ptr::null_mut();
9636static mut ATEXIT_SLOT: usize = 0;
9637static mut ATEXIT_FINISHED: bool = false;
9638
9639#[no_mangle]
9640pub unsafe extern "C" fn __funcs_on_exit() {
9641 while !ATEXIT_HEAD.is_null() {
9642 let head = ATEXIT_HEAD;
9643 while ATEXIT_SLOT > 0 {
9644 ATEXIT_SLOT -= 1;
9645 if let Some(f) = (*head).f[ATEXIT_SLOT] {
9646 let a = (*head).a[ATEXIT_SLOT];
9647 f(a);
9648 }
9649 }
9650 ATEXIT_HEAD = (*head).next;
9651 ATEXIT_SLOT = ATEXIT_COUNT;
9652 }
9653 ATEXIT_FINISHED = true;
9654}
9655
9656#[no_mangle]
9657pub unsafe extern "C" fn __cxa_atexit(
9658 func: unsafe extern "C" fn(*mut c_void),
9659 arg: *mut c_void,
9660 _dso: *mut c_void,
9661) -> c_int {
9662 if ATEXIT_FINISHED {
9663 return -1;
9664 }
9665 if ATEXIT_HEAD.is_null() {
9666 ATEXIT_HEAD = core::ptr::addr_of_mut!(ATEXIT_BUILTIN);
9667 }
9668 if ATEXIT_SLOT == ATEXIT_COUNT {
9669 let new = calloc(1, core::mem::size_of::<AtExitBlock>()) as *mut AtExitBlock;
9670 if new.is_null() {
9671 return -1;
9672 }
9673 (*new).next = ATEXIT_HEAD;
9674 ATEXIT_HEAD = new;
9675 ATEXIT_SLOT = 0;
9676 }
9677 (*ATEXIT_HEAD).f[ATEXIT_SLOT] = Some(func);
9678 (*ATEXIT_HEAD).a[ATEXIT_SLOT] = arg;
9679 ATEXIT_SLOT += 1;
9680 0
9681}
9682
9683unsafe extern "C" fn atexit_caller(arg: *mut c_void) {
9684 let func: unsafe extern "C" fn() = core::mem::transmute(arg);
9685 func();
9686}
9687
9688#[no_mangle]
9689pub unsafe extern "C" fn atexit(func: unsafe extern "C" fn()) -> c_int {
9690 __cxa_atexit(atexit_caller, func as *mut c_void, core::ptr::null_mut())
9691}
9692
9693#[no_mangle]
9694pub unsafe extern "C" fn __cxa_finalize(_dso: *mut c_void) {}
9695
9696#[no_mangle]
9701pub static mut __environ: *mut *mut c_char = core::ptr::null_mut();
9702
9703const ENV_MAX_ALLOCED: usize = 256;
9705static mut ENV_ALLOCED: [*mut c_char; ENV_MAX_ALLOCED] = [core::ptr::null_mut(); ENV_MAX_ALLOCED];
9706static mut ENV_ALLOCED_N: usize = 0;
9707
9708unsafe fn env_rm_add(old: *mut c_char, mut new: *mut c_char) {
9709 for i in 0..ENV_ALLOCED_N {
9710 if ENV_ALLOCED[i] == old {
9711 ENV_ALLOCED[i] = new;
9712 if !old.is_null() {
9713 free(old as *mut c_void);
9714 }
9715 return;
9716 } else if ENV_ALLOCED[i].is_null() && !new.is_null() {
9717 ENV_ALLOCED[i] = new;
9718 new = core::ptr::null_mut();
9719 }
9720 }
9721 if !new.is_null() && ENV_ALLOCED_N < ENV_MAX_ALLOCED {
9722 ENV_ALLOCED[ENV_ALLOCED_N] = new;
9723 ENV_ALLOCED_N += 1;
9724 }
9725}
9726
9727unsafe fn strchrnul_u8(s: *const u8, c: u8) -> *const u8 {
9728 let mut p = s;
9729 while *p != 0 && *p != c {
9730 p = p.add(1);
9731 }
9732 p
9733}
9734
9735#[no_mangle]
9736pub unsafe extern "C" fn getenv(name: *const c_char) -> *mut c_char {
9737 if __environ.is_null() || name.is_null() {
9738 return core::ptr::null_mut();
9739 }
9740 let name = name as *const u8;
9741 let l = strchrnul_u8(name, b'=') as usize - name as usize;
9742 if l == 0 || *name.add(l) != 0 {
9743 return core::ptr::null_mut();
9744 }
9745 let mut e = __environ;
9746 while !(*e).is_null() {
9747 let entry = *e as *const u8;
9748 if strncmp(entry, name, l) == 0 && *entry.add(l) == b'=' {
9749 return entry.add(l + 1) as *mut c_char;
9750 }
9751 e = e.add(1);
9752 }
9753 core::ptr::null_mut()
9754}
9755
9756#[no_mangle]
9757pub unsafe extern "C" fn setenv(
9758 var: *const c_char,
9759 value: *const c_char,
9760 overwrite: c_int,
9761) -> c_int {
9762 if var.is_null() || value.is_null() {
9763 ERRNO!() = EINVAL;
9764 return -1;
9765 }
9766 let var = var as *const u8;
9767 let l1 = strchrnul_u8(var, b'=') as usize - var as usize;
9768 if l1 == 0 || *var.add(l1) != 0 {
9769 ERRNO!() = EINVAL;
9770 return -1;
9771 }
9772 if overwrite == 0 && !getenv(var as *const c_char).is_null() {
9773 return 0;
9774 }
9775 let l2 = strlen(value as *const c_char);
9776 let s = malloc(l1 + l2 + 2) as *mut u8;
9777 if s.is_null() {
9778 return -1;
9779 }
9780 core::ptr::copy_nonoverlapping(var, s, l1);
9781 *s.add(l1) = b'=';
9782 core::ptr::copy_nonoverlapping(value as *const u8, s.add(l1 + 1), l2 + 1);
9783 putenv_internal(s as *mut c_char, l1, s as *mut c_char)
9784}
9785
9786unsafe fn putenv_internal(s: *mut c_char, l: usize, r: *mut c_char) -> c_int {
9787 let mut i = 0;
9788 if !__environ.is_null() {
9789 let mut e = __environ;
9790 while !(*e).is_null() {
9791 if strncmp(s as *const u8, *e as *const u8, l + 1) == 0 {
9792 let tmp = *e;
9793 *e = s;
9794 env_rm_add(tmp, r);
9795 return 0;
9796 }
9797 e = e.add(1);
9798 i += 1;
9799 }
9800 }
9801 let newenv = malloc(core::mem::size_of::<*mut c_char>() * (i + 2)) as *mut *mut c_char;
9802 if newenv.is_null() {
9803 if !r.is_null() { free(r as *mut c_void); }
9804 return -1;
9805 }
9806 if i > 0 && !__environ.is_null() {
9807 core::ptr::copy_nonoverlapping(__environ, newenv, i);
9808 }
9809 *newenv.add(i) = s;
9810 *newenv.add(i + 1) = core::ptr::null_mut();
9811 __environ = newenv;
9813 environ = __environ;
9814 if !r.is_null() {
9815 env_rm_add(core::ptr::null_mut(), r);
9816 }
9817 0
9818}
9819
9820#[no_mangle]
9821pub unsafe extern "C" fn putenv(s: *mut c_char) -> c_int {
9822 if s.is_null() { return -1; }
9823 let l = strchrnul_u8(s as *const u8, b'=') as usize - s as *const u8 as usize;
9824 if l == 0 || *s.add(l) as u8 == 0 {
9825 return unsetenv(s);
9826 }
9827 putenv_internal(s, l, core::ptr::null_mut())
9828}
9829
9830#[no_mangle]
9831pub unsafe extern "C" fn unsetenv(name: *const c_char) -> c_int {
9832 if name.is_null() {
9833 ERRNO!() = EINVAL;
9834 return -1;
9835 }
9836 let name = name as *const u8;
9837 let l = strchrnul_u8(name, b'=') as usize - name as usize;
9838 if l == 0 || *name.add(l) != 0 {
9839 ERRNO!() = EINVAL;
9840 return -1;
9841 }
9842 if __environ.is_null() {
9843 return 0;
9844 }
9845 let mut e = __environ;
9846 let mut eo = e;
9847 while !(*e).is_null() {
9848 if strncmp(name, *e as *const u8, l) == 0 && *(*e as *const u8).add(l) == b'=' {
9849 env_rm_add(*e, core::ptr::null_mut());
9850 } else {
9851 if eo != e {
9852 *eo = *e;
9853 }
9854 eo = eo.add(1);
9855 }
9856 e = e.add(1);
9857 }
9858 if eo != e {
9859 *eo = core::ptr::null_mut();
9860 }
9861 environ = __environ;
9862 0
9863}
9864
9865#[no_mangle]
9866pub unsafe extern "C" fn clearenv() -> c_int {
9867 let e = __environ;
9868 __environ = core::ptr::null_mut();
9869 environ = core::ptr::null_mut();
9870 if !e.is_null() {
9871 let mut p = e;
9872 while !(*p).is_null() {
9873 env_rm_add(*p, core::ptr::null_mut());
9874 p = p.add(1);
9875 }
9876 }
9877 0
9878}
9879
9880static mut RANDOM_INIT: [u32; 32] = [
9886 0x00000000,0x5851f42d,0xc0b18ccf,0xcbb5f646,
9887 0xc7033129,0x30705b04,0x20fd5db4,0x9a8b7f78,
9888 0x502959d8,0xab894868,0x6c0356a7,0x88cdb7ff,
9889 0xb477d43f,0x70a3a52b,0xa8e4baf1,0xfd8341fc,
9890 0x8ae16fd9,0x742d2f7a,0x0d1f0796,0x76035e09,
9891 0x40f7702c,0x6fa72ca5,0xaaa84157,0x58a0df74,
9892 0xc74a0364,0xae533cc4,0x04185faf,0x6de3b115,
9893 0x0cab8628,0xf043bfa4,0x398150e9,0x37521657,
9894];
9895
9896static mut RANDOM_N: i32 = 31;
9897static mut RANDOM_I: i32 = 3;
9898static mut RANDOM_J: i32 = 0;
9899static mut RANDOM_X: *mut u32 = unsafe { core::ptr::addr_of_mut!(RANDOM_INIT).cast::<u32>().add(1) };
9900
9901unsafe fn random_lcg31(x: u32) -> u32 {
9902 (1103515245u32.wrapping_mul(x).wrapping_add(12345)) & 0x7fffffff
9903}
9904
9905unsafe fn random_lcg64(x: u64) -> u64 {
9906 6364136223846793005u64.wrapping_mul(x).wrapping_add(1)
9907}
9908
9909unsafe fn random_savestate() -> *mut u8 {
9910 (*RANDOM_X.offset(-1)) = ((RANDOM_N as u32) << 16) | ((RANDOM_I as u32) << 8) | (RANDOM_J as u32);
9911 RANDOM_X.offset(-1) as *mut u8
9912}
9913
9914unsafe fn random_loadstate(state: *mut u32) {
9915 RANDOM_X = state.add(1);
9916 RANDOM_N = ((*RANDOM_X.offset(-1)) >> 16) as i32;
9917 RANDOM_I = (((*RANDOM_X.offset(-1)) >> 8) & 0xff) as i32;
9918 RANDOM_J = ((*RANDOM_X.offset(-1)) & 0xff) as i32;
9919}
9920
9921unsafe fn random_srandom_inner(seed: u32) {
9922 let mut s = seed as u64;
9923 if RANDOM_N == 0 {
9924 *RANDOM_X = s as u32;
9925 return;
9926 }
9927 RANDOM_I = if RANDOM_N == 31 || RANDOM_N == 7 { 3 } else { 1 };
9928 RANDOM_J = 0;
9929 for k in 0..RANDOM_N as usize {
9930 s = random_lcg64(s);
9931 *RANDOM_X.add(k) = (s >> 32) as u32;
9932 }
9933 *RANDOM_X |= 1;
9934}
9935
9936#[no_mangle]
9937pub unsafe extern "C" fn srandom(seed: c_uint) {
9938 random_srandom_inner(seed);
9939}
9940
9941#[no_mangle]
9942pub unsafe extern "C" fn initstate(seed: c_uint, state: *mut c_char, size: usize) -> *mut c_char {
9943 if size < 8 { return core::ptr::null_mut(); }
9944 let old = random_savestate();
9945 RANDOM_N = if size < 32 { 0 }
9946 else if size < 64 { 7 }
9947 else if size < 128 { 15 }
9948 else if size < 256 { 31 }
9949 else { 63 };
9950 RANDOM_X = (state as *mut u32).add(1);
9951 random_srandom_inner(seed);
9952 random_savestate();
9953 old as *mut c_char
9954}
9955
9956#[no_mangle]
9957pub unsafe extern "C" fn setstate(state: *mut c_char) -> *mut c_char {
9958 let old = random_savestate();
9959 random_loadstate(state as *mut u32);
9960 old as *mut c_char
9961}
9962
9963#[no_mangle]
9964pub unsafe extern "C" fn random() -> c_long {
9965 let k: c_long;
9966 if RANDOM_N == 0 {
9967 *RANDOM_X = random_lcg31(*RANDOM_X);
9968 k = *RANDOM_X as c_long;
9969 } else {
9970 *RANDOM_X.add(RANDOM_I as usize) = (*RANDOM_X.add(RANDOM_I as usize)).wrapping_add(*RANDOM_X.add(RANDOM_J as usize));
9971 k = (*RANDOM_X.add(RANDOM_I as usize) >> 1) as c_long;
9972 RANDOM_I += 1;
9973 if RANDOM_I == RANDOM_N { RANDOM_I = 0; }
9974 RANDOM_J += 1;
9975 if RANDOM_J == RANDOM_N { RANDOM_J = 0; }
9976 }
9977 k
9978}
9979
9980const SA: u8 = 0xC2;
9985const SB: u8 = 0xF4;
9986
9987const BITTAB: [u32; 51] = [
9988 0xC000_0002, 0xC000_0003, 0xC000_0004, 0xC000_0005, 0xC000_0006, 0xC000_0007,
9989 0xC000_0008, 0xC000_0009, 0xC000_000A, 0xC000_000B, 0xC000_000C, 0xC000_000D,
9990 0xC000_000E, 0xC000_000F, 0xC000_0010, 0xC000_0011, 0xC000_0012, 0xC000_0013,
9991 0xC000_0014, 0xC000_0015, 0xC000_0016, 0xC000_0017, 0xC000_0018, 0xC000_0019,
9992 0xC000_001A, 0xC000_001B, 0xC000_001C, 0xC000_001D, 0xC000_001E, 0xC000_001F,
9993 0xB300_0000, 0xC300_0001, 0xC300_0002, 0xC300_0003, 0xC300_0004, 0xC300_0005,
9994 0xC300_0006, 0xC300_0007, 0xC300_0008, 0xC300_0009, 0xC300_000A, 0xC300_000B,
9995 0xC300_000C, 0xD300_000D, 0xC300_000E, 0xC300_000F, 0xBB0C_0000, 0xC30C_0001,
9996 0xC30C_0002, 0xC30C_0003, 0xDB0C_0004,
9997];
9998
9999#[inline]
10000fn mb_oob(c: u32, b: u8) -> u32 {
10001 let b3 = (b >> 3) as u32;
10002 ((b3.wrapping_sub(0x10)) | (b3.wrapping_add((c as i32 >> 26) as u32))) & !7
10003}
10004
10005static mut MB_STATE: c_uint = 0;
10006
10007const MB_CUR_MAX_VAL_UTF8: usize = 4;
10008const MB_CUR_MAX_VAL_C: usize = 1;
10009
10010#[no_mangle]
10011pub extern "C" fn __ctype_get_mb_cur_max() -> usize {
10012 unsafe { if LOCALE_CTYPE_UTF8 { MB_CUR_MAX_VAL_UTF8 } else { MB_CUR_MAX_VAL_C } }
10013}
10014
10015#[no_mangle]
10016pub unsafe extern "C" fn mbrtowc(
10017 wc: *mut c_int,
10018 src: *const c_char,
10019 n: usize,
10020 st: *mut c_uint,
10021) -> usize {
10022 let s = src as *const u8;
10023 let n0 = n;
10024 let mut dummy: c_int = 0;
10025 let wc = if wc.is_null() { &mut dummy } else { &mut *wc };
10026 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
10027
10028 let mut c: u32 = *st;
10029 let mut s = s;
10030 let mut n = n;
10031
10032 if s.is_null() {
10033 if c != 0 { *st = 0; ERRNO!() = EILSEQ; return !0usize; }
10034 return 0;
10035 }
10036
10037 if n == 0 { return !1usize; }
10038
10039 if unsafe { !LOCALE_CTYPE_UTF8 } {
10040 let b = *s;
10041 *wc = b as c_int;
10042 return if b == 0 { 0 } else { 1 };
10043 }
10044
10045 if c == 0 {
10046 if *s < 0x80 {
10047 let r = if *s == 0 { 0 } else { 1 };
10048 *wc = *s as c_int;
10049 return r;
10050 }
10051 if (*s).wrapping_sub(SA) as u32 > (SB - SA) as u32 {
10052 *st = 0; ERRNO!() = EILSEQ; return !0usize;
10053 }
10054 c = BITTAB[*s as usize - SA as usize];
10055 s = s.add(1);
10056 n -= 1;
10057 }
10058
10059 if n > 0 {
10060 if mb_oob(c, *s) != 0 {
10061 *st = 0; ERRNO!() = EILSEQ; return !0usize;
10062 }
10063 loop {
10064 c = (c << 6) | (*s as u32).wrapping_sub(0x80);
10065 s = s.add(1);
10066 n -= 1;
10067 if c & (1u32 << 31) == 0 {
10068 *st = 0;
10069 *wc = c as c_int;
10070 return n0 - n;
10071 }
10072 if n == 0 { break; }
10073 if (*s).wrapping_sub(0x80) >= 0x40 {
10074 *st = 0; ERRNO!() = EILSEQ; return !0usize;
10075 }
10076 }
10077 }
10078
10079 *st = c;
10080 !1usize
10081}
10082
10083#[no_mangle]
10084pub unsafe extern "C" fn wcrtomb(
10085 s: *mut c_char,
10086 wc: c_int,
10087 _st: *mut c_uint,
10088) -> usize {
10089 if s.is_null() { return 1; }
10090 let wc_u = wc as u32;
10091 if unsafe { !LOCALE_CTYPE_UTF8 } {
10092 if wc_u > 0xFF {
10093 ERRNO!() = EILSEQ;
10094 return !0usize;
10095 }
10096 *s = wc as c_char;
10097 return 1;
10098 }
10099 if wc_u < 0x80 {
10100 *s = wc as c_char;
10101 return 1;
10102 }
10103 if wc_u < 0x800 {
10104 *s = (0xC0 | (wc_u >> 6)) as c_char;
10105 *s.add(1) = (0x80 | (wc_u & 0x3F)) as c_char;
10106 return 2;
10107 }
10108 if wc_u < 0xD800 || wc_u.wrapping_sub(0xE000) < 0x2000 {
10109 *s = (0xE0 | (wc_u >> 12)) as c_char;
10110 *s.add(1) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
10111 *s.add(2) = (0x80 | (wc_u & 0x3F)) as c_char;
10112 return 3;
10113 }
10114 if wc_u.wrapping_sub(0x10000) < 0x100000 {
10115 *s = (0xF0 | (wc_u >> 18)) as c_char;
10116 *s.add(1) = (0x80 | ((wc_u >> 12) & 0x3F)) as c_char;
10117 *s.add(2) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
10118 *s.add(3) = (0x80 | (wc_u & 0x3F)) as c_char;
10119 return 4;
10120 }
10121 ERRNO!() = EILSEQ;
10122 !0usize
10123}
10124
10125#[no_mangle]
10126pub unsafe extern "C" fn mblen(s: *const c_char, n: usize) -> c_int {
10127 if s.is_null() { return 0; }
10128 mbtowc(core::ptr::null_mut(), s, n)
10129}
10130
10131#[no_mangle]
10132pub unsafe extern "C" fn mbtowc(
10133 wc: *mut c_int,
10134 src: *const c_char,
10135 n: usize,
10136) -> c_int {
10137 if src.is_null() { return 0; }
10138 if n == 0 { ERRNO!() = EILSEQ; return -1; }
10139 let mut state: c_uint = 0;
10140 let mut w: c_int = 0;
10141 let r = mbrtowc(&mut w, src, n, &mut state);
10142 if r == !0usize { return -1; }
10143 if !wc.is_null() { *wc = w; }
10144 r as c_int
10145}
10146
10147#[no_mangle]
10148pub unsafe extern "C" fn wctomb(s: *mut c_char, wc: c_int) -> c_int {
10149 if s.is_null() { return 0; }
10150 wcrtomb(s, wc, core::ptr::null_mut()) as c_int
10151}
10152
10153#[no_mangle]
10154pub unsafe extern "C" fn mbsrtowcs(
10155 ws: *mut c_int,
10156 src: *mut *const c_char,
10157 wn: usize,
10158 st: *mut c_uint,
10159) -> usize {
10160 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
10161 let mut s = *src as *const u8;
10162 let wn0 = wn;
10163 let mut wn = wn;
10164
10165 if ws.is_null() {
10166 while *s != 0 {
10167 if *s < 0x80 {
10168 s = s.add(1);
10169 wn = wn.wrapping_sub(1);
10170 continue;
10171 }
10172 let mut wc: c_int = 0;
10173 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
10174 if r == !0usize { return !0usize; }
10175 if r == !1usize { return wn0 - wn; }
10176 s = s.add(r);
10177 wn = wn.wrapping_sub(1);
10178 }
10179 wn0 - wn
10180 } else {
10181 let mut w = ws;
10182 while wn > 0 {
10183 if *s < 0x80 {
10184 let c = *s as c_int;
10185 *w = c;
10186 if c == 0 {
10187 *src = core::ptr::null();
10188 return wn0 - wn;
10189 }
10190 w = w.add(1);
10191 s = s.add(1);
10192 wn -= 1;
10193 continue;
10194 }
10195 let mut wc: c_int = 0;
10196 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
10197 if r == !0usize {
10198 *src = s as *const c_char;
10199 return !0usize;
10200 }
10201 if r == !1usize {
10202 *src = s as *const c_char;
10203 return wn0 - wn;
10204 }
10205 *w = wc;
10206 w = w.add(1);
10207 s = s.add(r);
10208 wn -= 1;
10209 }
10210 *src = s as *const c_char;
10211 wn0 - wn
10212 }
10213}
10214
10215#[no_mangle]
10216pub unsafe extern "C" fn wcsrtombs(
10217 s: *mut c_char,
10218 ws: *mut *const c_int,
10219 n: usize,
10220 _st: *mut c_uint,
10221) -> usize {
10222 let mut w = *ws;
10223 let n0 = n;
10224 let mut n = n;
10225
10226 if s.is_null() {
10227 let mut count = 0usize;
10228 while *w != 0 {
10229 if (*w as u32) < 0x80 {
10230 count += 1;
10231 } else {
10232 let mut buf = [0u8; 4];
10233 let r = wcrtomb(buf.as_mut_ptr() as *mut c_char, *w, core::ptr::null_mut());
10234 if r == !0usize { return !0usize; }
10235 count += r;
10236 }
10237 w = w.add(1);
10238 }
10239 return count;
10240 }
10241
10242 let mut dst = s;
10243 while n > 0 {
10244 if (*w as u32) < 0x80 {
10245 *dst = *w as c_char;
10246 if *w == 0 {
10247 *ws = core::ptr::null();
10248 return n0 - n;
10249 }
10250 dst = dst.add(1);
10251 n -= 1;
10252 } else {
10253 let r = wcrtomb(dst, *w, core::ptr::null_mut());
10254 if r == !0usize {
10255 *ws = w;
10256 return !0usize;
10257 }
10258 if r > n {
10259 *ws = w;
10260 return n0 - n;
10261 }
10262 dst = dst.add(r);
10263 n -= r;
10264 }
10265 w = w.add(1);
10266 }
10267 *ws = w;
10268 n0
10269}
10270
10271#[no_mangle]
10272pub unsafe extern "C" fn mbstowcs(
10273 ws: *mut c_int,
10274 src: *const c_char,
10275 wn: usize,
10276) -> usize {
10277 let mut src_ptr = src;
10278 mbsrtowcs(ws, &mut src_ptr, wn, core::ptr::null_mut())
10279}
10280
10281#[no_mangle]
10282pub unsafe extern "C" fn wcstombs(
10283 s: *mut c_char,
10284 ws: *const c_int,
10285 n: usize,
10286) -> usize {
10287 let mut ws_ptr = ws;
10288 wcsrtombs(s, &mut ws_ptr, n, core::ptr::null_mut())
10289}
10290
10291#[no_mangle]
10296pub extern "C" fn btowc(c: c_int) -> wint_t {
10297 if c == -1 { return WEOF; }
10298 unsafe {
10299 if LOCALE_CTYPE_UTF8 {
10300 if (c as u32) < 128 { c as wint_t } else { WEOF }
10301 } else {
10302 (c as u8) as wint_t
10303 }
10304 }
10305}
10306
10307#[no_mangle]
10308pub extern "C" fn wctob(c: wint_t) -> c_int {
10309 unsafe {
10310 if LOCALE_CTYPE_UTF8 {
10311 if c < 128 { c as c_int } else { -1 }
10312 } else {
10313 if c <= 0xFF { c as c_int } else { -1 }
10314 }
10315 }
10316}
10317
10318#[no_mangle]
10319pub unsafe extern "C" fn mbsinit(s: *const c_uint) -> c_int {
10320 if s.is_null() || *s == 0 { 1 } else { 0 }
10321}
10322
10323#[no_mangle]
10324pub unsafe extern "C" fn mbrlen(s: *const c_char, n: usize, ps: *mut c_uint) -> usize {
10325 mbrtowc(core::ptr::null_mut(), s, n, ps)
10326}
10327
10328#[no_mangle]
10333pub unsafe extern "C" fn wcslen(s: *const wchar_t) -> usize {
10334 let mut len = 0;
10335 while *s.add(len) != 0 { len += 1; }
10336 len
10337}
10338
10339#[no_mangle]
10340pub unsafe extern "C" fn wcschr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
10341 let mut i = 0;
10342 loop {
10343 let ch = *s.add(i);
10344 if ch == c { return s.add(i) as *mut wchar_t; }
10345 if ch == 0 { return null_mut(); }
10346 i += 1;
10347 }
10348}
10349
10350#[no_mangle]
10351pub unsafe extern "C" fn wcsrchr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
10352 let mut i = 0;
10353 let mut last: *mut wchar_t = null_mut();
10354 loop {
10355 let ch = *s.add(i);
10356 if ch == c { last = s.add(i) as *mut wchar_t; }
10357 if ch == 0 { return last; }
10358 i += 1;
10359 }
10360}
10361
10362#[no_mangle]
10363pub unsafe extern "C" fn wcsstr(haystack: *const wchar_t, needle: *const wchar_t) -> *mut wchar_t {
10364 if *needle == 0 { return haystack as *mut wchar_t; }
10365 let mut i = 0;
10366 loop {
10367 let h = *haystack.add(i);
10368 if h == 0 { return null_mut(); }
10369 if h == *needle {
10370 let mut j = 0;
10371 loop {
10372 let n = *needle.add(j);
10373 if n == 0 { return haystack.add(i) as *mut wchar_t; }
10374 if *haystack.add(i + j) != n { break; }
10375 j += 1;
10376 }
10377 }
10378 i += 1;
10379 }
10380}
10381
10382#[no_mangle]
10383pub unsafe extern "C" fn wcscmp(s1: *const wchar_t, s2: *const wchar_t) -> c_int {
10384 let mut i = 0;
10385 loop {
10386 let a = *s1.add(i);
10387 let b = *s2.add(i);
10388 if a != b { return a - b; }
10389 if a == 0 { return 0; }
10390 i += 1;
10391 }
10392}
10393
10394#[no_mangle]
10395pub unsafe extern "C" fn wcsncmp(s1: *const wchar_t, s2: *const wchar_t, n: usize) -> c_int {
10396 let mut i = 0;
10397 while i < n {
10398 let a = *s1.add(i);
10399 let b = *s2.add(i);
10400 if a != b { return a - b; }
10401 if a == 0 { return 0; }
10402 i += 1;
10403 }
10404 0
10405}
10406
10407#[no_mangle]
10408pub unsafe extern "C" fn wcscpy(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
10409 let mut i = 0;
10410 loop {
10411 let c = *src.add(i);
10412 *dst.add(i) = c;
10413 if c == 0 { break; }
10414 i += 1;
10415 }
10416 dst
10417}
10418
10419#[no_mangle]
10420pub unsafe extern "C" fn wcsncpy(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
10421 let mut i = 0;
10422 while i < n && *src.add(i) != 0 { *dst.add(i) = *src.add(i); i += 1; }
10423 while i < n { *dst.add(i) = 0; i += 1; }
10424 dst
10425}
10426
10427#[no_mangle]
10428pub unsafe extern "C" fn wcscat(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
10429 let mut i = 0;
10430 while *dst.add(i) != 0 { i += 1; }
10431 let mut j = 0;
10432 loop {
10433 let c = *src.add(j);
10434 *dst.add(i + j) = c;
10435 if c == 0 { break; }
10436 j += 1;
10437 }
10438 dst
10439}
10440
10441#[no_mangle]
10442pub unsafe extern "C" fn wcsncat(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
10443 let mut i = 0;
10444 while *dst.add(i) != 0 { i += 1; }
10445 let mut j = 0;
10446 while j < n && *src.add(j) != 0 { *dst.add(i + j) = *src.add(j); j += 1; }
10447 *dst.add(i + j) = 0;
10448 dst
10449}
10450
10451#[no_mangle]
10452pub unsafe extern "C" fn wcsdup(s: *const wchar_t) -> *mut wchar_t {
10453 let len = wcslen(s);
10454 let p = malloc((len + 1) * core::mem::size_of::<wchar_t>()) as *mut wchar_t;
10455 if p.is_null() { return null_mut(); }
10456 core::ptr::copy_nonoverlapping(s, p, len + 1);
10457 p
10458}
10459
10460#[no_mangle]
10461pub unsafe extern "C" fn wcsnlen(s: *const wchar_t, maxlen: usize) -> usize {
10462 let mut i = 0;
10463 while i < maxlen && *s.add(i) != 0 { i += 1; }
10464 i
10465}
10466
10467#[no_mangle]
10468pub unsafe extern "C" fn wcsspn(s: *const wchar_t, accept: *const wchar_t) -> usize {
10469 let mut i = 0;
10470 loop {
10471 let c = *s.add(i);
10472 if c == 0 { return i; }
10473 let mut found = false;
10474 let mut j = 0;
10475 loop {
10476 let a = *accept.add(j);
10477 if a == 0 { break; }
10478 if c == a { found = true; break; }
10479 j += 1;
10480 }
10481 if !found { return i; }
10482 i += 1;
10483 }
10484}
10485
10486#[no_mangle]
10487pub unsafe extern "C" fn wcscspn(s: *const wchar_t, reject: *const wchar_t) -> usize {
10488 let mut i = 0;
10489 loop {
10490 let c = *s.add(i);
10491 if c == 0 { return i; }
10492 let mut j = 0;
10493 loop {
10494 let r = *reject.add(j);
10495 if r == 0 { break; }
10496 if c == r { return i; }
10497 j += 1;
10498 }
10499 i += 1;
10500 }
10501}
10502
10503#[no_mangle]
10504pub unsafe extern "C" fn wcspbrk(s: *const wchar_t, accept: *const wchar_t) -> *mut wchar_t {
10505 let mut i = 0;
10506 loop {
10507 let c = *s.add(i);
10508 if c == 0 { return null_mut(); }
10509 let mut j = 0;
10510 loop {
10511 let a = *accept.add(j);
10512 if a == 0 { break; }
10513 if c == a { return s.add(i) as *mut wchar_t; }
10514 j += 1;
10515 }
10516 i += 1;
10517 }
10518}
10519
10520#[no_mangle]
10521pub unsafe extern "C" fn wcsxfrm(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> usize {
10522 let len = wcslen(src);
10523 if !dst.is_null() {
10524 let copy = if len < n { len } else { if n > 0 { n - 1 } else { 0 } };
10525 for i in 0..copy { *dst.add(i) = *src.add(i); }
10526 if n > 0 { *dst.add(copy) = 0; }
10527 }
10528 len
10529}
10530
10531unsafe fn wcs_to_bytes(ws: *const wchar_t, buf: *mut u8, bufsz: usize) -> usize {
10536 let mut i = 0;
10537 while i < bufsz - 1 {
10538 let c = *ws.add(i);
10539 if c == 0 { break; }
10540 if (c as u32) > 127 { break; }
10541 *buf.add(i) = c as u8;
10542 i += 1;
10543 }
10544 *buf.add(i) = 0;
10545 i
10546}
10547
10548#[no_mangle]
10549pub unsafe extern "C" fn wcstol(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_long {
10550 let mut buf = [0u8; 256];
10551 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10552 let mut end: *mut c_char = core::ptr::null_mut();
10553 let r = strtol(buf.as_ptr() as *const c_char, &mut end, base);
10554 if !endptr.is_null() {
10555 let offset = end as usize - buf.as_ptr() as usize;
10556 *endptr = s.add(offset) as *mut wchar_t;
10557 }
10558 r
10559}
10560
10561#[no_mangle]
10562pub unsafe extern "C" fn wcstoul(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulong {
10563 let mut buf = [0u8; 256];
10564 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10565 let mut end: *mut c_char = core::ptr::null_mut();
10566 let r = strtoul(buf.as_ptr() as *const c_char, &mut end, base);
10567 if !endptr.is_null() {
10568 let offset = end as usize - buf.as_ptr() as usize;
10569 *endptr = s.add(offset) as *mut wchar_t;
10570 }
10571 r
10572}
10573
10574#[no_mangle]
10575pub unsafe extern "C" fn wcstoll(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong {
10576 let mut buf = [0u8; 256];
10577 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10578 let mut end: *mut c_char = core::ptr::null_mut();
10579 let r = strtoll(buf.as_ptr() as *const c_char, &mut end, base);
10580 if !endptr.is_null() {
10581 let offset = end as usize - buf.as_ptr() as usize;
10582 *endptr = s.add(offset) as *mut wchar_t;
10583 }
10584 r
10585}
10586
10587#[no_mangle]
10588pub unsafe extern "C" fn wcstoull(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong {
10589 let mut buf = [0u8; 256];
10590 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10591 let mut end: *mut c_char = core::ptr::null_mut();
10592 let r = strtoull(buf.as_ptr() as *const c_char, &mut end, base);
10593 if !endptr.is_null() {
10594 let offset = end as usize - buf.as_ptr() as usize;
10595 *endptr = s.add(offset) as *mut wchar_t;
10596 }
10597 r
10598}
10599
10600#[no_mangle]
10601pub unsafe extern "C" fn wcstod(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 {
10602 let mut buf = [0u8; 256];
10603 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10604 let mut end: *mut c_char = core::ptr::null_mut();
10605 let r = strtod(buf.as_ptr() as *const c_char, &mut end);
10606 if !endptr.is_null() {
10607 let offset = end as usize - buf.as_ptr() as usize;
10608 *endptr = s.add(offset) as *mut wchar_t;
10609 }
10610 r
10611}
10612
10613#[no_mangle]
10614pub unsafe extern "C" fn wcstof(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f32 { wcstod(s, endptr) as f32 }
10615
10616#[no_mangle]
10617#[cfg(target_arch = "x86_64")]
10618pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 { wcstod(s, endptr) }
10619
10620#[no_mangle]
10621#[cfg(target_arch = "aarch64")]
10622pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
10623
10624#[no_mangle]
10625#[cfg(target_arch = "riscv64")]
10626pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
10627
10628#[no_mangle]
10629pub unsafe extern "C" fn wcstoimax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong { wcstoll(s, endptr, base) }
10630
10631#[no_mangle]
10632pub unsafe extern "C" fn wcstoumax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong { wcstoull(s, endptr, base) }
10633
10634const WC_ALPHA: c_int = 1;
10639const WC_DIGIT: c_int = 2;
10640const WC_SPACE: c_int = 4;
10641const WC_UPPER: c_int = 8;
10642const WC_LOWER: c_int = 16;
10643const WC_ALNUM: c_int = WC_ALPHA | WC_DIGIT;
10644const WC_BLANK: c_int = 32;
10645const WC_CNTRL: c_int = 64;
10646const WC_PUNCT: c_int = 128;
10647const WC_GRAPH: c_int = WC_ALNUM | WC_PUNCT;
10648const WC_PRINT: c_int = WC_GRAPH | WC_BLANK;
10649const WC_XDIGIT: c_int = 256;
10650
10651fn wc_flags(c: wint_t) -> c_int {
10652 if c < 128 {
10653 let f = CT_TABLE[c as usize];
10654 let mut r = 0;
10655 if f & (CT_UPPER | CT_LOWER) != 0 { r |= WC_ALPHA; }
10656 if f & CT_DIGIT != 0 { r |= WC_DIGIT; }
10657 if f & CT_SPACE != 0 { r |= WC_SPACE; }
10658 if f & CT_UPPER != 0 { r |= WC_UPPER; }
10659 if f & CT_LOWER != 0 { r |= WC_LOWER; }
10660 if f & CT_BLANK != 0 { r |= WC_BLANK; }
10661 if f & CT_CNTRL != 0 { r |= WC_CNTRL; }
10662 if f & CT_PUNCT != 0 { r |= WC_PUNCT; }
10663 if f & CT_XDIGIT != 0 { r |= WC_XDIGIT; }
10664 r
10665 } else {
10666 if c < 0x100 { 0 }
10667 else { WC_PRINT | WC_ALPHA }
10668 }
10669}
10670
10671#[no_mangle]
10672pub extern "C" fn iswalnum(c: wint_t) -> c_int { (wc_flags(c) & WC_ALNUM != 0) as c_int }
10673#[no_mangle]
10674pub extern "C" fn iswalpha(c: wint_t) -> c_int { (wc_flags(c) & WC_ALPHA != 0) as c_int }
10675#[no_mangle]
10676pub extern "C" fn iswblank(c: wint_t) -> c_int { (wc_flags(c) & WC_BLANK != 0) as c_int }
10677#[no_mangle]
10678pub extern "C" fn iswcntrl(c: wint_t) -> c_int { (wc_flags(c) & WC_CNTRL != 0) as c_int }
10679#[no_mangle]
10680pub extern "C" fn iswdigit(c: wint_t) -> c_int { ((c >= b'0' as wint_t) && (c <= b'9' as wint_t)) as c_int }
10681#[no_mangle]
10682pub extern "C" fn iswgraph(c: wint_t) -> c_int { (wc_flags(c) & WC_GRAPH != 0) as c_int }
10683#[no_mangle]
10684pub extern "C" fn iswlower(c: wint_t) -> c_int { (wc_flags(c) & WC_LOWER != 0) as c_int }
10685#[no_mangle]
10686pub extern "C" fn iswprint(c: wint_t) -> c_int {
10687 if c < 128 { (wc_flags(c) & WC_PRINT != 0) as c_int }
10688 else if c >= 0x100 && c < 0x110000 { 1 }
10689 else { 0 }
10690}
10691#[no_mangle]
10692pub extern "C" fn iswpunct(c: wint_t) -> c_int { (wc_flags(c) & WC_PUNCT != 0) as c_int }
10693#[no_mangle]
10694pub extern "C" fn iswspace(c: wint_t) -> c_int {
10695 if c < 128 { (wc_flags(c) & WC_SPACE != 0) as c_int }
10696 else {
10697 match c {
10698 0x1680 | 0x2000..=0x200A | 0x2028 | 0x2029 | 0x202F | 0x205F | 0x3000 => 1,
10699 _ => 0,
10700 }
10701 }
10702}
10703#[no_mangle]
10704pub extern "C" fn iswupper(c: wint_t) -> c_int { (wc_flags(c) & WC_UPPER != 0) as c_int }
10705#[no_mangle]
10706pub extern "C" fn iswxdigit(c: wint_t) -> c_int { (wc_flags(c) & WC_XDIGIT != 0) as c_int }
10707
10708static WCTYPE_ALNUM: c_int = WC_ALNUM;
10709static WCTYPE_ALPHA: c_int = WC_ALPHA;
10710static WCTYPE_BLANK: c_int = WC_BLANK;
10711static WCTYPE_CNTRL: c_int = WC_CNTRL;
10712static WCTYPE_DIGIT: c_int = WC_DIGIT;
10713static WCTYPE_GRAPH: c_int = WC_GRAPH;
10714static WCTYPE_LOWER: c_int = WC_LOWER;
10715static WCTYPE_PRINT: c_int = WC_PRINT;
10716static WCTYPE_PUNCT: c_int = WC_PUNCT;
10717static WCTYPE_SPACE: c_int = WC_SPACE;
10718static WCTYPE_UPPER: c_int = WC_UPPER;
10719static WCTYPE_XDIGIT: c_int = WC_XDIGIT;
10720
10721#[no_mangle]
10722pub unsafe extern "C" fn wctype(name: *const c_char) -> wctype_t {
10723 if name.is_null() { return core::ptr::null(); }
10724 let n = name as *const u8;
10725 if strcmp(n, b"alnum\0".as_ptr()) == 0 { return &WCTYPE_ALNUM; }
10726 if strcmp(n, b"alpha\0".as_ptr()) == 0 { return &WCTYPE_ALPHA; }
10727 if strcmp(n, b"blank\0".as_ptr()) == 0 { return &WCTYPE_BLANK; }
10728 if strcmp(n, b"cntrl\0".as_ptr()) == 0 { return &WCTYPE_CNTRL; }
10729 if strcmp(n, b"digit\0".as_ptr()) == 0 { return &WCTYPE_DIGIT; }
10730 if strcmp(n, b"graph\0".as_ptr()) == 0 { return &WCTYPE_GRAPH; }
10731 if strcmp(n, b"lower\0".as_ptr()) == 0 { return &WCTYPE_LOWER; }
10732 if strcmp(n, b"print\0".as_ptr()) == 0 { return &WCTYPE_PRINT; }
10733 if strcmp(n, b"punct\0".as_ptr()) == 0 { return &WCTYPE_PUNCT; }
10734 if strcmp(n, b"space\0".as_ptr()) == 0 { return &WCTYPE_SPACE; }
10735 if strcmp(n, b"upper\0".as_ptr()) == 0 { return &WCTYPE_UPPER; }
10736 if strcmp(n, b"xdigit\0".as_ptr()) == 0 { return &WCTYPE_XDIGIT; }
10737 core::ptr::null()
10738}
10739
10740#[no_mangle]
10741pub unsafe extern "C" fn iswctype(c: wint_t, desc: wctype_t) -> c_int {
10742 if desc.is_null() { return 0; }
10743 (wc_flags(c) & *desc != 0) as c_int
10744}
10745
10746static WCTRANS_LOWER: c_int = 1;
10747static WCTRANS_UPPER: c_int = 2;
10748
10749#[no_mangle]
10750pub unsafe extern "C" fn towlower(c: wint_t) -> wint_t {
10751 if c < 128 { tolower(c as c_int) as wint_t } else { c }
10752}
10753
10754#[no_mangle]
10755pub unsafe extern "C" fn towupper(c: wint_t) -> wint_t {
10756 if c < 128 { toupper(c as c_int) as wint_t } else { c }
10757}
10758
10759#[no_mangle]
10760pub unsafe extern "C" fn wctrans(name: *const c_char) -> wctrans_t {
10761 if name.is_null() { return core::ptr::null(); }
10762 let n = name as *const u8;
10763 if strcmp(n, b"tolower\0".as_ptr()) == 0 { return &WCTRANS_LOWER; }
10764 if strcmp(n, b"toupper\0".as_ptr()) == 0 { return &WCTRANS_UPPER; }
10765 core::ptr::null()
10766}
10767
10768#[no_mangle]
10769pub unsafe extern "C" fn towctrans(c: wint_t, desc: wctrans_t) -> wint_t {
10770 if desc.is_null() { return c; }
10771 match *desc {
10772 1 => towlower(c),
10773 2 => towupper(c),
10774 _ => c,
10775 }
10776}
10777
10778#[no_mangle]
10783pub unsafe extern "C" fn fgetwc(f: *mut FILE) -> wint_t {
10784 let mut state: c_uint = 0;
10785 let mut wc: wchar_t = 0;
10786 let mut buf = [0u8; 4];
10787 let c = fgetc(f);
10788 if c == -1 { return WEOF; }
10789 buf[0] = c as u8;
10790 if buf[0] < 0x80 { return buf[0] as wint_t; }
10791 let len = if buf[0] < 0xE0 { 2 } else if buf[0] < 0xF0 { 3 } else { 4 };
10792 let mut n = 1usize;
10793 while n < len {
10794 let c2 = fgetc(f);
10795 if c2 == -1 { return WEOF; }
10796 buf[n] = c2 as u8;
10797 n += 1;
10798 }
10799 let r = mbrtowc(&mut wc, buf.as_ptr() as *const c_char, n, &mut state);
10800 if r == !0usize || r == !1usize { WEOF } else { wc as wint_t }
10801}
10802
10803#[no_mangle]
10804pub unsafe extern "C" fn fputwc(c: wchar_t, f: *mut FILE) -> wint_t {
10805 let mut buf = [0u8; 4];
10806 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c, core::ptr::null_mut());
10807 if n == !0usize || n == 0 { return WEOF; }
10808 if fwrite(buf.as_ptr() as *const c_void, 1, n, f) != n { return WEOF; }
10809 c as wint_t
10810}
10811
10812#[no_mangle]
10813pub unsafe extern "C" fn fputws(s: *const wchar_t, f: *mut FILE) -> c_int {
10814 let mut i = 0;
10815 while *s.add(i) != 0 {
10816 if fputwc(*s.add(i), f) == WEOF { return -1; }
10817 i += 1;
10818 }
10819 0
10820}
10821
10822#[no_mangle]
10823pub unsafe extern "C" fn ungetwc(c: wint_t, f: *mut FILE) -> wint_t {
10824 if c == WEOF { return WEOF; }
10825 let mut buf = [0u8; 4];
10826 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c as wchar_t, core::ptr::null_mut());
10827 if n == !0usize || n == 0 { return WEOF; }
10828 let mut i = n;
10829 while i > 0 {
10830 i -= 1;
10831 if ungetc(buf[i] as c_int, f) == -1 { return WEOF; }
10832 }
10833 c
10834}
10835
10836#[no_mangle]
10837pub unsafe extern "C" fn getwchar() -> wint_t { fgetwc(stdin) }
10838
10839#[no_mangle]
10840pub unsafe extern "C" fn putwchar(c: wchar_t) -> wint_t { fputwc(c, stdout) }
10841
10842unsafe fn wfmt_write_str(dst: *mut wchar_t, pos: usize, cap: usize, s: *const u8, len: usize) -> usize {
10847 let mut i = 0;
10848 while i < len {
10849 if pos + i < cap { *dst.add(pos + i) = *s.add(i) as wchar_t; }
10850 i += 1;
10851 }
10852 pos + len
10853}
10854
10855#[no_mangle]
10856pub unsafe extern "C" fn vswprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, mut args: VaList) -> c_int {
10857 if n == 0 { return -1; }
10858 let cap = n - 1;
10859 let mut pos = 0usize;
10860 let mut fmt_narrow = [0u8; 256];
10862 let mut flen = 0usize;
10863 loop {
10864 let ch = *fmt.add(flen) as u32;
10865 if ch == 0 || flen >= 255 { break; }
10866 fmt_narrow[flen] = if ch < 128 { ch as u8 } else { b'?' };
10867 flen += 1;
10868 }
10869 fmt_narrow[flen] = 0;
10870 let mut fi = 0usize;
10871 macro_rules! wc {
10872 ($c:expr) => { if pos < cap { *s.add(pos) = $c as wchar_t; } pos += 1; }
10873 }
10874 loop {
10875 let c = fmt_narrow[fi];
10876 if c == 0 { break; }
10877 if c != b'%' { wc!(c); fi += 1; continue; }
10878 fi += 1;
10879 let mut flags: u8 = 0;
10880 loop {
10881 match fmt_narrow[fi] {
10882 b'-' => { flags |= FLAG_MINUS; fi += 1; }
10883 b'+' => { flags |= FLAG_PLUS; fi += 1; }
10884 b' ' => { flags |= FLAG_SPACE; fi += 1; }
10885 b'0' => { flags |= FLAG_ZERO; fi += 1; }
10886 b'#' => { flags |= FLAG_HASH; fi += 1; }
10887 _ => break,
10888 }
10889 }
10890 let mut width: usize = 0;
10891 if fmt_narrow[fi] == b'*' {
10892 let w = args.next_arg::<c_int>();
10893 if w < 0 { flags |= FLAG_MINUS; width = (-w) as usize; } else { width = w as usize; }
10894 fi += 1;
10895 } else {
10896 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10897 width = width * 10 + (fmt_narrow[fi] - b'0') as usize; fi += 1;
10898 }
10899 }
10900 let mut precision: i32 = -1;
10901 if fmt_narrow[fi] == b'.' {
10902 fi += 1;
10903 if fmt_narrow[fi] == b'*' {
10904 let p = args.next_arg::<c_int>();
10905 precision = if p < 0 { -1 } else { p }; fi += 1;
10906 } else {
10907 precision = 0;
10908 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10909 precision = precision * 10 + (fmt_narrow[fi] - b'0') as i32; fi += 1;
10910 }
10911 }
10912 }
10913 let len_mod = fmt_narrow[fi];
10914 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' {
10915 fi += 1;
10916 let spec = fmt_narrow[fi];
10917 if (len_mod == b'h' && spec == b'h') || (len_mod == b'l' && spec == b'l') {
10918 fi += 1;
10919 let spec2 = fmt_narrow[fi];
10920 match (len_mod, spec, spec2) {
10921 (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; } }
10922 (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; } }
10923 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
10924 let val = args.next_arg::<c_longlong>();
10925 let neg = val < 0;
10926 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10927 let b = format_u64(abs);
10928 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10929 let mut fbuf = [0u8; 32];
10930 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10931 for k in 0..len { wc!(fbuf[k]); }
10932 }
10933 (b'l', b'l', b'u') => {
10934 let val = args.next_arg::<c_ulonglong>();
10935 let b = format_u64(val as u64);
10936 let mut fbuf = [0u8; 32];
10937 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10938 for k in 0..len { wc!(fbuf[k]); }
10939 }
10940 (b'l', b'l', b'x') => {
10941 let val = args.next_arg::<c_ulonglong>();
10942 let b = format_hex(val as u64, false);
10943 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10944 let mut fbuf = [0u8; 32];
10945 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10946 for k in 0..len { wc!(fbuf[k]); }
10947 }
10948 (b'l', b'l', b'X') => {
10949 let val = args.next_arg::<c_ulonglong>();
10950 let b = format_hex(val as u64, true);
10951 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10952 let mut fbuf = [0u8; 32];
10953 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10954 for k in 0..len { wc!(fbuf[k]); }
10955 }
10956 (b'l', b'l', b'o') => {
10957 let val = args.next_arg::<c_ulonglong>();
10958 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10959 let mut fbuf = [0u8; 32];
10960 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10961 for k in 0..len { wc!(fbuf[k]); }
10962 }
10963 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); wc!(spec2); }
10964 }
10965 } else {
10966 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
10967 match (lm, spec) {
10968 (b'h', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut u16) = pos as u16; } }
10969 (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; } }
10970 (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; } }
10971 (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; } }
10972 (b'l', b'd') | (b'l', b'i') => {
10973 let val = args.next_arg::<c_long>();
10974 let neg = val < 0;
10975 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10976 let b = format_u64(abs);
10977 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10978 let mut fbuf = [0u8; 32];
10979 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10980 for k in 0..len { wc!(fbuf[k]); }
10981 }
10982 (b'l', b'u') => {
10983 let val = args.next_arg::<c_ulong>();
10984 let b = format_u64(val as u64);
10985 let mut fbuf = [0u8; 32];
10986 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10987 for k in 0..len { wc!(fbuf[k]); }
10988 }
10989 (b'l', b'x') => {
10990 let val = args.next_arg::<c_ulong>();
10991 let b = format_hex(val as u64, false);
10992 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10993 let mut fbuf = [0u8; 32];
10994 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10995 for k in 0..len { wc!(fbuf[k]); }
10996 }
10997 (b'l', b'X') => {
10998 let val = args.next_arg::<c_ulong>();
10999 let b = format_hex(val as u64, true);
11000 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
11001 let mut fbuf = [0u8; 32];
11002 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
11003 for k in 0..len { wc!(fbuf[k]); }
11004 }
11005 (b'l', b'o') => {
11006 let val = args.next_arg::<c_ulong>();
11007 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
11008 let mut fbuf = [0u8; 32];
11009 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
11010 for k in 0..len { wc!(fbuf[k]); }
11011 }
11012 (b'l', b'c') => {
11013 let ch = args.next_arg::<wint_t>();
11014 wc!(ch);
11015 }
11016 (b'l', b's') => {
11017 let ws_arg = args.next_arg::<*const wchar_t>();
11018 if ws_arg.is_null() {
11019 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
11020 if flags & FLAG_MINUS != 0 {
11021 for k in 0..slen { wc!(b"(null)"[k]); }
11022 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
11023 } else {
11024 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
11025 for k in 0..slen { wc!(b"(null)"[k]); }
11026 }
11027 } else {
11028 let mut wlen = 0usize;
11029 loop {
11030 let ch = *ws_arg.add(wlen);
11031 if ch == 0 { break; }
11032 if precision >= 0 && wlen >= precision as usize { break; }
11033 wlen += 1;
11034 }
11035 if flags & FLAG_MINUS != 0 {
11036 for k in 0..wlen { wc!(*ws_arg.add(k)); }
11037 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
11038 } else {
11039 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
11040 for k in 0..wlen { wc!(*ws_arg.add(k)); }
11041 }
11042 }
11043 }
11044 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
11045 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
11046 let val = args.next_arg::<f64>();
11047 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
11048 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
11049 let mut fbuf = [0u8; 4224];
11050 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
11051 let mut wbuf = [0u8; 4224];
11052 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
11053 for k in 0..wlen { wc!(wbuf[k]); }
11054 }
11055 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
11056 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
11057 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
11058 let val = {
11059 let lo: u64 = args.next_arg::<u64>();
11060 let hi: u64 = args.next_arg::<u64>();
11061 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
11062 f128::from_bits(combined) as f64
11063 };
11064 #[cfg(target_arch = "x86_64")]
11065 let val = args.next_arg::<f64>();
11066 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
11067 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
11068 let mut fbuf = [0u8; 4224];
11069 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
11070 let mut wbuf = [0u8; 4224];
11071 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
11072 for k in 0..wlen { wc!(wbuf[k]); }
11073 }
11074 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
11075 }
11076 }
11077 } else {
11078 let spec = fmt_narrow[fi];
11079 match spec {
11080 b'd' | b'i' => {
11081 let d = args.next_arg::<c_int>();
11082 let neg = d < 0;
11083 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
11084 let b = format_u64(abs);
11085 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
11086 let mut fbuf = [0u8; 32];
11087 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
11088 for k in 0..len { wc!(fbuf[k]); }
11089 }
11090 b'u' => {
11091 let u = args.next_arg::<c_uint>();
11092 let b = format_u64(u as u64);
11093 let mut fbuf = [0u8; 32];
11094 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
11095 for k in 0..len { wc!(fbuf[k]); }
11096 }
11097 b'x' => {
11098 let x = args.next_arg::<c_uint>();
11099 let b = format_hex(x as u64, false);
11100 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
11101 let mut fbuf = [0u8; 32];
11102 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
11103 for k in 0..len { wc!(fbuf[k]); }
11104 }
11105 b'X' => {
11106 let x = args.next_arg::<c_uint>();
11107 let b = format_hex(x as u64, true);
11108 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
11109 let mut fbuf = [0u8; 32];
11110 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
11111 for k in 0..len { wc!(fbuf[k]); }
11112 }
11113 b'o' => {
11114 let o = args.next_arg::<c_uint>();
11115 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
11116 let mut fbuf = [0u8; 32];
11117 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
11118 for k in 0..len { wc!(fbuf[k]); }
11119 }
11120 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
11121 let val = args.next_arg::<f64>();
11122 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
11123 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
11124 let mut fbuf = [0u8; 4224];
11125 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
11126 let mut wbuf = [0u8; 4224];
11127 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
11128 for k in 0..wlen { wc!(wbuf[k]); }
11129 }
11130 b'c' => {
11131 let ch = args.next_arg::<c_int>();
11132 wc!(ch as u8);
11133 }
11134 b's' => {
11135 let p = args.next_arg::<*const c_char>();
11136 if p.is_null() {
11137 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
11138 if flags & FLAG_MINUS != 0 {
11139 for k in 0..slen { wc!(b"(null)"[k]); }
11140 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
11141 } else {
11142 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
11143 for k in 0..slen { wc!(b"(null)"[k]); }
11144 }
11145 } else {
11146 let mut wbuf_local = [0i32; 256];
11147 let mut wcount = 0usize;
11148 let mut byte_pos = 0usize;
11149 let pbytes = p as *const u8;
11150 loop {
11151 if precision >= 0 && wcount >= precision as usize { break; }
11152 if wcount >= 256 { break; }
11153 let mut wc_val: c_int = 0;
11154 let consumed = mbrtowc(&mut wc_val as *mut c_int, p.add(byte_pos) as *const c_char, 256, core::ptr::null_mut());
11155 if consumed == !0usize || consumed == !1usize {
11156 wbuf_local[wcount] = *pbytes.add(byte_pos) as c_int;
11157 byte_pos += 1;
11158 wcount += 1;
11159 } else if consumed == 0 {
11160 break;
11161 } else {
11162 wbuf_local[wcount] = wc_val;
11163 byte_pos += consumed;
11164 wcount += 1;
11165 }
11166 }
11167 if flags & FLAG_MINUS != 0 {
11168 for k in 0..wcount { wc!(wbuf_local[k]); }
11169 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
11170 } else {
11171 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
11172 for k in 0..wcount { wc!(wbuf_local[k]); }
11173 }
11174 }
11175 }
11176 b'p' => {
11177 wc!(b'0'); wc!(b'x');
11178 let p = args.next_arg::<*const c_void>();
11179 let b = format_hex(p as u64, false);
11180 for k in 0..b.1 { wc!(b.0[k]); }
11181 }
11182 b'n' => {
11183 let p = args.next_arg::<*mut c_void>();
11184 if !p.is_null() { *(p as *mut c_int) = pos as c_int; }
11185 }
11186 b'%' => { wc!(b'%'); }
11187 _ => { wc!(b'%'); wc!(spec); }
11188 }
11189 }
11190 fi += 1;
11191 }
11192 let null_pos = if pos < cap { pos } else { cap };
11193 *s.add(null_pos) = 0;
11194 if pos > cap { -1 } else { pos as c_int }
11195}
11196
11197#[no_mangle]
11198pub unsafe extern "C" fn swprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, args: ...) -> c_int {
11199 vswprintf(s, n, fmt, args)
11200}
11201
11202#[no_mangle]
11203pub unsafe extern "C" fn vfwprintf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int {
11204 let mut buf = [0i32; 4096];
11205 let r = vswprintf(buf.as_mut_ptr(), 4096, fmt, args);
11206 if r < 0 { return r; }
11207 let mut i = 0;
11208 while i < r as usize {
11209 let mut mb = [0u8; 4];
11210 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, buf[i], core::ptr::null_mut());
11211 if n == !0usize { return -1; }
11212 if fwrite(mb.as_ptr() as *const c_void, 1, n, f) != n { return -1; }
11213 i += 1;
11214 }
11215 r
11216}
11217
11218#[no_mangle]
11219pub unsafe extern "C" fn fwprintf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
11220 vfwprintf(f, fmt, args)
11221}
11222
11223unsafe fn wcsfmt_to_mbs(dst: *mut u8, dst_len: usize, src: *const wchar_t) {
11229 let mut i = 0usize;
11230 loop {
11231 let ch = *src.add(i) as u32;
11232 if ch == 0 || i >= dst_len - 1 { break; }
11233 *dst.add(i) = if ch < 128 { ch as u8 } else { b'?' };
11234 i += 1;
11235 }
11236 *dst.add(i) = 0;
11237}
11238
11239#[no_mangle]
11240pub unsafe extern "C" fn vswscanf(s: *const wchar_t, fmt: *const wchar_t, mut args: VaList) -> c_int {
11241 let mut mbs_buf = [0u8; 4096];
11242 let mut i = 0usize;
11243 let mut mb_pos = 0usize;
11244 loop {
11245 let wc = *s.add(i) as c_int;
11246 if wc == 0 { break; }
11247 let mut mb = [0u8; 4];
11248 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, wc, core::ptr::null_mut());
11249 if n == !0usize || n == 0 { break; }
11250 if mb_pos + n >= mbs_buf.len() { break; }
11251 let mut k = 0usize;
11252 while k < n { mbs_buf[mb_pos + k] = mb[k]; k += 1; }
11253 mb_pos += n;
11254 i += 1;
11255 }
11256 mbs_buf[mb_pos] = 0;
11257 let mut mbs_fmt = [0u8; 4096];
11258 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
11259 do_vsscanf(mbs_buf.as_ptr(), mb_pos, mbs_fmt.as_ptr() as *const c_char, &mut args, core::ptr::null_mut())
11260}
11261
11262#[no_mangle]
11263pub unsafe extern "C" fn swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int {
11264 vswscanf(s, fmt, args)
11265}
11266
11267#[no_mangle]
11268pub unsafe extern "C" fn vfwscanf(f: *mut FILE, fmt: *const wchar_t, mut args: VaList) -> c_int {
11269 let start_pos = ftello(f);
11270 if start_pos < 0 { return -1; }
11271 let mut buf = [0u8; 4096];
11272 let mut n = 0usize;
11273 loop {
11274 if n >= buf.len() - 1 { break; }
11275 let c = fgetc(f);
11276 if c == -1 { break; }
11277 buf[n] = c as u8;
11278 n += 1;
11279 }
11280 buf[n] = 0;
11281 let mut mbs_fmt = [0u8; 4096];
11282 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
11283 let mut consumed = 0usize;
11284 let hit_eof = (*f)._eof != 0;
11285 let result = do_vsscanf(buf.as_ptr(), n, mbs_fmt.as_ptr() as *const c_char, &mut args, &mut consumed);
11286 let _ = fseeko(f, start_pos + consumed as i64, SEEK_SET);
11287 if hit_eof && consumed == n {
11288 (*f)._eof = 1;
11289 }
11290 result
11291}
11292
11293#[no_mangle]
11294pub unsafe extern "C" fn fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
11295 vfwscanf(f, fmt, args)
11296}
11297
11298#[no_mangle]
11299pub unsafe extern "C" fn vwscanf(fmt: *const wchar_t, args: VaList) -> c_int {
11300 vfwscanf(stdin, fmt, args)
11301}
11302
11303#[no_mangle]
11304pub unsafe extern "C" fn wscanf(fmt: *const wchar_t, args: ...) -> c_int {
11305 vfwscanf(stdin, fmt, args)
11306}
11307
11308const LEAPOCH: i64 = 946684800 + 86400 * (31 + 29);
11313const DAYS_PER_400Y: i64 = 365 * 400 + 97;
11314const DAYS_PER_100Y: i64 = 365 * 100 + 24;
11315const DAYS_PER_4Y: i64 = 365 * 4 + 1;
11316
11317const SECS_THROUGH_MONTH: [i32; 12] = [
11318 0, 31*86400, 59*86400, 90*86400, 120*86400, 151*86400,
11319 181*86400, 212*86400, 243*86400, 273*86400, 304*86400, 334*86400,
11320];
11321
11322const DAYS_IN_MONTH: [i32; 12] = [31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29];
11323
11324unsafe fn year_to_secs(year: i64, is_leap: &mut bool) -> i64 {
11325 if year - 2 <= 136 {
11326 let y = year as i32;
11327 let mut leaps = (y - 68) >> 2;
11328 if (y - 68) & 3 == 0 { leaps -= 1; *is_leap = true; } else { *is_leap = false; }
11329 return 31536000 * (y as i64 - 70) + 86400 * leaps as i64;
11330 }
11331 let mut cycles = ((year - 100) / 400) as i32;
11332 let mut rem = ((year - 100) % 400) as i32;
11333 if rem < 0 { cycles -= 1; rem += 400; }
11334 let (centuries, leaps);
11335 if rem == 0 { *is_leap = true; centuries = 0; leaps = 0; }
11336 else {
11337 let c;
11338 if rem >= 200 { if rem >= 300 { c = 3; rem -= 300; } else { c = 2; rem -= 200; } }
11339 else { if rem >= 100 { c = 1; rem -= 100; } else { c = 0; } }
11340 centuries = c;
11341 if rem == 0 { *is_leap = false; leaps = 0; }
11342 else { leaps = rem / 4; rem %= 4; *is_leap = rem == 0; }
11343 }
11344 let total_leaps = leaps + 97 * cycles + 24 * centuries - (*is_leap as i32);
11345 (year - 100) * 31536000 + total_leaps as i64 * 86400 + 946684800 + 86400
11346}
11347
11348fn month_to_secs(month: i32, is_leap: bool) -> i32 {
11349 let mut t = SECS_THROUGH_MONTH[month as usize];
11350 if is_leap && month >= 2 { t += 86400; }
11351 t
11352}
11353
11354unsafe fn secs_to_tm(t: i64, tm: &mut tm) -> bool {
11355 if t < (i32::MIN as i64) * 31622400 || t > (i32::MAX as i64) * 31622400 { return false; }
11356 let secs = t - LEAPOCH;
11357 let mut days = secs / 86400;
11358 let mut remsecs = (secs % 86400) as i32;
11359 if remsecs < 0 { remsecs += 86400; days -= 1; }
11360 let mut wday = ((3 + days) % 7) as i32;
11361 if wday < 0 { wday += 7; }
11362 let mut qc_cycles = (days / DAYS_PER_400Y) as i32;
11363 let mut remdays = (days % DAYS_PER_400Y) as i32;
11364 if remdays < 0 { remdays += DAYS_PER_400Y as i32; qc_cycles -= 1; }
11365 let mut c_cycles = remdays / DAYS_PER_100Y as i32;
11366 if c_cycles == 4 { c_cycles -= 1; }
11367 remdays -= c_cycles * DAYS_PER_100Y as i32;
11368 let mut q_cycles = remdays / DAYS_PER_4Y as i32;
11369 if q_cycles == 25 { q_cycles -= 1; }
11370 remdays -= q_cycles * DAYS_PER_4Y as i32;
11371 let mut remyears = remdays / 365;
11372 if remyears == 4 { remyears -= 1; }
11373 remdays -= remyears * 365;
11374 let leap = remyears == 0 && (q_cycles != 0 || c_cycles == 0);
11375 let mut yday = remdays + 31 + 28 + leap as i32;
11376 if yday >= 365 + leap as i32 { yday -= 365 + leap as i32; }
11377 let years = remyears as i64 + 4 * q_cycles as i64 + 100 * c_cycles as i64 + 400 * qc_cycles as i64;
11378 let mut months = 0i32;
11379 let mut rd = remdays;
11380 for m in 0..12 {
11381 if DAYS_IN_MONTH[m] <= rd { rd -= DAYS_IN_MONTH[m]; } else { months = m as i32; break; }
11382 }
11383 let mut adj_years = years;
11384 if months >= 10 { months -= 12; adj_years += 1; }
11385 if adj_years + 100 > i32::MAX as i64 || adj_years + 100 < i32::MIN as i64 { return false; }
11386 tm.tm_year = (adj_years + 100) as c_int;
11387 tm.tm_mon = months + 2;
11388 tm.tm_mday = rd + 1;
11389 tm.tm_wday = wday;
11390 tm.tm_yday = yday;
11391 tm.tm_hour = remsecs / 3600;
11392 tm.tm_min = remsecs / 60 % 60;
11393 tm.tm_sec = remsecs % 60;
11394 true
11395}
11396
11397unsafe fn tm_to_secs(tm: *const tm) -> i64 {
11398 let mut year = (*tm).tm_year as i64;
11399 let mut month = (*tm).tm_mon;
11400 if month >= 12 || month < 0 {
11401 let adj = month / 12;
11402 month %= 12;
11403 if month < 0 { month += 12; }
11404 year += adj as i64;
11405 }
11406 let mut is_leap = false;
11407 let mut t = year_to_secs(year, &mut is_leap);
11408 t += month_to_secs(month, is_leap) as i64;
11409 t += 86400 * ((*tm).tm_mday - 1) as i64;
11410 t += 3600 * (*tm).tm_hour as i64;
11411 t += 60 * (*tm).tm_min as i64;
11412 t += (*tm).tm_sec as i64;
11413 t
11414}
11415
11416static mut TM_BUF: tm = tm {
11417 tm_sec: 0, tm_min: 0, tm_hour: 0, tm_mday: 0, tm_mon: 0,
11418 tm_year: 0, tm_wday: 0, tm_yday: 0, tm_isdst: 0,
11419 tm_gmtoff: 0, tm_zone: core::ptr::null(),
11420};
11421
11422static mut UTC_STR: [c_char; 4] = [b'U' as c_char, b'T' as c_char, b'C' as c_char, 0];
11423
11424const CLOCK_PROCESS_CPUTIME_ID: c_int = 2;
11425
11426#[no_mangle]
11431pub unsafe extern "C" fn time(t: *mut TimeT) -> TimeT {
11432 let mut ts: timespec = core::mem::zeroed();
11433 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
11434 if !t.is_null() { *t = ts.tv_sec; }
11435 ts.tv_sec
11436}
11437
11438#[no_mangle]
11439pub unsafe extern "C" fn difftime(t1: TimeT, t0: TimeT) -> f64 {
11440 (t1 as i64 - t0 as i64) as f64
11441}
11442
11443#[no_mangle]
11444pub unsafe extern "C" fn clock() -> ClockT {
11445 let mut ts: timespec = core::mem::zeroed();
11446 let _ = sys_clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &mut ts);
11447 ts.tv_sec * 1000000 + ts.tv_nsec / 1000
11448}
11449
11450#[no_mangle]
11451pub unsafe extern "C" fn gmtime(t: *const TimeT) -> *mut tm {
11452 gmtime_r(t, &raw mut TM_BUF)
11453}
11454
11455#[no_mangle]
11456pub unsafe extern "C" fn gmtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm {
11457 if !secs_to_tm(*t as i64, &mut *tm) { ERRNO!() = EOVERFLOW; return core::ptr::null_mut(); }
11458 (*tm).tm_isdst = 0;
11459 (*tm).tm_gmtoff = 0;
11460 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11461 tm
11462}
11463
11464#[no_mangle]
11465pub unsafe extern "C" fn localtime(t: *const TimeT) -> *mut tm { gmtime(t) }
11466
11467#[no_mangle]
11468pub unsafe extern "C" fn localtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm { gmtime_r(t, tm) }
11469
11470#[no_mangle]
11471pub unsafe extern "C" fn mktime(tm: *mut tm) -> TimeT {
11472 let t = tm_to_secs(tm as *const tm);
11473 if !secs_to_tm(t, &mut *tm) { ERRNO!() = EOVERFLOW; return -1; }
11474 (*tm).tm_isdst = 0;
11475 (*tm).tm_gmtoff = 0;
11476 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11477 t as TimeT
11478}
11479
11480#[no_mangle]
11481pub unsafe extern "C" fn timegm(tm: *mut tm) -> TimeT {
11482 let t = tm_to_secs(tm as *const tm);
11483 if !secs_to_tm(t, &mut *tm) { ERRNO!() = EOVERFLOW; return -1; }
11484 (*tm).tm_isdst = 0;
11485 (*tm).tm_gmtoff = 0;
11486 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11487 t as TimeT
11488}
11489
11490static mut ASCTIME_BUF: [c_char; 26] = [0; 26];
11491
11492const 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"];
11493const 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"];
11494
11495#[no_mangle]
11496pub unsafe extern "C" fn asctime(tm: *const tm) -> *mut c_char {
11497 asctime_r(tm, core::ptr::addr_of_mut!(ASCTIME_BUF).cast::<c_char>())
11498}
11499
11500#[no_mangle]
11501pub unsafe extern "C" fn asctime_r(tm: *const tm, buf: *mut c_char) -> *mut c_char {
11502 let wday = if (*tm).tm_wday >= 0 && (*tm).tm_wday < 7 { (*tm).tm_wday as usize } else { 0 };
11503 let mon = if (*tm).tm_mon >= 0 && (*tm).tm_mon < 12 { (*tm).tm_mon as usize } else { 0 };
11504 let dn = DAY_NAMES[wday];
11505 let mn = MON_NAMES[mon];
11506 let mut p = 0;
11507 for k in 0..3 { *buf.add(p) = *dn.as_ptr().add(k) as c_char; p += 1; }
11508 *buf.add(p) = b' ' as c_char; p += 1;
11509 for k in 0..3 { *buf.add(p) = *mn.as_ptr().add(k) as c_char; p += 1; }
11510 *buf.add(p) = b' ' as c_char; p += 1;
11511 let v = (*tm).tm_mday;
11512 *buf.add(p) = (b'0' + (v / 10) as u8) as c_char; p += 1;
11513 *buf.add(p) = (b'0' + (v % 10) as u8) as c_char; p += 1;
11514 *buf.add(p) = b' ' as c_char; p += 1;
11515 let hh = (*tm).tm_hour;
11516 *buf.add(p) = (b'0' + (hh / 10) as u8) as c_char; p += 1;
11517 *buf.add(p) = (b'0' + (hh % 10) as u8) as c_char; p += 1;
11518 *buf.add(p) = b':' as c_char; p += 1;
11519 let mm = (*tm).tm_min;
11520 *buf.add(p) = (b'0' + (mm / 10) as u8) as c_char; p += 1;
11521 *buf.add(p) = (b'0' + (mm % 10) as u8) as c_char; p += 1;
11522 *buf.add(p) = b':' as c_char; p += 1;
11523 let ss = (*tm).tm_sec;
11524 *buf.add(p) = (b'0' + (ss / 10) as u8) as c_char; p += 1;
11525 *buf.add(p) = (b'0' + (ss % 10) as u8) as c_char; p += 1;
11526 *buf.add(p) = b' ' as c_char; p += 1;
11527 let yr = (*tm).tm_year + 1900;
11528 let mut tmp = [0u8; 4];
11529 let mut v2 = yr;
11530 for k in (0..4).rev() { tmp[k] = b'0' + (v2 % 10) as u8; v2 /= 10; }
11531 for k in 0..4 { *buf.add(p) = tmp[k] as c_char; p += 1; }
11532 *buf.add(p) = b'\n' as c_char; p += 1;
11533 *buf.add(p) = 0;
11534 buf
11535}
11536
11537#[no_mangle]
11538pub unsafe extern "C" fn ctime(t: *const TimeT) -> *mut c_char { asctime(gmtime(t)) }
11539
11540#[no_mangle]
11541pub unsafe extern "C" fn ctime_r(t: *const TimeT, buf: *mut c_char) -> *mut c_char {
11542 let mut tmp: tm = core::mem::zeroed();
11543 gmtime_r(t, &mut tmp);
11544 asctime_r(&tmp, buf)
11545}
11546
11547unsafe fn sys_clock_getres(clockid: c_int, ts: *mut timespec) -> i64 {
11552 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, clockid as i64, ts as i64)
11553}
11554
11555unsafe fn sys_clock_settime(clockid: c_int, ts: *const timespec) -> i64 {
11556 <Arch as Syscalls>::syscall2(SYS_CLOCK_SETTIME, clockid as i64, ts as i64)
11557}
11558
11559unsafe fn sys_clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> i64 {
11560 <Arch as Syscalls>::syscall4(SYS_CLOCK_NANOSLEEP, clockid as i64, flags as i64, req as i64, rem as i64)
11561}
11562
11563#[no_mangle]
11564pub unsafe extern "C" fn clock_getres(clockid: c_int, ts: *mut timespec) -> c_int {
11565 let r = sys_clock_getres(clockid, ts);
11566 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
11567}
11568
11569#[no_mangle]
11570pub unsafe extern "C" fn clock_settime(clockid: c_int, ts: *const timespec) -> c_int {
11571 let r = sys_clock_settime(clockid, ts);
11572 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
11573}
11574
11575#[no_mangle]
11576pub unsafe extern "C" fn clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> c_int {
11577 let r = sys_clock_nanosleep(clockid, flags, req, rem);
11578 if r < 0 {
11579 let e = (-r) as c_int;
11580 if clockid == 3 && e == 95 { return 22; }
11583 e
11584 } else {
11585 0
11586 }
11587}
11588
11589#[no_mangle]
11590pub unsafe extern "C" fn gettimeofday(tv: *mut timeval, _tz: *mut c_void) -> c_int {
11591 if tv.is_null() { return 0; }
11592 let mut ts: timespec = core::mem::zeroed();
11593 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
11594 (*tv).tv_sec = ts.tv_sec;
11595 (*tv).tv_usec = ts.tv_nsec / 1000;
11596 0
11597}
11598
11599fn is_leap_year(y: i32) -> bool {
11604 let yr = if y > i32::MAX - 1900 { y - 2000 } else { y + 1900 };
11605 yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0)
11606}
11607
11608fn week_num(tm: &tm) -> i32 {
11609 let mut val = (tm.tm_yday + 7 - ((tm.tm_wday + 6) % 7)) / 7;
11610 if (tm.tm_wday + 371 - tm.tm_yday - 2).rem_euclid(7) <= 2 { val += 1; }
11611 if val == 0 {
11612 val = 52;
11613 let dec31 = (tm.tm_wday + 7 - tm.tm_yday - 1).rem_euclid(7);
11614 if dec31 == 4 || (dec31 == 5 && is_leap_year(tm.tm_year % 400 - 1)) { val += 1; }
11615 } else if val == 53 {
11616 let jan1 = (tm.tm_wday + 371 - tm.tm_yday).rem_euclid(7);
11617 if jan1 != 4 && (jan1 != 3 || !is_leap_year(tm.tm_year)) { val = 1; }
11618 }
11619 val
11620}
11621
11622const ABDAY_1: c_int = 0x20000;
11624const DAY_1: c_int = 0x20007;
11625const ABMON_1: c_int = 0x2000E;
11626const MON_1: c_int = 0x2001A;
11627const AM_STR_LI: c_int = 0x20026;
11628const PM_STR_LI: c_int = 0x20027;
11629const D_T_FMT: c_int = 0x20028;
11630const D_FMT: c_int = 0x20029;
11631const T_FMT: c_int = 0x2002A;
11632const T_FMT_AMPM: c_int = 0x2002B;
11633
11634unsafe fn num_fmt(buf: &mut [u8; 100], val: i64, pad: u8, width: usize) -> (*const u8, usize) {
11637 let negative = val < 0;
11638 let mut v = if negative { -val as u64 } else { val as u64 };
11639 let mut tmp = [0u8; 24];
11640 let mut pos = 24usize;
11641 if v == 0 { pos -= 1; tmp[pos] = b'0'; }
11642 while v > 0 { pos -= 1; tmp[pos] = b'0' + (v % 10) as u8; v /= 10; }
11643 let digits = 24 - pos;
11644 let sign_chars = if negative { 1 } else { 0 };
11645 let needed = sign_chars + digits;
11646 let fill = if width > needed { width - needed } else { 0 };
11647 let total = fill + needed;
11648 let mut p = 0usize;
11649 match pad {
11650 b'-' => { }
11651 b'_' => {
11652 for _ in 0..fill { buf[p] = b' '; p += 1; }
11653 if negative { buf[p] = b'-'; p += 1; }
11654 }
11655 _ => {
11656 if negative { buf[p] = b'-'; p += 1; }
11657 for _ in 0..fill { buf[p] = b'0'; p += 1; }
11658 }
11659 }
11660 for i in 0..digits { buf[p] = tmp[pos + i]; p += 1; }
11661 (buf.as_ptr(), total)
11662}
11663
11664unsafe fn str_to_buf(buf: &mut [u8; 100], s: *const c_char) -> (*const u8, usize) {
11666 let mut k = 0usize;
11667 while *s.add(k) != 0 {
11668 buf[k] = *s.add(k) as u8;
11669 k += 1;
11670 }
11671 (buf.as_ptr(), k)
11672}
11673
11674unsafe fn __strftime_fmt_1(buf: &mut [u8; 100], f: u8, tm: *const tm, pad: u8) -> (*const u8, usize) {
11677 let mut val: i64;
11678 let mut width: usize = 2;
11679 let mut def_pad: u8 = b'0';
11680 let fmt: *const c_char;
11681
11682 match f {
11683 b'a' => {
11684 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
11685 let p = nl_langinfo(ABDAY_1 + (*tm).tm_wday);
11686 return str_to_buf(buf, p);
11687 }
11688 b'A' => {
11689 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
11690 let p = nl_langinfo(DAY_1 + (*tm).tm_wday);
11691 return str_to_buf(buf, p);
11692 }
11693 b'h' | b'b' => {
11694 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11695 let p = nl_langinfo(ABMON_1 + (*tm).tm_mon);
11696 return str_to_buf(buf, p);
11697 }
11698 b'B' => {
11699 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11700 let p = nl_langinfo(MON_1 + (*tm).tm_mon);
11701 return str_to_buf(buf, p);
11702 }
11703 b'c' => {
11704 let p = nl_langinfo(D_T_FMT);
11705 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11706 return (buf.as_ptr(), l);
11707 }
11708 b'C' => {
11709 val = (1900i64 + (*tm).tm_year as i64) / 100;
11710 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11711 }
11712 b'e' => { def_pad = b'_'; }
11713 b'd' => {
11714 val = (*tm).tm_mday as i64;
11715 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11716 }
11717 b'D' => {
11718 fmt = b"%m/%d/%y\0".as_ptr() as *const c_char;
11719 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11720 return (buf.as_ptr(), l);
11721 }
11722 b'F' => {
11723 fmt = b"%Y-%m-%d\0".as_ptr() as *const c_char;
11724 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11725 return (buf.as_ptr(), l);
11726 }
11727 b'g' | b'G' => {
11728 val = (*tm).tm_year as i64 + 1900;
11729 if (*tm).tm_yday < 3 && week_num(&*tm) != 1 { val -= 1; }
11730 else if (*tm).tm_yday > 360 && week_num(&*tm) == 1 { val += 1; }
11731 if f == b'g' { val %= 100; }
11732 else { width = 4; }
11733 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11734 }
11735 b'H' => {
11736 val = (*tm).tm_hour as i64;
11737 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11738 }
11739 b'I' => {
11740 val = (*tm).tm_hour as i64;
11741 if val == 0 { val = 12; }
11742 else if val > 12 { val -= 12; }
11743 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11744 }
11745 b'j' => {
11746 val = (*tm).tm_yday as i64 + 1;
11747 width = 3;
11748 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11749 }
11750 b'm' => {
11751 val = (*tm).tm_mon as i64 + 1;
11752 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11753 }
11754 b'M' => {
11755 val = (*tm).tm_min as i64;
11756 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11757 }
11758 b'n' => { buf[0] = b'\n'; return (buf.as_ptr(), 1); }
11759 b'p' => {
11760 let p = if (*tm).tm_hour >= 12 { nl_langinfo(PM_STR_LI) } else { nl_langinfo(AM_STR_LI) };
11761 return str_to_buf(buf, p);
11762 }
11763 b'r' => {
11764 let p = nl_langinfo(T_FMT_AMPM);
11765 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11766 return (buf.as_ptr(), l);
11767 }
11768 b'R' => {
11769 fmt = b"%H:%M\0".as_ptr() as *const c_char;
11770 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11771 return (buf.as_ptr(), l);
11772 }
11773 b's' => {
11774 val = tm_to_secs(tm) - (*tm).tm_gmtoff as i64;
11775 width = 1;
11776 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11777 }
11778 b'S' => {
11779 val = (*tm).tm_sec as i64;
11780 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11781 }
11782 b't' => { buf[0] = b'\t'; return (buf.as_ptr(), 1); }
11783 b'T' => {
11784 fmt = b"%H:%M:%S\0".as_ptr() as *const c_char;
11785 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11786 return (buf.as_ptr(), l);
11787 }
11788 b'u' => {
11789 val = if (*tm).tm_wday != 0 { (*tm).tm_wday as i64 } else { 7 };
11790 width = 1;
11791 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11792 }
11793 b'U' => {
11794 val = ((*tm).tm_yday as u64 + 7 - (*tm).tm_wday as u64) as i64 / 7;
11795 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11796 }
11797 b'W' => {
11798 val = ((*tm).tm_yday as u64 + 7 - ((*tm).tm_wday as u64 + 6) % 7) as i64 / 7;
11799 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11800 }
11801 b'V' => {
11802 val = week_num(&*tm) as i64;
11803 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11804 }
11805 b'w' => {
11806 val = (*tm).tm_wday as i64;
11807 width = 1;
11808 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11809 }
11810 b'x' => {
11811 let p = nl_langinfo(D_FMT);
11812 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11813 return (buf.as_ptr(), l);
11814 }
11815 b'X' => {
11816 let p = nl_langinfo(T_FMT);
11817 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11818 return (buf.as_ptr(), l);
11819 }
11820 b'y' => {
11821 val = (1900i64 + (*tm).tm_year as i64) % 100;
11822 if val < 0 { val = -val; }
11823 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11824 }
11825 b'Y' => {
11826 val = (*tm).tm_year as i64 + 1900;
11827 if val >= 10000 {
11828 let mut tmp = [0u8; 100];
11829 let (_, k) = num_fmt(&mut tmp, val, b'-', 1);
11830 buf[0] = b'+';
11831 for i in 0..k { buf[1 + i] = tmp[i]; }
11832 return (buf.as_ptr(), 1 + k);
11833 }
11834 width = 4;
11835 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11836 }
11837 b'z' => {
11838 if (*tm).tm_isdst < 0 { return (b"\0".as_ptr(), 0); }
11839 let gmtoff = (*tm).tm_gmtoff as i64;
11840 let sign = if gmtoff >= 0 { b'+' } else { b'-' };
11841 let off = if gmtoff < 0 { -gmtoff } else { gmtoff };
11842 let hh = (off / 3600) as i32;
11843 let mm = ((off % 3600) / 60) as i32;
11844 buf[0] = sign;
11845 buf[1] = b'0' + (hh / 10) as u8;
11846 buf[2] = b'0' + (hh % 10) as u8;
11847 buf[3] = b'0' + (mm / 10) as u8;
11848 buf[4] = b'0' + (mm % 10) as u8;
11849 return (buf.as_ptr(), 5);
11850 }
11851 b'Z' => {
11852 if (*tm).tm_isdst < 0 || (*tm).tm_zone.is_null() { return (b"\0".as_ptr(), 0); }
11853 return str_to_buf(buf, (*tm).tm_zone);
11854 }
11855 b'%' => { buf[0] = b'%'; return (buf.as_ptr(), 1); }
11856 _ => { return (core::ptr::null(), 0); }
11857 }
11858 val = (*tm).tm_mday as i64;
11860 num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width)
11861}
11862
11863unsafe fn __strftime_l(s: *mut c_char, n: usize, f: *const c_char, tm: *const tm) -> usize {
11864 let mut l: usize = 0;
11865 let mut fi: usize = 0;
11866 while l < n {
11867 let ch = *f.add(fi) as u8;
11868 if ch == 0 {
11869 *s.add(l) = 0;
11870 return l;
11871 }
11872 if ch != b'%' {
11873 *s.add(l) = ch as c_char;
11874 l += 1;
11875 fi += 1;
11876 continue;
11877 }
11878 fi += 1;
11879 let mut pad: u8 = 0;
11881 let fc = *f.add(fi) as u8;
11882 if fc == b'-' || fc == b'_' || fc == b'0' { pad = fc; fi += 1; }
11883 let plus = *f.add(fi) as u8 == b'+';
11884 if plus { fi += 1; }
11885 let mut width: usize = 0;
11887 let mut p_idx = fi;
11888 {
11889 let fc2 = *f.add(fi) as u8;
11890 if fc2 >= b'0' && fc2 <= b'9' {
11891 let mut w: usize = 0;
11892 while { let c = *f.add(p_idx) as u8; c >= b'0' && c <= b'9' } {
11893 w = w * 10 + (*f.add(p_idx) as usize - b'0' as usize);
11894 p_idx += 1;
11895 }
11896 width = w;
11897 }
11898 }
11899 let spec_ch = *f.add(p_idx) as u8;
11900 if spec_ch == b'C' || spec_ch == b'F' || spec_ch == b'G' || spec_ch == b'Y' {
11901 if width == 0 && p_idx != fi { width = 1; }
11902 } else {
11903 width = 0;
11904 }
11905 fi = p_idx;
11906 let fc3 = *f.add(fi) as u8;
11908 if fc3 == b'E' || fc3 == b'O' { fi += 1; }
11909 let fch = *f.add(fi) as u8;
11910 let mut buf = [0u8; 100];
11912 let (t, k) = __strftime_fmt_1(&mut buf, fch, tm, pad);
11913 if t.is_null() { break; }
11914 let mut k = k;
11915 let mut t = t;
11916 if width != 0 {
11917 if *t == b'+' || *t == b'-' { t = t.add(1); k -= 1; }
11919 while k > 0 && *t == b'0' && k > 1 && *t.add(1) >= b'0' && *t.add(1) <= b'9' {
11920 t = t.add(1); k -= 1;
11921 }
11922 if width < k { width = k; }
11923 let mut d: usize = 0;
11924 while d < k && *t.add(d) >= b'0' && *t.add(d) <= b'9' { d += 1; }
11925 if (*tm).tm_year < -1900 {
11926 if l < n { *s.add(l) = b'-' as c_char; }
11927 l += 1;
11928 width -= 1;
11929 } else if plus && d + (width - k) >= (if spec_ch == b'C' { 3 } else { 5 }) {
11930 if l < n { *s.add(l) = b'+' as c_char; }
11931 l += 1;
11932 width -= 1;
11933 }
11934 while width > k && l < n {
11935 *s.add(l) = b'0' as c_char;
11936 l += 1;
11937 width -= 1;
11938 }
11939 }
11940 let copy = if k > n - l { n - l } else { k };
11941 core::ptr::copy_nonoverlapping(t, s.add(l) as *mut u8, copy);
11942 l += copy;
11943 fi += 1;
11944 }
11945 if n > 0 {
11946 if l == n { l = n - 1; }
11947 *s.add(l) = 0;
11948 }
11949 0
11950}
11951
11952#[no_mangle]
11953pub unsafe extern "C" fn strftime(s: *mut c_char, maxsize: usize, fmt: *const c_char, tm: *const tm) -> usize {
11954 __strftime_l(s, maxsize, fmt, tm)
11955}
11956
11957unsafe fn match_prefix(s: *const u8, prefix: &[u8]) -> bool {
11962 for i in 0..prefix.len() {
11963 if *s.add(i) == 0 || *s.add(i) != prefix[i] { return false; }
11964 }
11965 true
11966}
11967
11968unsafe fn match_ci_prefix(s: *const u8, prefix: &[u8]) -> bool {
11969 for i in 0..prefix.len() {
11970 let c = *s.add(i);
11971 if c == 0 { return false; }
11972 if c.to_ascii_lowercase() != prefix[i].to_ascii_lowercase() { return false; }
11973 }
11974 true
11975}
11976
11977unsafe fn parse_int(p: *const u8, max_digits: usize) -> (i32, *const u8) {
11978 let mut val = 0i32;
11979 let mut np = p;
11980 let mut count = 0;
11981 while *np >= b'0' && *np <= b'9' && count < max_digits {
11982 val = val * 10 + (*np - b'0') as i32;
11983 np = np.add(1);
11984 count += 1;
11985 }
11986 if count == 0 { (0, p) } else { (val, np) }
11987}
11988
11989unsafe fn parse_range(p: *const u8, min: i32, max: i32) -> (i32, *const u8) {
11990 let (val, np) = parse_int(p, 4);
11991 if np == p || val < min || val > max { (0, p) } else { (val, np) }
11992}
11993
11994fn is_ascii_space(c: u8) -> bool {
11995 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0c || c == 0x0b
11996}
11997
11998#[no_mangle]
11999pub unsafe extern "C" fn strptime(s: *const c_char, fmt: *const c_char, tm: *mut tm) -> *mut c_char {
12000 let mut p = s as *const u8;
12001 let mut f = fmt as *const u8;
12002 let mut want_century = 0i32;
12003 let mut century = 0i32;
12004 let mut relyear = 0i32;
12005 while *f != 0 {
12006 if *f != b'%' {
12007 if is_ascii_space(*f) {
12008 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
12009 } else {
12010 if *p != *f { return core::ptr::null_mut(); }
12011 p = p.add(1);
12012 }
12013 f = f.add(1);
12014 continue;
12015 }
12016 f = f.add(1);
12017 if *f == b'+' { f = f.add(1); }
12018 while *f >= b'0' && *f <= b'9' { f = f.add(1); }
12019 if *f == b'E' || *f == b'O' { f = f.add(1); }
12020 match *f {
12021 b'a' | b'A' => {
12022 let mut found = false;
12023 for i in 0..7 {
12024 let names: [&[u8]; 7] = [b"Sunday", b"Monday", b"Tuesday", b"Wednesday", b"Thursday", b"Friday", b"Saturday"];
12025 let snames: [&[u8]; 7] = [b"Sun", b"Mon", b"Tue", b"Wed", b"Thu", b"Fri", b"Sat"];
12026 if match_prefix(p, names[i]) { (*tm).tm_wday = i as c_int; p = p.add(names[i].len()); found = true; break; }
12027 if match_prefix(p, snames[i]) { (*tm).tm_wday = i as c_int; p = p.add(snames[i].len()); found = true; break; }
12028 }
12029 if !found { return core::ptr::null_mut(); }
12030 }
12031 b'b' | b'B' | b'h' => {
12032 let mut found = false;
12033 for i in 0..12 {
12034 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"];
12035 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"];
12036 if match_prefix(p, names[i]) { (*tm).tm_mon = i as c_int; p = p.add(names[i].len()); found = true; break; }
12037 if match_prefix(p, snames[i]) { (*tm).tm_mon = i as c_int; p = p.add(snames[i].len()); found = true; break; }
12038 }
12039 if !found { return core::ptr::null_mut(); }
12040 }
12041 b'C' => {
12042 let (v, np) = parse_int(p, 2);
12043 if np == p { return core::ptr::null_mut(); }
12044 century = v;
12045 want_century |= 2;
12046 p = np;
12047 }
12048 b'd' | b'e' => {
12049 let (v, np) = parse_range(p, 1, 31);
12050 if np == p { return core::ptr::null_mut(); }
12051 (*tm).tm_mday = v;
12052 p = np;
12053 }
12054 b'D' => {
12055 let r = strptime(p as *const c_char, b"%m/%d/%y\0".as_ptr() as *const c_char, tm);
12056 if r.is_null() { return core::ptr::null_mut(); }
12057 p = r as *const u8;
12058 }
12059 b'F' => {
12060 let (yv, ynp) = parse_int(p, 4);
12061 if ynp == p { return core::ptr::null_mut(); }
12062 (*tm).tm_year = yv - 1900;
12063 p = ynp;
12064 if *p != b'-' { return core::ptr::null_mut(); }
12065 p = p.add(1);
12066 let (mv, mnp) = parse_range(p, 1, 12);
12067 if mnp == p { return core::ptr::null_mut(); }
12068 (*tm).tm_mon = mv - 1;
12069 p = mnp;
12070 if *p != b'-' { return core::ptr::null_mut(); }
12071 p = p.add(1);
12072 let (dv, dnp) = parse_range(p, 1, 31);
12073 if dnp == p { return core::ptr::null_mut(); }
12074 (*tm).tm_mday = dv;
12075 p = dnp;
12076 }
12077 b'H' | b'I' => {
12078 let (v, np) = parse_range(p, 0, 23);
12079 if np == p { return core::ptr::null_mut(); }
12080 (*tm).tm_hour = v;
12081 p = np;
12082 }
12083 b'j' => {
12084 let (v, np) = parse_range(p, 1, 366);
12085 if np == p { return core::ptr::null_mut(); }
12086 (*tm).tm_yday = v - 1;
12087 p = np;
12088 }
12089 b'm' => {
12090 let (v, np) = parse_range(p, 1, 12);
12091 if np == p { return core::ptr::null_mut(); }
12092 (*tm).tm_mon = v - 1;
12093 p = np;
12094 }
12095 b'M' => {
12096 let (v, np) = parse_range(p, 0, 59);
12097 if np == p { return core::ptr::null_mut(); }
12098 (*tm).tm_min = v;
12099 p = np;
12100 }
12101 b'n' | b't' => {
12102 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
12103 }
12104 b'p' => {
12105 if match_ci_prefix(p, b"AM") {
12106 if (*tm).tm_hour == 12 { (*tm).tm_hour = 0; }
12107 p = p.add(2);
12108 } else if match_ci_prefix(p, b"PM") {
12109 if (*tm).tm_hour < 12 { (*tm).tm_hour += 12; }
12110 p = p.add(2);
12111 } else { return core::ptr::null_mut(); }
12112 }
12113 b'r' => {
12114 let r = strptime(p as *const c_char, b"%I:%M:%S %p\0".as_ptr() as *const c_char, tm);
12115 if r.is_null() { return core::ptr::null_mut(); }
12116 p = r as *const u8;
12117 }
12118 b'R' => {
12119 let r = strptime(p as *const c_char, b"%H:%M\0".as_ptr() as *const c_char, tm);
12120 if r.is_null() { return core::ptr::null_mut(); }
12121 p = r as *const u8;
12122 }
12123 b's' => {
12124 let neg = if *p == b'-' { p = p.add(1); true } else { false };
12125 if *p < b'0' || *p > b'9' { return core::ptr::null_mut(); }
12126 let mut val = 0i64;
12127 while *p >= b'0' && *p <= b'9' {
12128 val = val * 10 + (*p - b'0') as i64;
12129 p = p.add(1);
12130 }
12131 if neg { val = -val; }
12132 secs_to_tm(val, &mut *tm);
12133 }
12134 b'S' => {
12135 let (v, np) = parse_range(p, 0, 60);
12136 if np == p { return core::ptr::null_mut(); }
12137 (*tm).tm_sec = v;
12138 p = np;
12139 }
12140 b'T' => {
12141 let r = strptime(p as *const c_char, b"%H:%M:%S\0".as_ptr() as *const c_char, tm);
12142 if r.is_null() { return core::ptr::null_mut(); }
12143 p = r as *const u8;
12144 }
12145 b'U' | b'W' => {
12146 let (_, np) = parse_range(p, 0, 53);
12147 if np == p { return core::ptr::null_mut(); }
12148 p = np;
12149 }
12150 b'V' => {
12151 let (_, np) = parse_range(p, 1, 53);
12152 if np == p { return core::ptr::null_mut(); }
12153 p = np;
12154 }
12155 b'w' => {
12156 let (v, np) = parse_range(p, 0, 6);
12157 if np == p { return core::ptr::null_mut(); }
12158 (*tm).tm_wday = v;
12159 p = np;
12160 }
12161 b'y' => {
12162 let (v, np) = parse_int(p, 2);
12163 if np == p { return core::ptr::null_mut(); }
12164 relyear = v;
12165 want_century |= 1;
12166 p = np;
12167 }
12168 b'Y' => {
12169 let neg = if *p == b'-' { p = p.add(1); true } else { false };
12170 let (v, np) = parse_int(p, 4);
12171 if np == p { return core::ptr::null_mut(); }
12172 (*tm).tm_year = if neg { -(v + 1900) } else { v - 1900 };
12173 want_century = 0;
12174 p = np;
12175 }
12176 b'z' => {
12177 if *p != b'+' && *p != b'-' { return core::ptr::null_mut(); }
12178 let neg = *p == b'-';
12179 p = p.add(1);
12180 let mut off = 0i64;
12181 let mut digits = 0;
12182 while digits < 4 && *p >= b'0' && *p <= b'9' {
12183 off = off * 10 + (*p - b'0') as i64;
12184 p = p.add(1);
12185 digits += 1;
12186 }
12187 if digits == 0 { return core::ptr::null_mut(); }
12188 let (hh, mm) = if digits <= 2 { (off, 0i64) } else { (off / 100, off % 100) };
12189 (*tm).tm_gmtoff = (hh * 3600 + mm * 60) * if neg { -1 } else { 1 };
12190 }
12191 b'%' => {
12192 if *p != b'%' { return core::ptr::null_mut(); }
12193 p = p.add(1);
12194 }
12195 _ => { return core::ptr::null_mut(); }
12196 }
12197 f = f.add(1);
12198 }
12199 if want_century != 0 {
12200 (*tm).tm_year = relyear;
12201 if want_century & 2 != 0 { (*tm).tm_year += century * 100 - 1900; }
12202 else if (*tm).tm_year <= 68 { (*tm).tm_year += 100; }
12203 }
12204 p as *mut c_char
12205}
12206
12207#[no_mangle]
12212pub static mut daylight: c_int = 0;
12213#[no_mangle]
12214pub static mut timezone: c_long = 0;
12215#[no_mangle]
12216pub 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];
12217
12218#[no_mangle]
12219pub unsafe extern "C" fn tzset() {
12220 daylight = 0;
12221 timezone = 0;
12222}
12223
12224#[no_mangle]
12229pub unsafe extern "C" fn system(cmd: *const c_char) -> c_int {
12230 if cmd.is_null() {
12231 let pid = sys_fork();
12233 if pid == 0 {
12234 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
12235 let dash_c = b"-c\0".as_ptr() as *const c_char;
12236 let exit0 = b"exit 0\0".as_ptr() as *const c_char;
12237 let argv = [b"sh\0".as_ptr() as *const c_char, dash_c, exit0, core::ptr::null()];
12238 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
12239 _exit(127);
12240 }
12241 if pid < 0 { return -1; }
12242 let mut status: c_int = 0;
12243 loop {
12244 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
12245 if r >= 0 { return status; }
12246 if r != -4 { return -1; } }
12248 }
12249
12250 let sa_ignore = KSigAction {
12251 sa_handler: SIG_IGN,
12252 sa_flags: SA_RESTORER,
12253 sa_restorer: sig_restorer as *const () as usize,
12254 sa_mask: [0],
12255 };
12256 let mut oldint: KSigAction = core::mem::zeroed();
12257 let mut oldquit: KSigAction = core::mem::zeroed();
12258
12259 sys_rt_sigaction(SIGINT, &sa_ignore, &mut oldint, 8);
12260 sys_rt_sigaction(SIGQUIT, &sa_ignore, &mut oldquit, 8);
12261
12262 let mut block_set: SigSetT = 0;
12263 block_set |= 1u64 << (SIGCHLD - 1);
12264 let mut oldmask: SigSetT = 0;
12265 sys_rt_sigprocmask(SIG_BLOCK, &block_set, &mut oldmask, 8);
12266
12267 let pid = sys_fork();
12268
12269 if pid == 0 {
12270 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
12271 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
12272 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
12273
12274 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
12275 let argv = [
12276 b"sh\0".as_ptr() as *const c_char,
12277 b"-c\0".as_ptr() as *const c_char,
12278 cmd,
12279 core::ptr::null(),
12280 ];
12281 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
12282 _exit(127);
12283 }
12284
12285 let mut status: c_int = -1;
12286 if pid > 0 {
12287 loop {
12288 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
12289 if r >= 0 { break; }
12290 if r != -4 { break; } }
12292 }
12293
12294 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
12295 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
12296 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
12297
12298 status
12299}
12300
12301const EPERM_VAL: c_int = 1;
12306const ENOENT_VAL: c_int = 2;
12307const ESRCH_VAL: c_int = 3;
12308const EINTR_VAL: c_int = 4;
12309const EIO_VAL: c_int = 5;
12310const ENXIO_VAL: c_int = 6;
12311const E2BIG_VAL: c_int = 7;
12312const ENOEXEC_VAL: c_int = 8;
12313const EBADF_VAL: c_int = 9;
12314const ECHILD_VAL: c_int = 10;
12315const EAGAIN_VAL: c_int = 11;
12316const ENOMEM_VAL: c_int = 12;
12317const EACCES_VAL: c_int = 13;
12318const EFAULT_VAL: c_int = 14;
12319const ENOTBLK_VAL: c_int = 15;
12320const EBUSY_VAL: c_int = 16;
12321const EEXIST_VAL: c_int = 17;
12322const EXDEV_VAL: c_int = 18;
12323const ENODEV_VAL: c_int = 19;
12324const ENOTDIR_VAL: c_int = 20;
12325const EISDIR_VAL: c_int = 21;
12326const EINVAL_VAL: c_int = 22;
12327const ENFILE_VAL: c_int = 23;
12328const EMFILE_VAL: c_int = 24;
12329const ENOTTY_VAL: c_int = 25;
12330const ETXTBSY_VAL: c_int = 26;
12331const EFBIG_VAL: c_int = 27;
12332const ENOSPC_VAL: c_int = 28;
12333const ESPIPE_VAL: c_int = 29;
12334const EROFS_VAL: c_int = 30;
12335const EMLINK_VAL: c_int = 31;
12336const EPIPE_VAL: c_int = 32;
12337const EDOM_VAL: c_int = 33;
12338const ERANGE_VAL: c_int = 34;
12339const EDEADLK_VAL: c_int = 35;
12340const ENAMETOOLONG_VAL: c_int = 36;
12341const ENOLCK_VAL: c_int = 37;
12342const ENOSYS_VAL: c_int = 38;
12343const ENOTEMPTY_VAL: c_int = 39;
12344const ELOOP_VAL: c_int = 40;
12345const EWOULDBLOCK_VAL: c_int = 11;
12346const ENOMSG_VAL: c_int = 42;
12347const EIDRM_VAL: c_int = 43;
12348const ECHRNG_VAL: c_int = 44;
12349const EL2NSYNC_VAL: c_int = 45;
12350const EL3HLT_VAL: c_int = 46;
12351const EL3RST_VAL: c_int = 47;
12352const ELNRNG_VAL: c_int = 48;
12353const EUNATCH_VAL: c_int = 49;
12354const ENOCSI_VAL: c_int = 50;
12355const EL2HLT_VAL: c_int = 51;
12356const EBADE_VAL: c_int = 52;
12357const EBADR_VAL: c_int = 53;
12358const EXFULL_VAL: c_int = 54;
12359const ENOANO_VAL: c_int = 55;
12360const EBADRQC_VAL: c_int = 56;
12361const EBADSLT_VAL: c_int = 57;
12362const EBFONT_VAL: c_int = 59;
12363const ENOSTR_VAL: c_int = 60;
12364const ENODATA_VAL: c_int = 61;
12365const ETIME_VAL: c_int = 62;
12366const ENOSR_VAL: c_int = 63;
12367const ENONET_VAL: c_int = 64;
12368const ENOPKG_VAL: c_int = 65;
12369const EREMOTE_VAL: c_int = 66;
12370const ENOLINK_VAL: c_int = 67;
12371const EADV_VAL: c_int = 68;
12372const ESRMNT_VAL: c_int = 69;
12373const ECOMM_VAL: c_int = 70;
12374const EPROTO_VAL: c_int = 71;
12375const EMULTIHOP_VAL: c_int = 72;
12376const EDOTDOT_VAL: c_int = 73;
12377const EBADMSG_VAL: c_int = 74;
12378const EOVERFLOW_VAL: c_int = 75;
12379const ENOTUNIQ_VAL: c_int = 76;
12380const EBADFD_VAL: c_int = 77;
12381const EREMCHG_VAL: c_int = 78;
12382const ELIBACC_VAL: c_int = 79;
12383const ELIBBAD_VAL: c_int = 80;
12384const ELIBSCN_VAL: c_int = 81;
12385const ELIBMAX_VAL: c_int = 82;
12386const ELIBEXEC_VAL: c_int = 83;
12387const EILSEQ_VAL: c_int = 84;
12388const ERESTART_VAL: c_int = 85;
12389const ESTRPIPE_VAL: c_int = 86;
12390const EUSERS_VAL: c_int = 87;
12391const ENOTSOCK_VAL: c_int = 88;
12392const EDESTADDRREQ_VAL: c_int = 89;
12393const EMSGSIZE_VAL: c_int = 90;
12394const EPROTOTYPE_VAL: c_int = 91;
12395const ENOPROTOOPT_VAL: c_int = 92;
12396const EPROTONOSUPPORT_VAL: c_int = 93;
12397const ESOCKTNOSUPPORT_VAL: c_int = 94;
12398const EOPNOTSUPP_VAL: c_int = 95;
12399const ENOTSUP_VAL: c_int = 95;
12400const EPFNOSUPPORT_VAL: c_int = 96;
12401const EAFNOSUPPORT_VAL: c_int = 97;
12402const EADDRINUSE_VAL: c_int = 98;
12403const EADDRNOTAVAIL_VAL: c_int = 99;
12404const ENETDOWN_VAL: c_int = 100;
12405const ENETUNREACH_VAL: c_int = 101;
12406const ENETRESET_VAL: c_int = 102;
12407const ECONNABORTED_VAL: c_int = 103;
12408const ECONNRESET_VAL: c_int = 104;
12409const ENOBUFS_VAL: c_int = 105;
12410const EISCONN_VAL: c_int = 106;
12411const ENOTCONN_VAL: c_int = 107;
12412const ESHUTDOWN_VAL: c_int = 108;
12413const ETOOMANYREFS_VAL: c_int = 109;
12414const ETIMEDOUT_VAL: c_int = 110;
12415const ECONNREFUSED_VAL: c_int = 111;
12416const EHOSTDOWN_VAL: c_int = 112;
12417const EHOSTUNREACH_VAL: c_int = 113;
12418const EALREADY_VAL: c_int = 114;
12419const EINPROGRESS_VAL: c_int = 115;
12420const ESTALE_VAL: c_int = 116;
12421const EUCLEAN_VAL: c_int = 117;
12422const ENOTNAM_VAL: c_int = 118;
12423const ENAVAIL_VAL: c_int = 119;
12424const EISNAM_VAL: c_int = 120;
12425const EREMOTEIO_VAL: c_int = 121;
12426const EDQUOT_VAL: c_int = 122;
12427const ENOMEDIUM_VAL: c_int = 123;
12428const EMEDIUMTYPE_VAL: c_int = 124;
12429const ECANCELED_VAL: c_int = 125;
12430const ENOKEY_VAL: c_int = 126;
12431const EKEYEXPIRED_VAL: c_int = 127;
12432const EKEYREVOKED_VAL: c_int = 128;
12433const EKEYREJECTED_VAL: c_int = 129;
12434const EOWNERDEAD_VAL: c_int = 130;
12435const ENOTRECOVERABLE_VAL: c_int = 131;
12436const ERFKILL_VAL: c_int = 132;
12437const EHWPOISON_VAL: c_int = 133;
12438
12439static ERR_STRS: [&[u8]; 134] = [
12441 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", ];
12576
12577#[no_mangle]
12578pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char {
12579 if errnum < 0 || errnum as usize >= ERR_STRS.len() {
12580 static mut UNKNOWN_BUF: [c_char; 32] = [0; 32];
12582 let prefix = b"Unknown error \0";
12583 let mut i = 0;
12584 while prefix[i] != 0 {
12585 UNKNOWN_BUF[i] = prefix[i] as c_char;
12586 i += 1;
12587 }
12588 let (buf, len) = format_u64(errnum as u64);
12589 for j in 0..len {
12590 UNKNOWN_BUF[i] = buf[20 - len + j] as c_char;
12591 i += 1;
12592 }
12593 UNKNOWN_BUF[i] = 0;
12594 return core::ptr::addr_of_mut!(UNKNOWN_BUF).cast::<c_char>();
12595 }
12596 ERR_STRS[errnum as usize].as_ptr() as *mut c_char
12597}
12598
12599#[no_mangle]
12600pub unsafe extern "C" fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: usize) -> c_int {
12601 let s = strerror(errnum);
12602 let slen = strlen(s as *const c_char);
12603 if slen >= buflen {
12604 if buflen > 0 {
12605 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, buflen - 1);
12606 *buf.add(buflen - 1) = 0;
12607 }
12608 return 34; }
12610 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, slen + 1);
12611 0
12612}
12613
12614#[no_mangle]
12616pub static mut environ: *mut *mut c_char = core::ptr::null_mut();
12617
12618unsafe fn sync_environ() {
12620 environ = __environ;
12621}
12622
12623#[inline]
12628unsafe fn sys_dup(oldfd: i32) -> i64 {
12629 <Arch as Syscalls>::syscall1(SYS_DUP, oldfd as i64)
12630}
12631
12632#[inline]unsafe fn sys_dup2(oldfd: i32, newfd: i32) -> i64 {
12633 sys_dup3(oldfd, newfd, 0)
12635}
12636
12637#[inline]
12638unsafe fn sys_access(path: *const u8, mode: i32) -> i64 {
12639 <Arch as Syscalls>::syscall4(SYS_FACCESSAT, AT_FDCWD as i64, path as i64, mode as i64, 0)
12640}
12641
12642#[inline]unsafe fn sys_unlink(path: *const u8) -> i64 {
12643 sys_unlinkat(AT_FDCWD, path, 0)
12644}
12645
12646#[inline]unsafe fn sys_rmdir(path: *const u8) -> i64 {
12647 sys_unlinkat(AT_FDCWD, path, 512) }
12649
12650#[inline]
12651unsafe fn sys_chdir(path: *const u8) -> i64 {
12652 <Arch as Syscalls>::syscall1(SYS_CHDIR, path as i64)
12653}
12654
12655#[inline]
12656unsafe fn sys_getcwd(buf: *mut u8, size: usize) -> i64 {
12657 <Arch as Syscalls>::syscall2(SYS_GETCWD, buf as i64, size as i64)
12658}
12659
12660#[inline]
12661unsafe fn sys_sethostname(name: *const u8, len: usize) -> i64 {
12662 <Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64)
12663}
12664
12665#[inline]
12666unsafe fn sys_gethostname(buf: *mut u8, len: usize) -> i64 {
12667 #[repr(C)]
12668 struct UtsName {
12669 sysname: [u8; 65],
12670 nodename: [u8; 65],
12671 release: [u8; 65],
12672 version: [u8; 65],
12673 machine: [u8; 65],
12674 domainname: [u8; 65],
12675 }
12676 let mut uts: UtsName = core::mem::zeroed();
12677 let result = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
12678 if result < 0 {
12679 return result;
12680 }
12681 let nlen = strlen(uts.nodename.as_ptr() as *const c_char);
12682 let copylen = if nlen < len { nlen } else { if len > 0 { len - 1 } else { 0 } };
12683 core::ptr::copy_nonoverlapping(uts.nodename.as_ptr(), buf, copylen);
12684 if len > 0 { *buf.add(copylen) = 0; }
12685 0
12686}
12687
12688unsafe fn sys_truncate(path: *const u8, length: i64) -> i64 {
12689 <Arch as Syscalls>::syscall2(SYS_TRUNCATE, path as i64, length as i64)
12690}
12691
12692unsafe fn sys_ftruncate(fd: i32, length: i64) -> i64 {
12693 <Arch as Syscalls>::syscall2(SYS_FTRUNCATE, fd as i64, length as i64)
12694}
12695
12696unsafe fn sys_nanosleep(req: *const timespec, rem: *mut timespec) -> i64 {
12697 <Arch as Syscalls>::syscall2(SYS_NANOSLEEP, req as i64, rem as i64)
12698}
12699
12700const ITIMER_REAL: i32 = 0;
12701
12702#[repr(C)]
12703struct itimerval {
12704 it_interval: timeval,
12705 it_value: timeval,
12706}
12707
12708unsafe fn sys_alarm(seconds: c_uint) -> i64 {
12709 let mut new: itimerval = core::mem::zeroed();
12710 new.it_value.tv_sec = seconds as c_long;
12711 let mut old: itimerval = core::mem::zeroed();
12712 let r = <Arch as Syscalls>::syscall3(
12713 SYS_SETITIMER,
12714 ITIMER_REAL as i64,
12715 &new as *const _ as i64,
12716 &mut old as *mut _ as i64,
12717 );
12718 if r < 0 {
12719 return r;
12720 }
12721 old.it_value.tv_sec as i64 + (old.it_value.tv_usec != 0) as i64
12722}
12723
12724unsafe fn sys_pause() -> i64 {
12725 #[cfg(target_arch = "x86_64")]
12726 { <Arch as Syscalls>::syscall0(SYS_PAUSE) }
12727 #[cfg(target_arch = "aarch64")]
12728 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12729 #[cfg(target_arch = "riscv64")]
12730 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12731}
12732
12733unsafe fn sys_fsync(fd: i32) -> i64 {
12734 <Arch as Syscalls>::syscall1(SYS_FSYNC, fd as i64)
12735}
12736
12737unsafe fn sys_fdatasync(fd: i32) -> i64 {
12738 <Arch as Syscalls>::syscall1(SYS_FDATASYNC, fd as i64)
12739}
12740
12741unsafe fn sys_sync() {
12742 let _ = <Arch as Syscalls>::syscall0(SYS_SYNC);
12743}
12744
12745unsafe fn sys_symlink(target: *const u8, linkpath: *const u8) -> i64 {
12746 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, AT_FDCWD as i64, linkpath as i64)
12747}
12748
12749unsafe fn sys_symlinkat(target: *const u8, newdirfd: i32, linkpath: *const u8) -> i64 {
12750 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64)
12751}
12752
12753unsafe fn sys_readlinkat(dirfd: i32, path: *const u8, buf: *mut u8, bufsiz: usize) -> i64 {
12754 <Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, path as i64, buf as i64, bufsiz as i64)
12755}
12756
12757unsafe fn sys_linkat(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: i32) -> i64 {
12758 <Arch as Syscalls>::syscall5(SYS_LINKAT, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
12759}
12760
12761unsafe fn sys_fchmod(fd: i32, mode: u32) -> i64 {
12762 <Arch as Syscalls>::syscall2(SYS_FCHMOD, fd as i64, mode as i64)
12763}
12764
12765unsafe fn sys_fchmodat(dirfd: i32, path: *const u8, mode: u32, flags: i32) -> i64 {
12766 <Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, path as i64, mode as i64, flags as i64)
12767}
12768
12769unsafe fn sys_umask(mask: u32) -> u32 {
12770 <Arch as Syscalls>::syscall1(SYS_UMASK, mask as i64) as u32
12771}
12772
12773unsafe fn sys_getgroups(size: i32, list: *mut c_uint) -> i64 {
12774 <Arch as Syscalls>::syscall2(SYS_GETGROUPS, size as i64, list as i64)
12775}
12776
12777unsafe fn sys_setuid(uid: c_uint) -> i64 {
12778 <Arch as Syscalls>::syscall1(SYS_SETUID, uid as i64)
12779}
12780
12781unsafe fn sys_setgid(gid: c_uint) -> i64 {
12782 <Arch as Syscalls>::syscall1(SYS_SETGID, gid as i64)
12783}
12784
12785unsafe fn sys_setsid() -> i64 {
12786 <Arch as Syscalls>::syscall0(SYS_SETSID)
12787}
12788
12789unsafe fn sys_setpgid(pid: c_int, pgid: c_int) -> i64 {
12790 <Arch as Syscalls>::syscall2(SYS_SETPGID, pid as i64, pgid as i64)
12791}
12792
12793unsafe fn sys_getpgid(pid: c_int) -> i64 {
12794 <Arch as Syscalls>::syscall1(SYS_GETPGID, pid as i64)
12795}
12796
12797unsafe fn sys_getsid(pid: c_int) -> i64 {
12798 <Arch as Syscalls>::syscall1(SYS_GETSID, pid as i64)
12799}
12800
12801unsafe fn sys_mkdirat(dirfd: i32, path: *const u8, mode: u32) -> i64 {
12802 <Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, path as i64, mode as i64)
12803}
12804
12805#[no_mangle]
12808pub unsafe extern "C" fn pipe(fds: *mut c_int) -> c_int {
12809 let r = sys_pipe2(fds, 0);
12810 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12811 0
12812}
12813
12814#[no_mangle]
12815pub unsafe extern "C" fn pipe2(fds: *mut c_int, flags: c_int) -> c_int {
12816 let r = sys_pipe2(fds, flags);
12817 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12818 0
12819}
12820
12821#[no_mangle]
12822pub unsafe extern "C" fn dup(oldfd: c_int) -> c_int {
12823 let r = sys_dup(oldfd);
12824 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12825 r as c_int
12826}
12827
12828#[no_mangle]
12829pub unsafe extern "C" fn dup2(oldfd: c_int, newfd: c_int) -> c_int {
12830 if oldfd == newfd {
12831 let r = sys_fcntl(oldfd, 1 , 0);
12834 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12835 return newfd;
12836 }
12837 let r = sys_dup2(oldfd, newfd);
12838 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12839 r as c_int
12840}
12841
12842#[no_mangle]
12843pub unsafe extern "C" fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int {
12844 let r = sys_dup3(oldfd, newfd, flags);
12845 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12846 r as c_int
12847}
12848
12849#[no_mangle]
12850pub unsafe extern "C" fn fcntl(fd: c_int, cmd: c_int, mut args: ...) -> c_int {
12851 let no_arg = matches!(cmd, 1 | 3 | 9 | 11 | 1025 | 1032 | 1034 );
12856 let r = if no_arg {
12857 sys_fcntl(fd, cmd, 0)
12858 } else {
12859 let arg = args.next_arg::<c_long>();
12860 sys_fcntl(fd, cmd, arg)
12861 };
12862 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12863 r as c_int
12864}
12865
12866#[no_mangle]
12867pub unsafe extern "C" fn access(path: *const c_char, mode: c_int) -> c_int {
12868 let r = sys_access(path as *const u8, mode);
12869 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12870 0
12871}
12872
12873#[no_mangle]
12874pub unsafe extern "C" fn unlink(path: *const c_char) -> c_int {
12875 let r = sys_unlink(path as *const u8);
12876 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12877 0
12878}
12879
12880#[no_mangle]
12881pub unsafe extern "C" fn rmdir(path: *const c_char) -> c_int {
12882 let r = sys_rmdir(path as *const u8);
12883 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12884 0
12885}
12886
12887#[no_mangle]
12888pub unsafe extern "C" fn chdir(path: *const c_char) -> c_int {
12889 let r = sys_chdir(path as *const u8);
12890 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12891 0
12892}
12893
12894#[no_mangle]
12895pub unsafe extern "C" fn getcwd(buf: *mut c_char, size: usize) -> *mut c_char {
12896 if buf.is_null() {
12897 let alloc_size = if size == 0 { 256 } else { size };
12899 let p = malloc(alloc_size) as *mut c_char;
12900 if p.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
12901 let r = sys_getcwd(p as *mut u8, alloc_size);
12902 if r < 0 { free(p as *mut c_void); ERRNO!() = (-r) as c_int; return core::ptr::null_mut(); }
12903 if *p as u8 != b'/' {
12906 free(p as *mut c_void);
12907 ERRNO!() = 2;
12908 return core::ptr::null_mut();
12909 }
12910 return p;
12911 }
12912 if size == 0 { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
12913 let r = sys_getcwd(buf as *mut u8, size);
12914 if r < 0 { ERRNO!() = (-r) as c_int; return core::ptr::null_mut(); }
12915 if *buf as u8 != b'/' {
12916 ERRNO!() = 2;
12917 return core::ptr::null_mut();
12918 }
12919 buf
12920}
12921
12922#[no_mangle]
12923pub unsafe extern "C" fn gethostname(name: *mut c_char, len: usize) -> c_int {
12924 let r = sys_gethostname(name as *mut u8, len);
12925 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12926 0
12927}
12928
12929#[no_mangle]
12931pub extern "C" fn getpagesize() -> c_int {
12932 4096
12933}
12934
12935#[no_mangle]
12936pub unsafe extern "C" fn truncate(path: *const c_char, length: i64) -> c_int {
12937 let r = sys_truncate(path as *const u8, length);
12938 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12939 0
12940}
12941
12942#[no_mangle]
12943pub unsafe extern "C" fn ftruncate(fd: c_int, length: i64) -> c_int {
12944 let r = sys_ftruncate(fd, length);
12945 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12946 0
12947}
12948
12949#[no_mangle]
12950pub unsafe extern "C" fn nanosleep(req: *const timespec, rem: *mut timespec) -> c_int {
12951 pthread_testcancel();
12952 let r = sys_nanosleep(req, rem);
12953 pthread_testcancel();
12954 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12955 0
12956}
12957
12958#[no_mangle]
12959pub unsafe extern "C" fn sleep(seconds: c_uint) -> c_uint {
12960 let req = timespec { tv_sec: seconds as c_long, tv_nsec: 0 };
12961 let mut rem: timespec = core::mem::zeroed();
12962 pthread_testcancel();
12963 let r = sys_nanosleep(&req, &mut rem);
12964 pthread_testcancel();
12965 if r < 0 {
12966 let e = (-r) as c_int;
12967 if e == EINTR { return rem.tv_sec as c_uint; }
12968 }
12969 0
12970}
12971
12972#[no_mangle]
12973pub unsafe extern "C" fn usleep(usec: c_uint) -> c_int {
12974 let req = timespec { tv_sec: (usec / 1000000) as c_long, tv_nsec: ((usec % 1000000) * 1000) as c_long };
12975 pthread_testcancel();
12976 let r = sys_nanosleep(&req, core::ptr::null_mut());
12977 pthread_testcancel();
12978 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12979 0
12980}
12981
12982#[no_mangle]
12983pub unsafe extern "C" fn alarm(seconds: c_uint) -> c_uint {
12984 let r = sys_alarm(seconds);
12987 if r < 0 { 0 } else { r as c_uint }
12988}
12989
12990#[no_mangle]
12991pub unsafe extern "C" fn pause() -> c_int {
12992 pthread_testcancel();
12993 sys_pause();
12994 pthread_testcancel();
12995 ERRNO!() = EINTR;
12996 -1
12997}
12998
12999#[no_mangle]
13000pub unsafe extern "C" fn fsync(fd: c_int) -> c_int {
13001 let r = sys_fsync(fd);
13002 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13003 0
13004}
13005
13006#[no_mangle]
13007pub unsafe extern "C" fn fdatasync(fd: c_int) -> c_int {
13008 let r = sys_fdatasync(fd);
13009 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13010 0
13011}
13012
13013#[no_mangle]
13014pub unsafe extern "C" fn sync() {
13015 sys_sync();
13016}
13017
13018#[no_mangle]
13019pub unsafe extern "C" fn symlink(target: *const c_char, linkpath: *const c_char) -> c_int {
13020 let r = sys_symlinkat(target as *const u8, AT_FDCWD, linkpath as *const u8);
13021 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13022 0
13023}
13024
13025#[no_mangle]
13026pub unsafe extern "C" fn readlink(path: *const c_char, buf: *mut c_char, bufsiz: usize) -> isize {
13027 let r = sys_readlinkat(AT_FDCWD, path as *const u8, buf as *mut u8, bufsiz);
13028 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13029 r as isize
13030}
13031
13032#[no_mangle]
13033pub unsafe extern "C" fn link(oldpath: *const c_char, newpath: *const c_char) -> c_int {
13034 let r = sys_linkat(AT_FDCWD, oldpath as *const u8, AT_FDCWD, newpath as *const u8, 0);
13035 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13036 0
13037}
13038
13039#[no_mangle]
13040pub unsafe extern "C" fn chmod(path: *const c_char, mode: c_uint) -> c_int {
13041 let r = sys_fchmodat(AT_FDCWD, path as *const u8, mode, 0);
13042 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13043 0
13044}
13045
13046#[no_mangle]
13047pub unsafe extern "C" fn fchmod(fd: c_int, mode: c_uint) -> c_int {
13048 let r = sys_fchmod(fd, mode);
13049 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13050 0
13051}
13052
13053#[no_mangle]
13054pub unsafe extern "C" fn umask(mask: c_uint) -> c_uint {
13055 sys_umask(mask) as c_uint
13056}
13057
13058#[no_mangle]
13059pub unsafe extern "C" fn isatty(fd: c_int) -> c_int {
13060 let mut ws: winsize = core::mem::zeroed();
13061 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 { 1 } else { 0 }
13062}
13063
13064#[no_mangle]
13065pub unsafe extern "C" fn getlogin() -> *mut c_char {
13066 static mut LOGIN_BUF: [c_char; 32] = [0; 32];
13067 let pw = getpwuid(crate::getuid());
13068 if pw.is_null() { return core::ptr::null_mut(); }
13069 let n = crate::strlen((*pw).pw_name);
13070 if n + 1 > LOGIN_BUF.len() { return core::ptr::null_mut(); }
13071 core::ptr::copy_nonoverlapping((*pw).pw_name, LOGIN_BUF.as_mut_ptr(), n + 1);
13072 LOGIN_BUF.as_mut_ptr()
13073}
13074
13075#[no_mangle]
13076pub unsafe extern "C" fn getgroups(size: c_int, list: *mut c_uint) -> c_int {
13077 let r = sys_getgroups(size, list);
13078 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13079 r as c_int
13080}
13081
13082#[no_mangle]
13083pub unsafe extern "C" fn setuid(uid: c_uint) -> c_int {
13084 let r = sys_setuid(uid);
13085 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13086 0
13087}
13088
13089#[no_mangle]
13090pub unsafe extern "C" fn setgid(gid: c_uint) -> c_int {
13091 let r = sys_setgid(gid);
13092 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13093 0
13094}
13095
13096#[no_mangle]
13097pub unsafe extern "C" fn seteuid(euid: c_uint) -> c_int {
13098 setresuid(u32::MAX, euid, u32::MAX)
13102}
13103
13104#[no_mangle]
13105pub unsafe extern "C" fn setegid(egid: c_uint) -> c_int {
13106 setresgid(u32::MAX, egid, u32::MAX)
13107}
13108
13109#[no_mangle]
13110pub unsafe extern "C" fn setreuid(ruid: c_uint, euid: c_uint) -> c_int {
13111 let r = <Arch as Syscalls>::syscall2(sysno(113, 145), ruid as i64, euid as i64);
13112 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
13113}
13114
13115
13116
13117#[no_mangle]
13118pub unsafe extern "C" fn setsid() -> c_int {
13119 let r = sys_setsid();
13120 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13121 r as c_int
13122}
13123
13124#[no_mangle]
13125pub unsafe extern "C" fn setpgid(pid: c_int, pgid: c_int) -> c_int {
13126 let r = sys_setpgid(pid, pgid);
13127 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13128 0
13129}
13130
13131#[no_mangle]
13132pub unsafe extern "C" fn getpgid(pid: c_int) -> c_int {
13133 let r = sys_getpgid(pid);
13134 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13135 r as c_int
13136}
13137
13138#[no_mangle]
13139pub unsafe extern "C" fn getsid(pid: c_int) -> c_int {
13140 let r = sys_getsid(pid);
13141 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13142 r as c_int
13143}
13144
13145#[no_mangle]
13146pub unsafe extern "C" fn getpgrp() -> c_int {
13147 sys_getpgid(0) as c_int
13148}
13149
13150#[no_mangle]
13151pub unsafe extern "C" fn setpgrp() -> c_int {
13152 setpgid(0, 0)
13153}
13154
13155#[no_mangle]
13156unsafe fn mkstemps_impl(template: *mut c_char, suffixlen: i32) -> c_int {
13157 if template.is_null() || suffixlen < 0 {
13158 ERRNO!() = EINVAL;
13159 return -1;
13160 }
13161 let len = strlen(template as *const c_char);
13162 let suffix = suffixlen as usize;
13163 if len < 6 + suffix {
13164 ERRNO!() = EINVAL;
13165 return -1;
13166 }
13167 let x_start = len - suffix - 6;
13168 for i in x_start..x_start + 6 {
13169 if *template.add(i) != b'X' as c_char {
13170 ERRNO!() = EINVAL;
13171 return -1;
13172 }
13173 }
13174 let mut ts: timespec = core::mem::zeroed();
13175 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
13176 let mut ctr: u32 = ts.tv_nsec as u32;
13177 for _ in 0..100 {
13178 ctr = ctr.wrapping_mul(1103515245).wrapping_add(12345);
13179 let mut seed = ctr;
13180 let hex = b"0123456789abcdef";
13181 for i in x_start..x_start + 6 {
13182 *template.add(i) = hex[(seed & 0xf) as usize] as c_char;
13183 seed >>= 4;
13184 }
13185 let fd = sys_open(template as *const u8, (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
13186 if fd >= 0 {
13187 return fd as c_int;
13188 }
13189 let e = (-fd) as c_int;
13190 if e != EEXIST_VAL {
13191 ERRNO!() = e;
13192 return -1;
13193 }
13194 }
13195 ERRNO!() = EEXIST_VAL;
13196 -1
13197}
13198
13199#[no_mangle]
13200pub unsafe extern "C" fn mkstemp(template: *mut c_char) -> c_int {
13201 mkstemps_impl(template, 0)
13202}
13203
13204#[no_mangle]
13205pub unsafe extern "C" fn mkdir(path: *const c_char, mode: c_uint) -> c_int {
13206 let r = sys_mkdirat(AT_FDCWD, path as *const u8, mode);
13207 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13208 0
13209}
13210
13211#[no_mangle]
13216pub unsafe extern "C" fn dirname(s: *mut c_char) -> *mut c_char {
13217 if s.is_null() || *s == 0 {
13218 return b".\0".as_ptr() as *mut c_char;
13219 }
13220 let mut i = strlen(s as *const c_char);
13221 i = i.wrapping_sub(1);
13222 while i > 0 && *s.add(i) == b'/' as c_char {
13224 i = i.wrapping_sub(1);
13225 }
13226 if i == 0 && *s.add(0) == b'/' as c_char {
13227 return b"/\0".as_ptr() as *mut c_char;
13228 }
13229 while i > 0 && *s.add(i) != b'/' as c_char {
13231 i = i.wrapping_sub(1);
13232 }
13233 if i == 0 {
13234 if *s.add(0) == b'/' as c_char {
13235 return b"/\0".as_ptr() as *mut c_char;
13236 }
13237 return b".\0".as_ptr() as *mut c_char;
13238 }
13239 while i > 0 && *s.add(i - 1) == b'/' as c_char {
13241 i = i.wrapping_sub(1);
13242 }
13243 if i == 0 {
13244 return b"/\0".as_ptr() as *mut c_char;
13245 }
13246 *s.add(i) = 0;
13247 s
13248}
13249
13250#[no_mangle]
13251pub unsafe extern "C" fn basename(s: *mut c_char) -> *mut c_char {
13252 if s.is_null() || *s == 0 {
13253 return b".\0".as_ptr() as *mut c_char;
13254 }
13255 let mut i = strlen(s as *const c_char);
13256 i = i.wrapping_sub(1);
13257 while i > 0 && *s.add(i) == b'/' as c_char {
13259 *s.add(i) = 0;
13260 i = i.wrapping_sub(1);
13261 }
13262 while i > 0 && *s.add(i - 1) != b'/' as c_char {
13264 i = i.wrapping_sub(1);
13265 }
13266 s.add(i)
13267}
13268
13269const AF_INET_VAL: c_int = 2;
13274const AF_INET6_VAL: c_int = 10;
13275const EAFNOSUPPORT: c_int = 97;
13276const ENOSPC_VAL2: c_int = 28;
13277
13278unsafe fn inet_pton_v4(s: *const u8, a: *mut u8) -> c_int {
13279 let mut p = s;
13280 let mut i = 0;
13281 while i < 4 {
13282 let oct_start = p;
13283 let mut v: u32 = 0;
13284 let mut j: u32 = 0;
13285 while j < 3 && *p >= b'0' && *p <= b'9' {
13286 v = v * 10 + (*p - b'0') as u32;
13287 p = p.add(1);
13288 j += 1;
13289 }
13290 if j == 0 || (j > 1 && *oct_start == b'0') || v > 255 { return 0; }
13291 *a.add(i) = v as u8;
13292 if *p == 0 && i == 3 { return 1; }
13293 if *p != b'.' { return 0; }
13294 p = p.add(1);
13295 i += 1;
13296 }
13297 0
13298}
13299
13300unsafe fn inet_pton_v6(s: *const u8, a: *mut u8) -> c_int {
13301 let mut ip = [0u16; 8];
13302 let mut p = s;
13303 let mut i: usize = 0;
13304 let mut brk: isize = -1;
13305 let mut need_v4 = false;
13306 let mut v4_start: *const u8 = core::ptr::null();
13307
13308 if *p == b':' {
13309 p = p.add(1);
13310 if *p != b':' { return 0; }
13311 }
13312
13313 loop {
13314 if *p == b':' && brk < 0 {
13315 brk = i as isize;
13316 ip[i & 7] = 0;
13317 p = p.add(1);
13318 if *p == 0 { break; }
13319 if i == 7 { return 0; }
13320 i += 1;
13321 continue;
13322 }
13323 v4_start = p;
13324 let mut v: u16 = 0;
13325 let mut j = 0;
13326 while j < 4 {
13327 let d = hex_digit(*p);
13328 if d < 0 { break; }
13329 v = v * 16 + d as u16;
13330 p = p.add(1);
13331 j += 1;
13332 }
13333 if j == 0 { return 0; }
13334 ip[i & 7] = v;
13335 if *p == 0 && (brk >= 0 || i == 7) { break; }
13336 if i == 7 { return 0; }
13337 if *p != b':' {
13338 if *p != b'.' || (i < 6 && brk < 0) { return 0; }
13339 need_v4 = true;
13340 i += 1;
13341 ip[i & 7] = 0;
13342 break;
13343 }
13344 p = p.add(1);
13345 i += 1;
13346 }
13347
13348 if brk >= 0 {
13349 let trail_count = i + 1 - brk as usize;
13351 let dest_start = brk as usize + 7 - i;
13352 for j in (0..trail_count).rev() {
13354 ip[dest_start + j] = ip[brk as usize + j];
13355 }
13356 for j in 0..(7 - i) {
13357 ip[brk as usize + j] = 0;
13358 }
13359 }
13360
13361 for k in 0..8 {
13362 *a.add(k * 2) = (ip[k] >> 8) as u8;
13363 *a.add(k * 2 + 1) = (ip[k] & 0xff) as u8;
13364 }
13365
13366 if need_v4 {
13367 if inet_pton_v4(v4_start, a.add(12)) <= 0 { return 0; }
13368 }
13369 1
13370}
13371
13372unsafe fn hex_digit(c: u8) -> i32 {
13373 if c >= b'0' && c <= b'9' { (c - b'0') as i32 }
13374 else if c >= b'a' && c <= b'f' { (c - b'a' + 10) as i32 }
13375 else if c >= b'A' && c <= b'F' { (c - b'A' + 10) as i32 }
13376 else { -1 }
13377}
13378
13379#[no_mangle]
13380pub unsafe extern "C" fn inet_pton(af: c_int, s: *const c_char, a: *mut c_void) -> c_int {
13381 if af == AF_INET_VAL {
13382 inet_pton_v4(s as *const u8, a as *mut u8)
13383 } else if af == AF_INET6_VAL {
13384 inet_pton_v6(s as *const u8, a as *mut u8)
13385 } else {
13386 ERRNO!() = EAFNOSUPPORT;
13387 -1
13388 }
13389}
13390
13391#[no_mangle]
13392pub unsafe extern "C" fn inet_ntop(af: c_int, a: *const c_void, s: *mut c_char, size: u32) -> *mut c_char {
13393 if af == AF_INET_VAL {
13394 let b = a as *const u8;
13395 let needed = 16; if size < needed as u32 { ERRNO!() = ENOSPC_VAL2; return core::ptr::null_mut(); }
13397 let mut pos = 0;
13398 for i in 0..4 {
13399 if i > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
13400 let (buf, len) = format_u64(*b.add(i) as u64);
13401 for j in 0..len { *s.add(pos) = buf[j] as c_char; pos += 1; }
13402 }
13403 *s.add(pos) = 0;
13404 s
13405 } else if af == AF_INET6_VAL {
13406 let b = a as *const u8;
13407 let needed = 46; if size < needed as u32 { ERRNO!() = ENOSPC_VAL2; return core::ptr::null_mut(); }
13409 let mut words = [0u16; 8];
13410 for i in 0..8 {
13411 words[i] = ((*b.add(i * 2) as u16) << 8) | (*b.add(i * 2 + 1) as u16);
13412 }
13413 let mut pos = 0usize;
13415 if words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0
13416 && words[4] == 0 && words[5] == 0xffff
13417 {
13418 let prefix = b"::ffff:";
13419 for k in 0..prefix.len() { *s.add(pos) = prefix[k] as c_char; pos += 1; }
13420 for idx in 0..4 {
13421 if idx > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
13422 let octet = *b.add(12 + idx);
13423 if octet >= 100 {
13424 *s.add(pos) = (b'0' + octet / 100) as c_char; pos += 1;
13425 *s.add(pos) = (b'0' + (octet / 10) % 10) as c_char; pos += 1;
13426 } else if octet >= 10 {
13427 *s.add(pos) = (b'0' + octet / 10) as c_char; pos += 1;
13428 }
13429 *s.add(pos) = (b'0' + octet % 10) as c_char; pos += 1;
13430 }
13431 *s.add(pos) = 0;
13432 return s;
13433 }
13434 let mut best_start: isize = -1;
13436 let mut best_len: usize = 0;
13437 let mut j: usize = 0;
13438 while j < 8 {
13439 if words[j] == 0 {
13440 let mut k = j;
13441 while k < 8 && words[k] == 0 { k += 1; }
13442 let run = k - j;
13443 if run > best_len { best_start = j as isize; best_len = run; }
13444 j = k;
13445 } else {
13446 j += 1;
13447 }
13448 }
13449 let mut i: usize = 0;
13450 let mut prev_in_run = false;
13451 while i < 8 {
13452 let in_run = best_len >= 2 && i >= best_start as usize && i < best_start as usize + best_len;
13453 if in_run {
13454 if i == best_start as usize {
13455 *s.add(pos) = b':' as c_char; pos += 1;
13456 *s.add(pos) = b':' as c_char; pos += 1;
13457 }
13458 i += 1;
13459 prev_in_run = true;
13460 continue;
13461 }
13462 if i > 0 && !prev_in_run {
13463 *s.add(pos) = b':' as c_char; pos += 1;
13464 }
13465 let (buf, len) = format_hex(words[i] as u64, false);
13466 for k in 0..len { *s.add(pos) = buf[k] as c_char; pos += 1; }
13467 i += 1;
13468 prev_in_run = false;
13469 }
13470 *s.add(pos) = 0;
13471 s
13472 } else {
13473 ERRNO!() = EAFNOSUPPORT;
13474 core::ptr::null_mut()
13475 }
13476}
13477
13478#[no_mangle]
13479pub unsafe extern "C" fn inet_aton(s: *const c_char, dest: *mut c_void) -> c_int {
13480 let a = dest as *mut u8;
13481 let mut p = s as *const u8;
13482 let mut vals = [0u64; 4];
13483 let mut i = 0usize;
13484 while i < 4 {
13485 if *p < b'0' || *p > b'9' { return 0; }
13486 let mut base = 10u32;
13487 if *p == b'0' {
13488 let c = *p.add(1);
13489 if c == b'x' || c == b'X' {
13490 base = 16;
13491 p = p.add(2);
13492 if !((*p >= b'0' && *p <= b'9')
13493 || (*p >= b'a' && *p <= b'f')
13494 || (*p >= b'A' && *p <= b'F')) {
13495 return 0;
13496 }
13497 } else {
13498 base = 8;
13499 }
13500 }
13501 let mut v: u64 = 0;
13502 let start = p;
13503 loop {
13504 let c = *p;
13505 let d = if c >= b'0' && c <= b'9' {
13506 (c - b'0') as u64
13507 } else if base == 16 && c >= b'a' && c <= b'f' {
13508 (c - b'a' + 10) as u64
13509 } else if base == 16 && c >= b'A' && c <= b'F' {
13510 (c - b'A' + 10) as u64
13511 } else {
13512 break;
13513 };
13514 v = v * (base as u64) + d;
13515 p = p.add(1);
13516 }
13517 if p == start { return 0; }
13518 vals[i] = v;
13519 if *p == 0 {
13520 break;
13521 }
13522 if *p != b'.' || i == 3 { return 0; }
13523 p = p.add(1);
13524 i += 1;
13525 }
13526 if i == 4 { return 0; }
13527 if i < 1 { vals[1] = vals[0] & 0xffffff; vals[0] >>= 24; }
13528 if i < 2 { vals[2] = vals[1] & 0xffff; vals[1] >>= 16; }
13529 if i < 3 { vals[3] = vals[2] & 0xff; vals[2] >>= 8; }
13530 for j in 0..4 {
13531 if vals[j] > 255 { return 0; }
13532 *a.add(j) = vals[j] as u8;
13533 }
13534 1
13535}
13536
13537#[no_mangle]
13538pub unsafe extern "C" fn inet_addr(s: *const c_char) -> u32 {
13539 let mut a = [0u8; 4];
13540 if inet_aton(s, a.as_mut_ptr() as *mut c_void) == 1 {
13541 u32::from_ne_bytes(a)
13542 } else {
13543 !0u32 }
13545}
13546
13547#[no_mangle]
13548pub unsafe extern "C" fn inet_ntoa(addr: u32) -> *mut c_char {
13549 static mut NTOA_BUF: [c_char; 16] = [0; 16];
13550 let b = addr.to_ne_bytes();
13551 let mut pos = 0;
13552 for i in 0..4 {
13553 if i > 0 { NTOA_BUF[pos] = b'.' as c_char; pos += 1; }
13554 let (buf, len) = format_u64(b[i] as u64);
13555 for j in 0..len { NTOA_BUF[pos] = buf[j] as c_char; pos += 1; }
13556 }
13557 NTOA_BUF[pos] = 0;
13558 core::ptr::addr_of_mut!(NTOA_BUF).cast::<c_char>()
13559}
13560
13561#[no_mangle]
13563pub unsafe extern "C" fn inet_network(s: *const c_char) -> u32 {
13564 inet_addr(s).to_be()
13565}
13566
13567#[no_mangle]
13568pub extern "C" fn inet_makeaddr(net: c_int, host: c_int) -> u32 {
13569 let addr: u32;
13570 if (net as u32) < 128 {
13571 addr = (net as u32) << 24;
13572 } else if (net as u32) < 0x10000 {
13573 addr = (net as u32) << 16;
13574 } else if (net as u32) < 0x1000000 {
13575 addr = (net as u32) << 8;
13576 } else {
13577 addr = net as u32;
13578 }
13579 addr | (host as u32 & 0xffffffff)
13580}
13581
13582#[no_mangle]
13583pub extern "C" fn inet_lnaof(addr: u32) -> c_int {
13584 let h = u32::from_be(addr);
13585 if h < 0x80000000 { (h & 0x00ffffff) as c_int }
13586 else if h < 0xc0000000 { (h & 0x0000ffff) as c_int }
13587 else { (h & 0x000000ff) as c_int }
13588}
13589
13590#[no_mangle]
13591pub extern "C" fn inet_netof(addr: u32) -> c_int {
13592 let h = u32::from_be(addr);
13593 if h < 0x80000000 { (h >> 24) as c_int }
13594 else if h < 0xc0000000 { (h >> 16) as c_int }
13595 else { (h >> 8) as c_int }
13596}
13597
13598unsafe fn parse_float(s: *const u8, endptr: *mut *mut u8, is_f32: bool) -> f64 {
13607 let mut p = s;
13608 while *p == b' ' || *p == b'\t' || *p == b'\n' || *p == b'\r' { p = p.add(1); }
13610 let mut neg = false;
13611 if *p == b'-' { neg = true; p = p.add(1); }
13612 else if *p == b'+' { p = p.add(1); }
13613
13614 if (*p | 0x20) == b'i'
13616 && (*p.add(1) | 0x20) == b'n'
13617 && (*p.add(2) | 0x20) == b'f'
13618 {
13619 p = p.add(3);
13620 if (*p | 0x20) == b'i'
13622 && (*p.add(1) | 0x20) == b't'
13623 && (*p.add(2) | 0x20) == b'y'
13624 {
13625 p = p.add(3);
13626 }
13627 if !endptr.is_null() { *endptr = p as *mut u8; }
13628 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13629 }
13630 if (*p | 0x20) == b'n'
13632 && (*p.add(1) | 0x20) == b'a'
13633 && (*p.add(2) | 0x20) == b'n'
13634 {
13635 p = p.add(3);
13636 if *p == b'(' {
13638 p = p.add(1);
13639 while *p != 0 && *p != b')' { p = p.add(1); }
13640 if *p == b')' { p = p.add(1); }
13641 }
13642 if !endptr.is_null() { *endptr = p as *mut u8; }
13643 return if neg { -f64::NAN } else { f64::NAN };
13644 }
13645
13646 if *p == b'0' && (*p.add(1) == b'x' || *p.add(1) == b'X') {
13648 p = p.add(2);
13649 let mut mant: u128 = 0;
13650 let mut frac_hex: u32 = 0;
13651 let mut found = false;
13652 let mut in_frac = false;
13653
13654 loop {
13655 if let Some(d) = hex_val(*p) {
13656 if mant <= u128::MAX / 16 {
13657 mant = mant * 16 + d as u128;
13658 }
13659 if in_frac { frac_hex += 1; }
13660 p = p.add(1);
13661 found = true;
13662 } else if *p == b'.' && !in_frac {
13663 in_frac = true;
13664 p = p.add(1);
13665 } else {
13666 break;
13667 }
13668 }
13669
13670 if !found {
13671 if !endptr.is_null() { *endptr = s as *mut u8; }
13672 return 0.0;
13673 }
13674
13675 let mut bin_exp: i32 = 0;
13677 if *p == b'p' || *p == b'P' {
13678 p = p.add(1);
13679 let mut exp_neg = false;
13680 if *p == b'-' { exp_neg = true; p = p.add(1); }
13681 else if *p == b'+' { p = p.add(1); }
13682 while *p >= b'0' && *p <= b'9' {
13683 if bin_exp < 100000 {
13684 bin_exp = bin_exp * 10 + (*p - b'0') as i32;
13685 }
13686 p = p.add(1);
13687 }
13688 if exp_neg { bin_exp = -bin_exp; }
13689 }
13690
13691 if !endptr.is_null() { *endptr = p as *mut u8; }
13692 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13693
13694 let total_exp = bin_exp as i64 - 4 * frac_hex as i64;
13695 return hex_mant_to_f64(mant, total_exp, neg);
13696 }
13697
13698 let mut buf = [0u8; 65536];
13700 let mut n = 0usize;
13701 let mut found_digit = false;
13702
13703 while *p >= b'0' && *p <= b'9' {
13704 if n < 65535 { buf[n] = *p; n += 1; }
13705 p = p.add(1);
13706 found_digit = true;
13707 }
13708 if *p == b'.' {
13709 if n < 65535 { buf[n] = b'.'; n += 1; }
13710 p = p.add(1);
13711 while *p >= b'0' && *p <= b'9' {
13712 if n < 65535 { buf[n] = *p; n += 1; }
13713 p = p.add(1);
13714 found_digit = true;
13715 }
13716 }
13717 if !found_digit {
13718 if !endptr.is_null() { *endptr = s as *mut u8; }
13719 return 0.0;
13720 }
13721 if *p == b'e' || *p == b'E' {
13722 if n < 65535 { buf[n] = b'e'; n += 1; }
13723 p = p.add(1);
13724 if *p == b'-' || *p == b'+' {
13725 if n < 65535 { buf[n] = *p; n += 1; }
13726 p = p.add(1);
13727 }
13728 while *p >= b'0' && *p <= b'9' {
13729 if n < 65535 { buf[n] = *p; n += 1; }
13730 p = p.add(1);
13731 }
13732 }
13733
13734 if !endptr.is_null() { *endptr = p as *mut u8; }
13735 let s_str = core::str::from_utf8_unchecked(
13736 core::slice::from_raw_parts(buf.as_ptr(), n),
13737 );
13738 if is_f32 {
13739 match <f32 as core::str::FromStr>::from_str(s_str) {
13740 Ok(v) => { let r = v as f64; if neg { -r } else { r } }
13741 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13742 }
13743 } else {
13744 match <f64 as core::str::FromStr>::from_str(s_str) {
13745 Ok(v) => if neg { -v } else { v },
13746 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13747 }
13748 }
13749}
13750
13751fn hex_mant_to_f64(mant: u128, total_exp: i64, neg: bool) -> f64 {
13755 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13756
13757 let msb = (127 - mant.leading_zeros()) as i64;
13758 let unbiased_exp = msb + total_exp;
13759 let biased_exp = unbiased_exp + 1023;
13760
13761 if biased_exp >= 2047 {
13763 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13764 }
13765
13766 if biased_exp <= 0 {
13768 let shift = total_exp + 1074;
13771 if shift < 0 {
13772 return if neg { -0.0 } else { 0.0 };
13773 }
13774 if shift > 128 {
13775 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13776 }
13777 let shifted = mant << (shift as u32);
13778 let mantissa52 = (shifted as u64) & 0x000FFFFFFFFFFFFF;
13779 let guard = ((shifted >> 52) & 1) != 0;
13780 let sticky = (shifted >> 53) != 0;
13781 let mut result = mantissa52;
13782 if guard && (sticky || (result & 1) != 0) {
13783 result += 1;
13784 if result > 0x000FFFFFFFFFFFFF {
13785 return if neg { -f64::from_bits(1u64 << 52) } else { f64::from_bits(1u64 << 52) };
13787 }
13788 }
13789 return if neg { -f64::from_bits(result) } else { f64::from_bits(result) };
13790 }
13791
13792 let shift = msb - 52;
13794
13795 if shift <= 0 {
13796 let mantissa = ((mant as u64) & ((1u64 << msb as u32) - 1)) << ((-shift) as u32);
13798 let bits = ((biased_exp as u64) << 52) | mantissa;
13799 return if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) };
13800 }
13801
13802 let mantissa = ((mant >> shift as u32) as u64) & 0x000FFFFFFFFFFFFF;
13804 let guard = ((mant >> (shift as u32 - 1)) & 1) != 0;
13805 let sticky = if shift > 1 {
13806 (mant & ((1u128 << (shift as u32 - 1)) - 1)) != 0
13807 } else { false };
13808
13809 let mut result_mant = mantissa;
13810 let mut result_exp = biased_exp;
13811 if guard && (sticky || (result_mant & 1) != 0) {
13812 result_mant += 1;
13813 if result_mant > 0x000FFFFFFFFFFFFF {
13814 result_mant = 0;
13815 result_exp += 1;
13816 if result_exp >= 2047 {
13817 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13818 }
13819 }
13820 }
13821
13822 let bits = ((result_exp as u64) << 52) | result_mant;
13823 if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) }
13824}
13825
13826unsafe fn hex_val(c: u8) -> Option<u8> {
13827 if c >= b'0' && c <= b'9' { Some(c - b'0') }
13828 else if c >= b'a' && c <= b'f' { Some(c - b'a' + 10) }
13829 else if c >= b'A' && c <= b'F' { Some(c - b'A' + 10) }
13830 else { None }
13831}
13832
13833#[no_mangle]
13834pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13835 let mut end: *mut u8 = s as *mut u8;
13836 let r = parse_float(s as *const u8, &mut end, false);
13837 if !endptr.is_null() { *endptr = end as *mut c_char; }
13838 r
13839}
13840
13841#[no_mangle]
13842pub unsafe extern "C" fn strtof(s: *const c_char, endptr: *mut *mut c_char) -> f32 {
13843 let mut end: *mut u8 = s as *mut u8;
13844 let r = parse_float(s as *const u8, &mut end, true);
13845 if !endptr.is_null() { *endptr = end as *mut c_char; }
13846 r as f32
13847}
13848
13849#[no_mangle]
13850#[cfg(target_arch = "x86_64")]
13851pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13852 strtod(s, endptr)
13853}
13854
13855#[no_mangle]
13856#[cfg(target_arch = "aarch64")]
13857pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13858 strtod(s, endptr) as f128
13859}
13860
13861#[no_mangle]
13862#[cfg(target_arch = "riscv64")]
13863pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13864 strtod(s, endptr) as f128
13865}
13866
13867#[no_mangle]
13868pub unsafe extern "C" fn atof(s: *const c_char) -> f64 {
13869 strtod(s, core::ptr::null_mut())
13870}
13871
13872#[repr(C)]
13877struct MsCookie {
13878 bufp: *mut *mut c_char,
13879 sizep: *mut usize,
13880 pos: usize,
13881 len: usize,
13882 buf: *mut u8,
13883 space: usize,
13884}
13885
13886#[repr(C)]
13887struct MfCookie {
13888 pos: usize,
13889 len: usize,
13890 size: usize,
13891 buf: *mut u8,
13892 mode: c_char,
13893}
13894
13895unsafe extern "C" fn ms_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13896 let c = (*f).cookie as *mut MsCookie;
13897 if whence < 0 || whence > 2 { ERRNO!() = EINVAL; return -1; }
13898 let base: i64 = match whence {
13899 0 => 0,
13900 1 => (*c).pos as i64,
13901 2 => (*c).len as i64,
13902 _ => { ERRNO!() = EINVAL; return -1; }
13903 };
13904 if off < -base || off > isize::MAX as i64 - base { ERRNO!() = EINVAL; return -1; }
13905 (*c).pos = (base + off) as usize;
13906 (*c).pos as i64
13907}
13908
13909unsafe extern "C" fn ms_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13910 let c = (*f).cookie as *mut MsCookie;
13911 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13912 if buffered > 0 {
13913 (*f).wpos = (*f).wbase;
13914 if ms_write(f, (*f).wbase, buffered) < buffered { return 0; }
13915 }
13916 if len == 0 { return 0; }
13917 if (*c).pos + len >= (*c).space {
13918 let new_space = 2 * (*c).space + 1 | (*c).pos + len + 1;
13919 let newbuf = realloc((*c).buf as *mut c_void, new_space) as *mut u8;
13920 if newbuf.is_null() { return 0; }
13921 *(*c).bufp = newbuf as *mut c_char;
13922 core::ptr::write_bytes(newbuf.add((*c).space), 0, new_space - (*c).space);
13923 (*c).buf = newbuf;
13924 (*c).space = new_space;
13925 }
13926 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), len);
13927 (*c).pos += len;
13928 if (*c).pos >= (*c).len { (*c).len = (*c).pos; }
13929 *(*c).sizep = (*c).pos;
13930 len
13931}
13932
13933unsafe extern "C" fn ms_close(_f: *mut FILE) -> c_int {
13934 0
13935}
13936
13937#[no_mangle]
13938pub unsafe extern "C" fn open_memstream(bufp: *mut *mut c_char, sizep: *mut usize) -> *mut FILE {
13939 if bufp.is_null() || sizep.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
13940 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
13941 if f.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13942 let buf_area = buf_ptr(f);
13943 init_file(f, -1, b"w\0".as_ptr() as *const c_char, Some(ms_close), buf_area, BUFSIZ);
13944 (*f).flags = F_NORD | F_SVB;
13945 (*f).lbf = -1;
13946 let c = calloc(1, core::mem::size_of::<MsCookie>()) as *mut MsCookie;
13947 if c.is_null() { free(f as *mut c_void); ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13948 (*c).bufp = bufp;
13949 (*c).sizep = sizep;
13950 (*c).pos = 0;
13951 (*c).len = 0;
13952 (*c).buf = core::ptr::null_mut();
13953 (*c).space = 0;
13954 (*f).cookie = c as *mut c_void;
13955 (*f).write_fn = Some(ms_write);
13956 (*f).seek_fn = Some(ms_seek);
13957 *bufp = core::ptr::null_mut();
13958 *sizep = 0;
13959 f
13960}
13961
13962unsafe extern "C" fn mseek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13963 let c = (*f).cookie as *mut MfCookie;
13964 if whence < 0 || whence > 2 { ERRNO!() = EINVAL; return -1; }
13965 let base: i64 = match whence {
13966 0 => 0,
13967 1 => (*c).pos as i64,
13968 2 => (*c).len as i64,
13969 _ => { ERRNO!() = EINVAL; return -1; }
13970 };
13971 if off < -base || off > (*c).size as i64 - base { ERRNO!() = EINVAL; return -1; }
13972 (*c).pos = (base + off) as usize;
13973 (*c).pos as i64
13974}
13975
13976unsafe extern "C" fn mread(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
13977 let c = (*f).cookie as *mut MfCookie;
13978 let mut rem = if (*c).pos <= (*c).len { (*c).len - (*c).pos } else { 0 };
13979 let mut l = len;
13980 if l > rem {
13981 l = rem;
13982 (*f).flags |= F_EOF;
13983 }
13984 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), buf, l);
13985 (*c).pos += l;
13986 rem -= l;
13987 if rem > (*f).buf_size { rem = (*f).buf_size; }
13988 (*f).rpos = (*f).buf;
13989 (*f).rend = (*f).buf.add(rem);
13990 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), (*f).rpos, rem);
13991 (*c).pos += rem;
13992 l
13993}
13994
13995unsafe extern "C" fn mwrite(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13996 let c = (*f).cookie as *mut MfCookie;
13997 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13998 if buffered > 0 {
13999 (*f).wpos = (*f).wbase;
14000 if mwrite(f, (*f).wbase, buffered) < buffered { return 0; }
14001 }
14002 if len == 0 { return 0; }
14003 if (*c).mode == b'a' as c_char { (*c).pos = (*c).len; }
14004 let rem = (*c).size - (*c).pos;
14005 let mut l = len;
14006 if l > rem { l = rem; }
14007 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), l);
14008 (*c).pos += l;
14009 if (*c).pos > (*c).len {
14010 (*c).len = (*c).pos;
14011 if (*c).len < (*c).size {
14012 *(*c).buf.add((*c).len) = 0;
14013 } else if ((*f).flags & F_NORD) != 0 && (*c).size > 0 {
14014 *(*c).buf.add((*c).size - 1) = 0;
14015 }
14016 }
14017 l
14018}
14019
14020unsafe extern "C" fn mclose(_f: *mut FILE) -> c_int {
14021 0
14022}
14023
14024#[no_mangle]
14025pub unsafe extern "C" fn fmemopen(buf: *mut c_void, size: usize, mode: *const c_char) -> *mut FILE {
14026 if mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
14027 let m = *mode;
14028 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
14029 ERRNO!() = EINVAL; return core::ptr::null_mut();
14030 }
14031 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
14032 let need_alloc = buf.is_null();
14033 let alloc_size = core::mem::size_of::<FILE>() + UNGET + BUFSIZ + if need_alloc { size } else { 0 };
14034 let f = calloc(1, alloc_size) as *mut FILE;
14035 if f.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
14036 let buf_area = buf_ptr(f);
14037 init_file(f, -1, mode, Some(mclose), buf_area, BUFSIZ);
14038 (*f).flags |= F_SVB;
14039 let actual_buf: *mut u8 = if need_alloc {
14040 (f as *mut u8).add(alloc_size - size)
14041 } else {
14042 buf as *mut u8
14043 };
14044 if need_alloc { core::ptr::write_bytes(actual_buf, 0, size); }
14045 let c = calloc(1, core::mem::size_of::<MfCookie>()) as *mut MfCookie;
14046 if c.is_null() { free(f as *mut c_void); ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
14047 (*c).buf = actual_buf;
14048 (*c).size = size;
14049 (*c).mode = m;
14050 (*f).cookie = c as *mut c_void;
14051 (*f).read_fn = Some(mread);
14052 (*f).write_fn = Some(mwrite);
14053 (*f).seek_fn = Some(mseek);
14054 if !has_plus { (*f).flags = if m == b'r' as c_char { F_NOWR } else { F_NORD }; }
14055 if m == b'r' as c_char {
14056 (*c).len = size;
14057 } else if m == b'a' as c_char {
14058 (*c).len = strnlen(actual_buf, size);
14059 (*c).pos = (*c).len;
14060 } else if has_plus {
14061 *actual_buf = 0;
14062 }
14063 f
14064}
14065
14066#[repr(C)]
14071struct kernel_stat64 {
14072 st_dev: u64,
14073 st_ino: u64,
14074 st_nlink: u64,
14075 st_mode: u32,
14076 st_uid: u32,
14077 st_gid: u32,
14078 __pad0: c_int,
14079 st_rdev: u64,
14080 st_size: i64,
14081 st_blksize: i64,
14082 st_blocks: i64,
14083 st_atime: i64,
14084 st_atime_nsec: i64,
14085 st_mtime: i64,
14086 st_mtime_nsec: i64,
14087 st_ctime: i64,
14088 st_ctime_nsec: i64,
14089 __unused: [i64; 3],
14090}
14091
14092#[inline]
14094unsafe fn sys_stat(path: *const u8, statbuf: *mut kernel_stat64) -> i64 {
14095 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, statbuf as i64, 0)
14096}
14097
14098const HSEARCH_MINSIZE: usize = 8;
14103
14104#[repr(C)]
14105#[derive(Copy, Clone)]
14106pub struct HSearchEntry {
14107 key: *mut c_char,
14108 data: *mut c_void,
14109}
14110
14111#[repr(C)]
14112struct HTab {
14113 entries: *mut HSearchEntry,
14114 mask: usize,
14115 used: usize,
14116}
14117
14118#[repr(C)]
14119pub struct HSearchData {
14120 tab: *mut HTab,
14121 __unused1: c_uint,
14122 __unused2: c_uint,
14123}
14124
14125static mut HTAB_DATA: HSearchData = HSearchData {
14127 tab: core::ptr::null_mut(),
14128 __unused1: 0,
14129 __unused2: 0,
14130};
14131
14132unsafe fn keyhash(k: *const c_char) -> usize {
14133 let mut h: usize = 0;
14134 let mut p = k;
14135 while *p != 0 {
14136 h = h.wrapping_mul(31).wrapping_add(*p as usize);
14137 p = p.add(1);
14138 }
14139 h
14140}
14141
14142unsafe fn htab_lookup(key: *const c_char, hash: usize, htab: *mut HSearchData) -> *mut HSearchEntry {
14143 let tab = (*htab).tab;
14144 let mask = (*tab).mask;
14145 let entries = (*tab).entries;
14146 let mut i = hash;
14147 let mut j: usize = 1;
14148 loop {
14149 let e = entries.add(i & mask);
14150 if (*e).key.is_null() || strcmp((*e).key as *const u8, key as *const u8) == 0 {
14151 return e;
14152 }
14153 i = i.wrapping_add(j);
14154 j += 1;
14155 }
14156}
14157
14158unsafe fn htab_resize(nel: usize, htab: *mut HSearchData) -> c_int {
14159 let tab = (*htab).tab;
14160 let old_entries = (*tab).entries;
14161 let old_size = (*tab).mask + 1;
14162
14163 let mut newsize: usize = HSEARCH_MINSIZE;
14164 while newsize < nel {
14165 let Some(next) = newsize.checked_mul(2) else {
14166 ERRNO!() = ENOMEM;
14167 return 0;
14168 };
14169 newsize = next;
14170 }
14171
14172 let new_entries = calloc(newsize, core::mem::size_of::<HSearchEntry>()) as *mut HSearchEntry;
14173 if new_entries.is_null() {
14174 ERRNO!() = ENOMEM;
14175 return 0;
14176 }
14177 (*tab).entries = new_entries;
14178 (*tab).mask = newsize - 1;
14179
14180 if !old_entries.is_null() {
14181 for idx in 0..old_size {
14182 let old_e = old_entries.add(idx);
14183 if !(*old_e).key.is_null() {
14184 let h = keyhash((*old_e).key);
14185 let mut i = h;
14186 let mut j: usize = 1;
14187 loop {
14188 let e = new_entries.add(i & (*tab).mask);
14189 if (*e).key.is_null() {
14190 *e = *old_e;
14191 break;
14192 }
14193 i = i.wrapping_add(j);
14194 j += 1;
14195 }
14196 }
14197 }
14198 free(old_entries as *mut c_void);
14199 }
14200 1
14201}
14202
14203unsafe fn hcreate_r_impl(nel: usize, htab: *mut HSearchData) -> c_int {
14204 if nel == 0 || nel > (1usize << 30) {
14205 ERRNO!() = ENOMEM;
14206 return 0;
14207 }
14208 (*htab).tab = calloc(1, core::mem::size_of::<HTab>()) as *mut HTab;
14209 if (*htab).tab.is_null() {
14210 ERRNO!() = ENOMEM;
14211 return 0;
14212 }
14213 if htab_resize(nel, htab) == 0 {
14214 free((*htab).tab as *mut c_void);
14215 (*htab).tab = core::ptr::null_mut();
14216 return 0;
14217 }
14218 1
14219}
14220
14221unsafe fn hdestroy_r_impl(htab: *mut HSearchData) {
14222 if !(*htab).tab.is_null() {
14223 if !(*(*htab).tab).entries.is_null() {
14224 free((*(*htab).tab).entries as *mut c_void);
14225 }
14226 free((*htab).tab as *mut c_void);
14227 (*htab).tab = core::ptr::null_mut();
14228 }
14229}
14230
14231unsafe fn hsearch_r_impl(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
14232 let hash = keyhash(item.key);
14233 let e = htab_lookup(item.key, hash, htab);
14234
14235 if !(*e).key.is_null() {
14236 *retval = e;
14237 return 1;
14238 }
14239 if action == 0 { *retval = core::ptr::null_mut();
14241 return 0;
14242 }
14243 let item_key = item.key;
14245 *e = item;
14246 (*(*htab).tab).used += 1;
14247 if (*(*htab).tab).used > (*(*htab).tab).mask - (*(*htab).tab).mask / 4 {
14248 if htab_resize(2 * (*(*htab).tab).used, htab) == 0 {
14249 (*(*htab).tab).used -= 1;
14250 (*e).key = core::ptr::null_mut();
14251 *retval = core::ptr::null_mut();
14252 return 0;
14253 }
14254 let e2 = htab_lookup(item_key, hash, htab);
14255 *retval = e2;
14256 return 1;
14257 }
14258 *retval = e;
14259 1
14260}
14261
14262#[no_mangle]
14263pub unsafe extern "C" fn hcreate(nel: usize) -> c_int {
14264 hcreate_r_impl(nel, core::ptr::addr_of_mut!(HTAB_DATA))
14265}
14266
14267#[no_mangle]
14268pub unsafe extern "C" fn hdestroy() {
14269 hdestroy_r_impl(core::ptr::addr_of_mut!(HTAB_DATA));
14270}
14271
14272#[no_mangle]
14273pub unsafe extern "C" fn hsearch(item: HSearchEntry, action: c_int) -> *mut HSearchEntry {
14274 let mut e: *mut HSearchEntry = core::ptr::null_mut();
14275 hsearch_r_impl(item, action, &mut e, core::ptr::addr_of_mut!(HTAB_DATA));
14276 e
14277}
14278
14279#[no_mangle]
14280pub unsafe extern "C" fn hcreate_r(nel: usize, htab: *mut HSearchData) -> c_int {
14281 hcreate_r_impl(nel, htab)
14282}
14283
14284#[no_mangle]
14285pub unsafe extern "C" fn hdestroy_r(htab: *mut HSearchData) {
14286 hdestroy_r_impl(htab);
14287}
14288
14289#[no_mangle]
14290pub unsafe extern "C" fn hsearch_r(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
14291 hsearch_r_impl(item, action, retval, htab)
14292}
14293
14294#[repr(C)]
14299struct QueNode {
14300 next: *mut QueNode,
14301 prev: *mut QueNode,
14302}
14303
14304#[no_mangle]
14305pub unsafe extern "C" fn insque(element: *mut c_void, pred: *mut c_void) {
14306 let e = element as *mut QueNode;
14307 let p = pred as *mut QueNode;
14308 if p.is_null() {
14309 (*e).next = core::ptr::null_mut();
14310 (*e).prev = core::ptr::null_mut();
14311 return;
14312 }
14313 (*e).next = (*p).next;
14314 (*e).prev = p;
14315 (*p).next = e;
14316 if !(*e).next.is_null() {
14317 (*(*e).next).prev = e;
14318 }
14319}
14320
14321#[no_mangle]
14322pub unsafe extern "C" fn remque(element: *mut c_void) {
14323 let e = element as *mut QueNode;
14324 if !(*e).next.is_null() {
14325 (*(*e).next).prev = (*e).prev;
14326 }
14327 if !(*e).prev.is_null() {
14328 (*(*e).prev).next = (*e).next;
14329 }
14330}
14331
14332#[no_mangle]
14337pub unsafe extern "C" fn lsearch(
14338 key: *const c_void,
14339 base: *mut c_void,
14340 nelp: *mut usize,
14341 width: usize,
14342 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
14343) -> *mut c_void {
14344 let n = *nelp;
14345 let p = base as *mut u8;
14346 for i in 0..n {
14347 let elem = p.add(i * width);
14348 if compar.unwrap()(key, elem as *const c_void) == 0 {
14349 return elem as *mut c_void;
14350 }
14351 }
14352 let dest = p.add(n * width);
14353 memcpy(dest as *mut c_void, key as *const c_void, width);
14354 *nelp = n + 1;
14355 dest as *mut c_void
14356}
14357
14358#[no_mangle]
14359pub unsafe extern "C" fn lfind(
14360 key: *const c_void,
14361 base: *const c_void,
14362 nelp: *mut usize,
14363 width: usize,
14364 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
14365) -> *mut c_void {
14366 let n = *nelp;
14367 let p = base as *const u8;
14368 for i in 0..n {
14369 let elem = p.add(i * width);
14370 if compar.unwrap()(key, elem as *const c_void) == 0 {
14371 return elem as *mut c_void;
14372 }
14373 }
14374 core::ptr::null_mut()
14375}
14376
14377#[repr(C)]
14383pub struct TreeNode {
14384 key: *const c_void,
14385 left: *mut TreeNode,
14386 right: *mut TreeNode,
14387}
14388
14389type ComparFn = Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>;
14390
14391unsafe fn bst_new(key: *const c_void) -> *mut TreeNode {
14392 let n = calloc(1, core::mem::size_of::<TreeNode>()) as *mut TreeNode;
14393 if !n.is_null() {
14394 (*n).key = key;
14395 (*n).left = core::ptr::null_mut();
14396 (*n).right = core::ptr::null_mut();
14397 }
14398 n
14399}
14400
14401#[no_mangle]
14402pub unsafe extern "C" fn tsearch(
14403 key: *const c_void,
14404 rootp: *mut *mut TreeNode,
14405 compar: ComparFn,
14406) -> *mut c_void {
14407 if rootp.is_null() {
14408 return core::ptr::null_mut();
14409 }
14410 let mut pp = rootp;
14411 loop {
14412 let n = *pp;
14413 if n.is_null() {
14414 let r = bst_new(key);
14415 if r.is_null() {
14416 return core::ptr::null_mut();
14417 }
14418 *pp = r;
14419 return r as *mut c_void;
14420 }
14421 let c = compar.unwrap()(key, (*n).key);
14422 if c == 0 {
14423 return n as *mut c_void;
14424 }
14425 if c < 0 {
14426 pp = &mut (*n).left;
14427 } else {
14428 pp = &mut (*n).right;
14429 }
14430 }
14431}
14432
14433#[no_mangle]
14434pub unsafe extern "C" fn tfind(
14435 key: *const c_void,
14436 rootp: *const *mut TreeNode,
14437 compar: ComparFn,
14438) -> *mut c_void {
14439 if rootp.is_null() {
14440 return core::ptr::null_mut();
14441 }
14442 let mut n = *rootp;
14443 loop {
14444 if n.is_null() {
14445 return core::ptr::null_mut();
14446 }
14447 let c = compar.unwrap()(key, (*n).key);
14448 if c == 0 {
14449 return n as *mut c_void;
14450 }
14451 if c < 0 {
14452 n = (*n).left;
14453 } else {
14454 n = (*n).right;
14455 }
14456 }
14457}
14458
14459#[no_mangle]
14460pub unsafe extern "C" fn tdelete(
14461 key: *const c_void,
14462 rootp: *mut *mut TreeNode,
14463 compar: ComparFn,
14464) -> *mut c_void {
14465 if rootp.is_null() {
14466 return core::ptr::null_mut();
14467 }
14468 let mut pp = rootp;
14469 loop {
14470 let n = *pp;
14471 if n.is_null() {
14472 return core::ptr::null_mut();
14473 }
14474 let c = compar.unwrap()(key, (*n).key);
14475 if c == 0 {
14476 break;
14477 }
14478 if c < 0 {
14479 pp = &mut (*n).left;
14480 } else {
14481 pp = &mut (*n).right;
14482 }
14483 }
14484 let n = *pp;
14485 let parent = *rootp;
14487 if !(*n).left.is_null() {
14488 let mut q = &mut (*n).left;
14490 while !(*(*q)).right.is_null() {
14491 q = &mut (*(*q)).right;
14492 }
14493 let pred = *q;
14494 (*n).key = (*pred).key;
14496 *q = (*pred).left;
14498 free(pred as *mut c_void);
14499 } else {
14500 *pp = (*n).right;
14502 free(n as *mut c_void);
14503 }
14504 parent as *mut c_void
14505}
14506
14507#[no_mangle]
14508pub unsafe extern "C" fn twalk(
14509 root: *const TreeNode,
14510 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
14511) {
14512 unsafe fn walk(
14513 node: *const TreeNode,
14514 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
14515 depth: c_int,
14516 ) {
14517 if node.is_null() {
14518 return;
14519 }
14520 let is_leaf = (*node).left.is_null() && (*node).right.is_null();
14521 if is_leaf {
14522 action.unwrap()(node as *const c_void, 3, depth); } else {
14524 action.unwrap()(node as *const c_void, 0, depth); walk((*node).left, action, depth + 1);
14526 action.unwrap()(node as *const c_void, 1, depth); walk((*node).right, action, depth + 1);
14528 action.unwrap()(node as *const c_void, 2, depth); }
14530 }
14531 walk(root, action, 0);
14532}
14533
14534#[no_mangle]
14535pub unsafe extern "C" fn tdestroy(root: *mut TreeNode, freekey: Option<unsafe extern "C" fn(*mut c_void)>) {
14536 if root.is_null() {
14537 return;
14538 }
14539 tdestroy((*root).left, freekey);
14540 tdestroy((*root).right, freekey);
14541 if let Some(f) = freekey {
14542 f((*root).key as *mut c_void);
14543 }
14544 free(root as *mut c_void);
14545}
14546
14547const FNM_PATHNAME: c_int = 0x1;
14552const FNM_NOESCAPE: c_int = 0x2;
14553const FNM_PERIOD: c_int = 0x4;
14554const FNM_LEADING_DIR: c_int = 0x8;
14555const FNM_CASEFOLD: c_int = 0x10;
14556const FNM_NOMATCH: c_int = 1;
14557
14558const FNM_END: c_int = 0;
14559const FNM_STAR: c_int = -5;
14560const FNM_QUESTION: c_int = -4;
14561const FNM_BRACKET: c_int = -3;
14562const FNM_UNMATCHABLE: c_int = -2;
14563
14564fn ascii_tolower(c: u8) -> u8 {
14565 if c >= b'A' && c <= b'Z' { c + 32 } else { c }
14566}
14567
14568fn ascii_toupper(c: u8) -> u8 {
14569 if c >= b'a' && c <= b'z' { c - 32 } else { c }
14570}
14571
14572fn ascii_casefold(k: u8) -> u8 {
14573 let upper = ascii_toupper(k);
14574 if upper != k { upper } else { ascii_tolower(k) }
14575}
14576
14577unsafe fn pat_next(pat: *const u8, m: usize, flags: c_int) -> (c_int, usize) {
14580 if m == 0 || *pat == 0 {
14581 return (FNM_END, 0);
14582 }
14583 let mut p = pat;
14584 let mut step = 1usize;
14585 let mut esc = false;
14586 if *p == b'\\' && !(flags & FNM_NOESCAPE != 0) && *p.add(1) != 0 {
14587 p = p.add(1);
14588 step = 2;
14589 esc = true;
14590 }
14591 if *p == b'[' && !esc {
14592 let mut k = 1usize;
14594 if k < m && (*pat.add(k) == b'^' || *pat.add(k) == b'!') { k += 1; }
14595 if k < m && *pat.add(k) == b']' { k += 1; }
14596 while k < m && *pat.add(k) != 0 && *pat.add(k) != b']' {
14597 if k + 1 < m && *pat.add(k) == b'[' &&
14598 (*pat.add(k+1) == b':' || *pat.add(k+1) == b'.' || *pat.add(k+1) == b'=') {
14599 let z = *pat.add(k+1);
14600 k += 2;
14601 if k < m { k += 1; }
14602 while k < m && *pat.add(k) != 0 && (*pat.add(k-1) != z || *pat.add(k) != b']') { k += 1; }
14603 if k == m || *pat.add(k) == 0 { break; }
14604 }
14605 k += 1;
14606 }
14607 if k == m || *pat.add(k) == 0 {
14608 return (b'[' as c_int, 1);
14610 }
14611 return (FNM_BRACKET, k + 1);
14612 }
14613 if *p == b'*' && !esc {
14614 return (FNM_STAR, 1);
14615 }
14616 if *p == b'?' && !esc {
14617 return (FNM_QUESTION, 1);
14618 }
14619 (*p as c_int, step)
14620}
14621
14622unsafe fn match_class(name: &[u8], k: u8, kfold: u8) -> bool {
14623 let eq = |c: u8| k == c || kfold == c;
14624 let in_range = |lo: u8, hi: u8| (k >= lo && k <= hi) || (kfold >= lo && kfold <= hi);
14625 match name {
14626 b"alnum" => in_range(b'0', b'9') || in_range(b'A', b'Z') || in_range(b'a', b'z'),
14627 b"alpha" => in_range(b'A', b'Z') || in_range(b'a', b'z'),
14628 b"blank" => eq(b' ') || eq(b'\t'),
14629 b"cntrl" => k < 0x20 || k == 0x7f,
14630 b"digit" => in_range(b'0', b'9'),
14631 b"graph" => k >= 0x21 && k <= 0x7e,
14632 b"lower" => in_range(b'a', b'z'),
14633 b"print" => k >= 0x20 && k <= 0x7e,
14634 b"punct" =>
14635 (k >= 0x21 && k <= 0x2f) ||
14636 (k >= 0x3a && k <= 0x40) ||
14637 (k >= 0x5b && k <= 0x60) ||
14638 (k >= 0x7b && k <= 0x7e),
14639 b"space" => eq(b' ') || eq(b'\t') || eq(b'\n') || eq(b'\r') || eq(0x0c) || eq(0x0b),
14640 b"upper" => in_range(b'A', b'Z'),
14641 b"xdigit" => in_range(b'0', b'9') || in_range(b'A', b'F') || in_range(b'a', b'f'),
14642 _ => false,
14643 }
14644}
14645
14646unsafe fn match_bracket(mut p: *const u8, k: u8, kfold: u8) -> bool {
14648 let mut inv = false;
14649 p = p.add(1); if *p == b'^' || *p == b'!' {
14651 inv = true;
14652 p = p.add(1);
14653 }
14654 if *p == b']' {
14656 if k == b']' { return !inv; }
14657 p = p.add(1);
14658 } else if *p == b'-' {
14659 if k == b'-' { return !inv; }
14660 p = p.add(1);
14661 }
14662 while *p != b']' && *p != 0 {
14663 if *p == b'-' && *p.add(1) != b']' && *p.add(1) != 0 {
14664 let lo = *p.sub(1);
14666 let hi = *p.add(1);
14667 if lo <= hi && (k >= lo && k <= hi || kfold >= lo && kfold <= hi) {
14668 return !inv;
14669 }
14670 p = p.add(2);
14671 } else if *p == b'[' && (*p.add(1) == b':' || *p.add(1) == b'.' || *p.add(1) == b'=') {
14672 let z = *p.add(1);
14673 let start = p.add(2);
14674 let mut q = start;
14675 while *q != 0 && (*q != z || *q.add(1) != b']') { q = q.add(1); }
14676 if *q != 0 {
14677 let len = (q as usize) - (start as usize);
14678 if len > 0 {
14679 let inner = core::slice::from_raw_parts(start, len);
14680 let matched =
14681 if z == b':' { match_class(inner, k, kfold) }
14682 else { len == 1 && (inner[0] == k || inner[0] == kfold) };
14683 if matched { return !inv; }
14684 }
14685 p = q.add(2);
14686 continue;
14687 }
14688 } else {
14689 if *p == k || *p == kfold {
14690 return !inv;
14691 }
14692 p = p.add(1);
14693 }
14694 }
14695 inv
14696}
14697
14698unsafe fn fnmatch_internal(pat: *const u8, str: *const u8, flags: c_int) -> c_int {
14700 if flags & FNM_PERIOD != 0 && *str == b'.' && *pat != b'.' {
14702 return FNM_NOMATCH;
14703 }
14704
14705 let mut p = pat;
14706 let mut s = str;
14707
14708 loop {
14710 let (tok, step) = pat_next(p, usize::MAX, flags);
14711 match tok {
14712 FNM_END => {
14713 return if *s == 0 { 0 } else { FNM_NOMATCH };
14714 }
14715 FNM_STAR => {
14716 p = p.add(1);
14717 break;
14718 }
14719 FNM_QUESTION => {
14720 if *s == 0 { return FNM_NOMATCH; }
14721 s = s.add(1);
14722 p = p.add(step);
14723 }
14724 FNM_BRACKET => {
14725 if *s == 0 { return FNM_NOMATCH; }
14726 let k = *s;
14727 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14728 if !match_bracket(p, k, kfold) { return FNM_NOMATCH; }
14729 p = p.add(step);
14730 s = s.add(1);
14731 }
14732 c => {
14733 if *s == 0 { return FNM_NOMATCH; }
14734 let k = *s;
14735 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14736 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14737 p = p.add(step);
14738 s = s.add(1);
14739 }
14740 }
14741 }
14742
14743 let mut ptail = p;
14746 let mut tailcnt: usize = 0;
14747 let mut pp = p;
14748 loop {
14749 let (tok, step) = pat_next(pp, usize::MAX, flags);
14750 if tok == FNM_END { break; }
14751 if tok == FNM_STAR {
14752 tailcnt = 0;
14753 ptail = pp.add(1);
14754 } else {
14755 tailcnt += 1;
14756 }
14757 pp = pp.add(step);
14758 }
14759
14760 let slen = strlen(s as *const c_char);
14762 if slen < tailcnt { return FNM_NOMATCH; }
14763
14764 let stail = s.add(slen - tailcnt);
14766 let mut tp = ptail;
14767 let mut ts = stail;
14768 loop {
14769 let (tok, step) = pat_next(tp, usize::MAX, flags);
14770 tp = tp.add(step);
14771 if tok == FNM_END {
14772 break;
14773 }
14774 let k = *ts;
14775 if k == 0 { return FNM_NOMATCH; }
14776 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14777 match tok {
14778 FNM_QUESTION => { ts = ts.add(1); }
14779 FNM_BRACKET => {
14780 if !match_bracket(tp.sub(step), k, kfold) { return FNM_NOMATCH; }
14781 ts = ts.add(1);
14782 }
14783 c => {
14784 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14785 ts = ts.add(1);
14786 }
14787 }
14788 }
14789
14790 let endstr = stail;
14791 let endpat = ptail;
14792
14793 let mut cp = p;
14794 let mut cs = s;
14795 while cp < endpat {
14796 let (tok, step) = pat_next(cp, usize::MAX, flags);
14797 if tok == FNM_STAR {
14798 cp = cp.add(step);
14799 cs = s;
14800 continue;
14801 }
14802 let comp_start = cp;
14803 let mut ok = false;
14804 let mut try_s = cs;
14805 while try_s < endstr {
14806 let mut tmp_p = comp_start;
14807 let mut tmp_s = try_s;
14808 let mut matched = true;
14809 loop {
14810 let (t, st) = pat_next(tmp_p, usize::MAX, flags);
14811 if t == FNM_STAR || t == FNM_END {
14812 cp = tmp_p;
14813 cs = tmp_s;
14814 ok = true;
14815 break;
14816 }
14817 if *tmp_s == 0 {
14818 matched = false;
14819 break;
14820 }
14821 let k = *tmp_s;
14822 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14823 match t {
14824 FNM_QUESTION => {
14825 tmp_s = tmp_s.add(1);
14826 }
14827 FNM_BRACKET => {
14828 if !match_bracket(tmp_p, k, kfold) {
14829 matched = false;
14830 break;
14831 }
14832 tmp_s = tmp_s.add(1);
14833 }
14834 c => {
14835 if k as c_int != c && kfold as c_int != c {
14836 matched = false;
14837 break;
14838 }
14839 tmp_s = tmp_s.add(1);
14840 }
14841 }
14842 tmp_p = tmp_p.add(st);
14843 }
14844 if ok { break; }
14845 if !matched {
14846 try_s = try_s.add(1);
14847 }
14848 }
14849 if !ok {
14850 return FNM_NOMATCH;
14851 }
14852 }
14853 0
14854}
14855
14856#[no_mangle]
14857pub unsafe extern "C" fn fnmatch(pat: *const c_char, str: *const c_char, flags: c_int) -> c_int {
14858 let pat = pat as *const u8;
14859 let str = str as *const u8;
14860
14861 if flags & FNM_PATHNAME != 0 {
14862 let mut s = str;
14864 let mut p = pat;
14865 loop {
14866 let mut send = s;
14868 while *send != 0 && *send != b'/' { send = send.add(1); }
14869 let mut pend = p;
14871 loop {
14872 let (tok, step) = pat_next(pend, usize::MAX, flags);
14873 if tok == FNM_END || (tok >= 0 && tok as u8 == b'/') {
14874 break;
14875 }
14876 pend = pend.add(step);
14877 }
14878 let (ptok, pstep) = pat_next(pend, usize::MAX, flags);
14879 let pat_is_slash = ptok >= 0 && ptok as u8 == b'/';
14880 let str_is_slash = *send == b'/';
14881 if pat_is_slash != str_is_slash && (*send != 0 || !(flags & FNM_LEADING_DIR != 0)) {
14882 return FNM_NOMATCH;
14883 }
14884 let plen = (pend as usize) - (p as usize);
14887 let slen = (send as usize) - (s as usize);
14888 if plen > 1024 || slen > 1024 { return FNM_NOMATCH; }
14891 let mut pbuf = [0u8; 1025];
14892 let mut sbuf = [0u8; 1025];
14893 core::ptr::copy_nonoverlapping(p, pbuf.as_mut_ptr(), plen);
14894 pbuf[plen] = 0;
14895 core::ptr::copy_nonoverlapping(s, sbuf.as_mut_ptr(), slen);
14896 sbuf[slen] = 0;
14897 if fnmatch_internal(pbuf.as_ptr(), sbuf.as_ptr(), flags & !FNM_LEADING_DIR) != 0 {
14898 return FNM_NOMATCH;
14899 }
14900 if !pat_is_slash {
14901 return 0;
14902 }
14903 s = send.add(1);
14904 p = pend.add(pstep);
14905 }
14906 }
14907
14908 if flags & FNM_LEADING_DIR != 0 {
14909 let mut s = str;
14911 while *s != 0 {
14912 if *s == b'/' {
14913 let len = (s as usize) - (str as usize);
14916 if len < 4096 {
14918 let mut buf = [0u8; 4096];
14919 core::ptr::copy_nonoverlapping(str, buf.as_mut_ptr(), len);
14920 buf[len] = 0;
14921 if fnmatch_internal(pat, buf.as_ptr(), flags) == 0 {
14922 return 0;
14923 }
14924 }
14925 }
14926 s = s.add(1);
14927 }
14928 }
14929
14930 fnmatch_internal(pat, str, flags)
14931}
14932
14933#[no_mangle]
14938pub unsafe extern "C" fn setmntent(name: *const c_char, mode: *const c_char) -> *mut FILE {
14939 fopen(name, mode)
14940}
14941
14942#[no_mangle]
14943pub unsafe extern "C" fn endmntent(f: *mut FILE) -> c_int {
14944 if !f.is_null() {
14945 fclose(f);
14946 }
14947 1
14948}
14949
14950static mut MNTENT_MNT: MntEnt = MntEnt {
14952 mnt_fsname: core::ptr::null_mut(),
14953 mnt_dir: core::ptr::null_mut(),
14954 mnt_type: core::ptr::null_mut(),
14955 mnt_opts: core::ptr::null_mut(),
14956 mnt_freq: 0,
14957 mnt_passno: 0,
14958};
14959
14960#[repr(C)]
14961pub struct MntEnt {
14962 mnt_fsname: *mut c_char,
14963 mnt_dir: *mut c_char,
14964 mnt_type: *mut c_char,
14965 mnt_opts: *mut c_char,
14966 mnt_freq: c_int,
14967 mnt_passno: c_int,
14968}
14969
14970unsafe fn unescape_ent(beg: *mut c_char) -> *mut c_char {
14971 let mut dest = beg;
14972 let mut src = beg;
14973 while *src != 0 {
14974 if *src != b'\\' as c_char {
14975 *dest = *src;
14976 dest = dest.add(1);
14977 src = src.add(1);
14978 continue;
14979 }
14980 if *src.add(1) == b'\\' as c_char {
14982 src = src.add(1);
14983 *dest = *src;
14984 dest = dest.add(1);
14985 src = src.add(1);
14986 continue;
14987 }
14988 let mut val: u8 = 0;
14990 let mut cnt = 0;
14991 let mut sp = src.add(1);
14992 while cnt < 3 && *sp >= b'0' as c_char && *sp <= b'7' as c_char {
14993 val = val * 8 + (*sp as u8 - b'0');
14994 sp = sp.add(1);
14995 cnt += 1;
14996 }
14997 if cnt > 0 {
14998 *dest = val as c_char;
14999 dest = dest.add(1);
15000 src = sp;
15001 } else {
15002 *dest = *src;
15003 dest = dest.add(1);
15004 src = src.add(1);
15005 }
15006 }
15007 *dest = 0;
15008 beg
15009}
15010
15011unsafe fn parse_mntent_line(
15012 linebuf: *mut c_char,
15013 mnt: *mut MntEnt,
15014) -> *mut MntEnt {
15015 let _len = strlen(linebuf as *const c_char);
15016 let mut p = linebuf;
15019 while *p == b' ' as c_char || *p == b'\t' as c_char || *p == b'\n' as c_char || *p == b'\r' as c_char {
15021 p = p.add(1);
15022 }
15023 if *p == 0 || *p == b'#' as c_char {
15024 return core::ptr::null_mut();
15025 }
15026
15027 (*mnt).mnt_fsname = p;
15029 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
15030 p = p.add(1);
15031 }
15032 if *p == 0 { return core::ptr::null_mut(); }
15033 *p = 0;
15034 p = p.add(1);
15035 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
15036
15037 (*mnt).mnt_dir = p;
15039 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
15040 p = p.add(1);
15041 }
15042 if *p == 0 { return core::ptr::null_mut(); }
15043 *p = 0;
15044 p = p.add(1);
15045 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
15046
15047 (*mnt).mnt_type = p;
15049 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
15050 p = p.add(1);
15051 }
15052 if *p == 0 { return core::ptr::null_mut(); }
15053 *p = 0;
15054 p = p.add(1);
15055 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
15056
15057 (*mnt).mnt_opts = p;
15059 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
15060 p = p.add(1);
15061 }
15062 if *p != 0 {
15063 *p = 0;
15064 p = p.add(1);
15065 }
15066 if *(*mnt).mnt_opts == 0 {
15067 (*mnt).mnt_opts = b"defaults\0".as_ptr() as *mut c_char;
15068 }
15069
15070 (*mnt).mnt_freq = 0;
15072 (*mnt).mnt_passno = 0;
15073 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
15075 if *p >= b'0' as c_char && *p <= b'9' as c_char {
15076 (*mnt).mnt_freq = (*p - b'0' as c_char) as c_int;
15077 p = p.add(1);
15078 while *p >= b'0' as c_char && *p <= b'9' as c_char {
15079 (*mnt).mnt_freq = (*mnt).mnt_freq * 10 + (*p - b'0' as c_char) as c_int;
15080 p = p.add(1);
15081 }
15082 }
15083 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
15084 if *p >= b'0' as c_char && *p <= b'9' as c_char {
15085 (*mnt).mnt_passno = (*p - b'0' as c_char) as c_int;
15086 p = p.add(1);
15087 while *p >= b'0' as c_char && *p <= b'9' as c_char {
15088 (*mnt).mnt_passno = (*mnt).mnt_passno * 10 + (*p - b'0' as c_char) as c_int;
15089 p = p.add(1);
15090 }
15091 }
15092
15093 unescape_ent((*mnt).mnt_fsname);
15095 unescape_ent((*mnt).mnt_dir);
15096 unescape_ent((*mnt).mnt_type);
15097 unescape_ent((*mnt).mnt_opts);
15098
15099 mnt
15100}
15101
15102static SENTINEL_PTR: usize = 1;
15105
15106unsafe fn mntent_fgetc(f: *mut FILE) -> c_int {
15108 fgetc(f)
15109}
15110
15111unsafe fn mntent_fgets(buf: *mut c_char, n: usize, f: *mut FILE) -> *mut c_char {
15112 if n == 0 { return core::ptr::null_mut(); }
15113 let max = n - 1;
15114 let mut i = 0usize;
15115 while i < max {
15116 let c = mntent_fgetc(f);
15117 if c == -1 { if i == 0 { return core::ptr::null_mut(); } break; }
15118 *buf.add(i) = c as c_char;
15119 i += 1;
15120 if c == b'\n' as c_int { break; }
15121 }
15122 *buf.add(i) = 0;
15123 buf
15124}
15125
15126#[no_mangle]
15127pub unsafe extern "C" fn getmntent_r(
15128 f: *mut FILE,
15129 mnt: *mut MntEnt,
15130 mut linebuf: *mut c_char,
15131 _buflen: c_int,
15132) -> *mut MntEnt {
15133 let use_internal = linebuf as usize == SENTINEL_PTR;
15134
15135 (*mnt).mnt_freq = 0;
15136 (*mnt).mnt_passno = 0;
15137
15138 static mut INTERNAL_BUF: [c_char; 4096] = [0; 4096];
15140
15141 loop {
15142 if use_internal {
15143 linebuf = core::ptr::addr_of_mut!(INTERNAL_BUF).cast::<c_char>();
15144 }
15145 let res = mntent_fgets(linebuf, 4096, f);
15146 if res.is_null() {
15147 return core::ptr::null_mut();
15148 }
15149 let mut has_newline = false;
15150 let mut p = linebuf;
15151 while *p != 0 { if *p == b'\n' as c_char { has_newline = true; break; } p = p.add(1); }
15152 if !has_newline {
15153 ERRNO!() = 34;
15154 return core::ptr::null_mut();
15155 }
15156 let result = parse_mntent_line(linebuf, mnt);
15157 if !result.is_null() {
15158 return result;
15159 }
15160 }
15161}
15162
15163#[no_mangle]
15164pub unsafe extern "C" fn getmntent(f: *mut FILE) -> *mut MntEnt {
15165 getmntent_r(f, core::ptr::addr_of_mut!(MNTENT_MNT), SENTINEL_PTR as *mut c_char, 0)
15166}
15167
15168#[no_mangle]
15169pub unsafe extern "C" fn addmntent(f: *mut FILE, mnt: *const MntEnt) -> c_int {
15170 fseek(f, 0, 2); let written = fprintf(
15172 f,
15173 b"%s\t%s\t%s\t%s\t%d\t%d\n\0".as_ptr() as *const c_char,
15174 (*mnt).mnt_fsname,
15175 (*mnt).mnt_dir,
15176 (*mnt).mnt_type,
15177 (*mnt).mnt_opts,
15178 (*mnt).mnt_freq,
15179 (*mnt).mnt_passno,
15180 );
15181 if written < 0 { 1 } else { 0 }
15182}
15183
15184#[no_mangle]
15185pub unsafe extern "C" fn hasmntopt(mnt: *const MntEnt, opt: *const c_char) -> *mut c_char {
15186 let l = strlen(opt as *const c_char);
15187 let mut p = (*mnt).mnt_opts;
15188 loop {
15189 if strncmp(p as *const u8, opt as *const u8, l) == 0 {
15190 let after = *p.add(l);
15191 if after == 0 || after == b',' as c_char || after == b'=' as c_char {
15192 return p;
15193 }
15194 }
15195 let comma = strchr(p as *const u8, b',' as c_int);
15196 if comma.is_null() {
15197 return core::ptr::null_mut();
15198 }
15199 p = comma.add(1) as *mut c_char;
15200 }
15201}
15202
15203const EEXIST: c_int = 17;
15211const ENAMETOOLONG: c_int = 36;
15212const EMFILE: c_int = 24;
15213const EIDRM: c_int = 43;
15214
15215#[inline]
15216unsafe fn sys_msgget(key: c_int, msgflg: c_int) -> i64 {
15217 <Arch as Syscalls>::syscall2(SYS_MSGGET, key as i64, msgflg as i64)
15218}
15219
15220#[inline]
15221unsafe fn sys_msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> i64 {
15222 <Arch as Syscalls>::syscall4(SYS_MSGSND, msqid as i64, msgp as i64, msgsz as i64, msgflg as i64)
15223}
15224
15225#[inline]
15226unsafe fn sys_msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> i64 {
15227 <Arch as Syscalls>::syscall5(SYS_MSGRCV, msqid as i64, msgp as i64, msgsz as i64, msgtyp as i64, msgflg as i64)
15228}
15229
15230#[inline]
15231unsafe fn sys_msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
15232 <Arch as Syscalls>::syscall3(SYS_MSGCTL, msqid as i64, cmd as i64, buf as i64)
15233}
15234
15235#[inline]
15236unsafe fn sys_semget(key: c_int, nsems: c_int, semflg: c_int) -> i64 {
15237 <Arch as Syscalls>::syscall3(SYS_SEMGET, key as i64, nsems as i64, semflg as i64)
15238}
15239
15240#[inline]
15241unsafe fn sys_semop(semid: c_int, sops: *const c_void, nsops: usize) -> i64 {
15242 <Arch as Syscalls>::syscall3(SYS_SEMOP, semid as i64, sops as i64, nsops as i64)
15243}
15244
15245#[inline]
15246unsafe fn sys_semctl(semid: c_int, semnum: c_int, cmd: c_int, arg: *mut c_void) -> i64 {
15247 <Arch as Syscalls>::syscall4(SYS_SEMCTL, semid as i64, semnum as i64, cmd as i64, arg as i64)
15248}
15249
15250#[inline]
15251unsafe fn sys_shmget(key: c_int, size: usize, shmflg: c_int) -> i64 {
15252 <Arch as Syscalls>::syscall3(SYS_SHMGET, key as i64, size as i64, shmflg as i64)
15253}
15254
15255#[inline]
15256unsafe fn sys_shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> i64 {
15257 <Arch as Syscalls>::syscall3(SYS_SHMAT, shmid as i64, shmaddr as i64, shmflg as i64)
15258}
15259
15260#[inline]
15261unsafe fn sys_shmdt(shmaddr: *const c_void) -> i64 {
15262 <Arch as Syscalls>::syscall1(SYS_SHMDT, shmaddr as i64)
15263}
15264
15265#[inline]
15266unsafe fn sys_shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
15267 <Arch as Syscalls>::syscall3(SYS_SHMCTL, shmid as i64, cmd as i64, buf as i64)
15268}
15269
15270#[no_mangle]
15272pub unsafe extern "C" fn ftok(path: *const c_char, id: c_int) -> c_int {
15273 let mut st: kernel_stat64 = core::mem::zeroed();
15274 let r = sys_stat(path as *const u8, &mut st);
15275 if r < 0 {
15276 ERRNO!() = (-r) as c_int;
15277 return -1;
15278 }
15279 ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) | (((id as u32 & 0xff) << 24)) as u64) as c_int
15280}
15281
15282#[no_mangle]
15284pub unsafe extern "C" fn msgget(key: c_int, msgflg: c_int) -> c_int {
15285 let r = sys_msgget(key, msgflg);
15286 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15287}
15288
15289#[no_mangle]
15291pub unsafe extern "C" fn msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> c_int {
15292 let r = sys_msgsnd(msqid, msgp, msgsz, msgflg);
15293 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15294}
15295
15296#[no_mangle]
15298pub unsafe extern "C" fn msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> isize {
15299 let r = sys_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
15300 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
15301}
15302
15303#[no_mangle]
15305pub unsafe extern "C" fn msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
15306 let r = sys_msgctl(msqid, cmd, buf);
15307 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15308}
15309
15310#[no_mangle]
15312pub unsafe extern "C" fn semget(key: c_int, nsems: c_int, semflg: c_int) -> c_int {
15313 if nsems > 65535 { ERRNO!() = 22; return -1; }
15314 let r = sys_semget(key, nsems, semflg);
15315 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15316}
15317
15318#[no_mangle]
15320pub unsafe extern "C" fn semop(semid: c_int, sops: *const c_void, nsops: usize) -> c_int {
15321 let r = sys_semop(semid, sops, nsops);
15322 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15323}
15324
15325#[no_mangle]
15327pub unsafe extern "C" fn semctl(semid: c_int, semnum: c_int, cmd: c_int, mut args: ...) -> c_int {
15328 let mut arg: *mut c_void = core::ptr::null_mut();
15329 match cmd {
15331 16 | 13 | 17 | 1 | 2 | 3 | 18 | 19 | 20 | 0x102 | 0x104 | 0x106 => {
15335 arg = args.next_arg::<*mut c_void>();
15336 }
15337 _ => {}
15338 }
15339 let r = sys_semctl(semid, semnum, cmd, arg);
15340 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15341}
15342
15343#[no_mangle]
15345pub unsafe extern "C" fn shmget(key: c_int, size: usize, shmflg: c_int) -> c_int {
15346 let r = sys_shmget(key, size, shmflg);
15347 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15348}
15349
15350#[no_mangle]
15352pub unsafe extern "C" fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void {
15353 let r = sys_shmat(shmid, shmaddr, shmflg);
15354 if (r as usize) > (-(4096isize as isize)) as usize {
15355 ERRNO!() = (-r) as c_int;
15356 return -1isize as *mut c_void;
15357 }
15358 r as *mut c_void
15359}
15360
15361#[no_mangle]
15363pub unsafe extern "C" fn shmdt(shmaddr: *const c_void) -> c_int {
15364 let r = sys_shmdt(shmaddr);
15365 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15366}
15367
15368#[no_mangle]
15370pub unsafe extern "C" fn shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
15371 let r = sys_shmctl(shmid, cmd, buf);
15372 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15373}
15374
15375#[no_mangle]
15385pub static mut __auxv: *const usize = core::ptr::null();
15386#[no_mangle]
15387pub static mut __rc_static_base: usize = 0;
15388static mut RC_STATIC_EXEC: bool = false;
15389
15390#[no_mangle]
15391pub static mut __progname: *mut c_char = core::ptr::null_mut();
15392#[no_mangle]
15393pub static mut __progname_full: *mut c_char = core::ptr::null_mut();
15394#[no_mangle]
15395pub static mut program_invocation_name: *mut c_char = core::ptr::null_mut();
15396#[no_mangle]
15397pub static mut program_invocation_short_name: *mut c_char = core::ptr::null_mut();
15398
15399#[no_mangle]
15400pub static in6addr_any: [u32; 4] = [0; 4];
15401#[no_mangle]
15402pub static in6addr_loopback: [u32; 4] = [0, 0, 0, 0x0100_0000];
15403
15404#[no_mangle]
15405pub static mut __daylight: c_int = 0;
15406#[no_mangle]
15407pub static mut __timezone: c_long = 0;
15408#[no_mangle]
15409pub static mut __tzname: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
15410
15411#[no_mangle]
15412pub unsafe extern "C" fn getauxval(type_: c_ulong) -> c_ulong {
15413 let mut p = __auxv;
15414 if p.is_null() {
15415 return 0;
15416 }
15417 loop {
15418 let tag = *p;
15419 if tag == 0 {
15420 return 0;
15421 }
15422 if tag == type_ as usize {
15423 return *p.add(1) as c_ulong;
15424 }
15425 p = p.add(2);
15426 }
15427}
15428
15429
15430unsafe fn run_static_init() {
15431 if !RC_STATIC_EXEC {
15432 return;
15433 }
15434 extern "C" {
15435 static __preinit_array_start: usize;
15436 static __preinit_array_end: usize;
15437 static __init_array_start: usize;
15438 static __init_array_end: usize;
15439 }
15440 let mut p = core::ptr::addr_of!(__preinit_array_start) as usize;
15441 let end = core::ptr::addr_of!(__preinit_array_end) as usize;
15442 while p < end {
15443 let f = core::ptr::read_unaligned(p as *const usize);
15444 if f != 0 {
15445 let f: unsafe extern "C" fn() = core::mem::transmute(f);
15446 f();
15447 }
15448 p += core::mem::size_of::<usize>();
15449 }
15450 p = core::ptr::addr_of!(__init_array_start) as usize;
15451 let end = core::ptr::addr_of!(__init_array_end) as usize;
15452 while p < end {
15453 let f = core::ptr::read_unaligned(p as *const usize);
15454 if f != 0 {
15455 let f: unsafe extern "C" fn() = core::mem::transmute(f);
15456 f();
15457 }
15458 p += core::mem::size_of::<usize>();
15459 }
15460}
15461
15462type MainFn = unsafe extern "C" fn(c_int, *const *const c_char, *const *const c_char) -> c_int;
15463type InitFn = unsafe extern "C" fn();
15464
15465#[cfg(target_arch = "x86_64")]
15466unsafe fn static_tls_tp() -> usize {
15467 let mut fs: u64 = 0;
15468 if arch_prctl(0x1003, &mut fs as *mut u64 as u64) != 0 {
15469 0
15470 } else {
15471 fs as usize
15472 }
15473}
15474
15475#[cfg(target_arch = "x86_64")]
15476unsafe fn set_static_tls_tp(tp: usize) {
15477 let _ = arch_prctl(0x1002, tp as u64);
15478}
15479
15480#[cfg(target_arch = "aarch64")]
15481unsafe fn static_tls_tp() -> usize {
15482 let tp: usize;
15483 core::arch::asm!("mrs {}, tpidr_el0", out(reg) tp, options(nostack));
15484 tp
15485}
15486
15487#[cfg(target_arch = "aarch64")]
15488unsafe fn set_static_tls_tp(tp: usize) {
15489 core::arch::asm!("msr tpidr_el0, {}", in(reg) tp, options(nostack));
15490}
15491
15492#[cfg(target_arch = "riscv64")]
15493unsafe fn static_tls_tp() -> usize {
15494 let tp: usize;
15495 core::arch::asm!("mv {}, tp", out(reg) tp, options(nostack));
15496 tp
15497}
15498
15499#[cfg(target_arch = "riscv64")]
15500unsafe fn set_static_tls_tp(tp: usize) {
15501 core::arch::asm!("mv tp, {}", in(reg) tp, options(nostack));
15502}
15503
15504static mut STATIC_TLS_BLOCK_SIZE: usize = 0;
15505static mut STATIC_TLS_TP_OFFSET: usize = 0;
15506static mut STATIC_TLS_VAR_OFFSET: usize = 0;
15507static mut STATIC_TLS_TLS_SIZE: usize = 0;
15508static mut STATIC_TLS_IMAGE: *const u8 = core::ptr::null();
15509static mut STATIC_TLS_FILESZ: usize = 0;
15510static mut STATIC_TLS_CANARY: u64 = 0;
15511
15512unsafe fn static_tls_init_block(block: *mut u8) -> *mut u8 {
15513 if block.is_null() || STATIC_TLS_BLOCK_SIZE == 0 {
15514 return core::ptr::null_mut();
15515 }
15516 let var_base = block.add(STATIC_TLS_VAR_OFFSET);
15517 if STATIC_TLS_TLS_SIZE > 0 {
15518 core::ptr::write_bytes(var_base, 0, STATIC_TLS_TLS_SIZE);
15519 }
15520 if STATIC_TLS_FILESZ > 0 && !STATIC_TLS_IMAGE.is_null() {
15521 core::ptr::copy_nonoverlapping(STATIC_TLS_IMAGE, var_base, STATIC_TLS_FILESZ);
15522 }
15523 let tp = block.add(STATIC_TLS_TP_OFFSET);
15524 let tcb = if cfg!(target_arch = "x86_64") {
15525 tp as usize
15526 } else {
15527 block as usize
15528 };
15529 core::ptr::write_unaligned(tcb as *mut u64, tcb as u64);
15530 core::ptr::write_unaligned((tcb as *mut u64).add(1), 1);
15531 core::ptr::write_unaligned((tcb as *mut u64).add(2), STATIC_TLS_TLS_SIZE as u64);
15532 core::ptr::write_unaligned((tcb as *mut u64).add(3), 1);
15533 core::ptr::write_unaligned((tcb as *mut u64).add(4), 0); core::ptr::write_unaligned((tcb as *mut u64).add(5), STATIC_TLS_CANARY); core::ptr::write_unaligned((tcb as *mut u64).add(6), 0); tp
15537}
15538
15539unsafe fn static_tls_create_block() -> *mut u8 {
15540 if STATIC_TLS_BLOCK_SIZE == 0 {
15541 return core::ptr::null_mut();
15542 }
15543 let block = sys_mmap(
15544 core::ptr::null_mut(),
15545 STATIC_TLS_BLOCK_SIZE,
15546 PROT_READ | PROT_WRITE,
15547 MAP_PRIVATE | MAP_ANONYMOUS,
15548 -1,
15549 0,
15550 );
15551 if block.is_null() || block == MMAP_FAILED {
15552 return core::ptr::null_mut();
15553 }
15554 static_tls_init_block(block)
15555}
15556
15557#[repr(C)]
15558pub struct TlsIndex {
15559 pub ti_module: usize,
15560 pub ti_offset: usize,
15561}
15562
15563static mut TLS_GET_ADDR_IMPL: usize = 0;
15568
15569#[no_mangle]
15574pub unsafe extern "C" fn __rc_set_tls_get_addr(f: usize) {
15575 TLS_GET_ADDR_IMPL = f;
15576}
15577
15578#[no_mangle]
15579pub unsafe extern "C" fn __tls_get_addr(ti: *const TlsIndex) -> *mut u8 {
15580 if TLS_GET_ADDR_IMPL != 0 {
15581 let f: unsafe extern "C" fn(*const TlsIndex) -> *mut u8 =
15582 core::mem::transmute(TLS_GET_ADDR_IMPL);
15583 return f(ti);
15584 }
15585 if ti.is_null() || (*ti).ti_module != 0 || !RC_STATIC_EXEC {
15586 return core::ptr::null_mut();
15587 }
15588 let tp = static_tls_tp();
15589 if tp == 0 {
15590 return core::ptr::null_mut();
15591 }
15592 (tp - STATIC_TLS_TP_OFFSET + STATIC_TLS_VAR_OFFSET + (*ti).ti_offset) as *mut u8
15593}
15594
15595unsafe fn init_static_tls() {
15598 if static_tls_tp() != 0 {
15599 return;
15600 }
15601 let phdr = getauxval(3) as usize; let phnum = getauxval(5) as usize; let phent = getauxval(4) as usize; if phdr == 0 || phnum == 0 || phent < 56 {
15605 return;
15606 }
15607
15608 let mut tls_vaddr = 0usize;
15609 let mut tls_filesz = 0usize;
15610 let mut tls_memsz = 0usize;
15611 let mut tls_align = 1usize;
15612 let mut exec_base = __rc_static_base;
15613 let mut i = 0usize;
15614 while i < phnum {
15615 let ph = phdr + i * phent;
15616 let p_type = core::ptr::read_unaligned(ph as *const u32);
15617 if p_type == 3 {
15618 return;
15620 }
15621 if p_type == 6 {
15622 if exec_base == 0 {
15624 let p_vaddr = core::ptr::read_unaligned((ph + 16) as *const u64) as usize;
15625 exec_base = phdr.wrapping_sub(p_vaddr);
15626 }
15627 } else if p_type == 7 {
15628 tls_vaddr = core::ptr::read_unaligned((ph + 16) as *const u64) as usize;
15630 tls_filesz = core::ptr::read_unaligned((ph + 32) as *const u64) as usize;
15631 tls_memsz = core::ptr::read_unaligned((ph + 40) as *const u64) as usize;
15632 let align = core::ptr::read_unaligned((ph + 48) as *const u64) as usize;
15633 if align > 1 {
15634 tls_align = align;
15635 }
15636 }
15637 i += 1;
15638 }
15639
15640 let tcb_size = 256usize;
15641 #[cfg(target_arch = "x86_64")]
15642 let gap = 0usize;
15643 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
15644 let gap = if cfg!(target_arch = "aarch64") { 16usize } else { 0usize };
15645
15646 let tls_size = if tls_align > 1 {
15647 (tls_memsz + tls_align - 1) & !(tls_align - 1)
15648 } else {
15649 tls_memsz
15650 };
15651 let total = tcb_size + gap + tls_size + tls_align;
15652 STATIC_TLS_BLOCK_SIZE = total;
15653 STATIC_TLS_TP_OFFSET = if cfg!(target_arch = "x86_64") {
15654 tls_size
15655 } else {
15656 tcb_size
15657 };
15658 STATIC_TLS_VAR_OFFSET = if cfg!(target_arch = "x86_64") {
15659 0
15660 } else {
15661 tcb_size + gap
15662 };
15663 STATIC_TLS_TLS_SIZE = tls_size;
15664 STATIC_TLS_IMAGE = (exec_base + tls_vaddr) as *const u8;
15665 STATIC_TLS_FILESZ = tls_filesz;
15666 let random = getauxval(25) as *const u8; STATIC_TLS_CANARY = if random.is_null() {
15668 0xdefaced_cafebeefu64
15669 } else {
15670 core::ptr::read_unaligned(random as *const u64)
15671 ^ core::ptr::read_unaligned(random.add(8) as *const u64)
15672 };
15673
15674 let block = sys_mmap(
15675 core::ptr::null_mut(),
15676 total,
15677 PROT_READ | PROT_WRITE,
15678 MAP_PRIVATE | MAP_ANONYMOUS,
15679 -1,
15680 0,
15681 );
15682 if block.is_null() || block == MMAP_FAILED {
15683 return;
15684 }
15685 let tp = static_tls_init_block(block);
15686 if tp.is_null() {
15687 return;
15688 }
15689 set_static_tls_tp(tp as usize);
15690 RC_STATIC_EXEC = true;
15691}
15692
15693
15694#[no_mangle]
15695pub unsafe extern "C" fn __libc_start_main(
15696 main: MainFn,
15697 argc: c_int,
15698 argv: *const *const c_char,
15699 _init: *const c_void,
15700 _fini: *const c_void,
15701 _rtld_fini: *const c_void,
15702 _stack_end: *const c_void,
15703) -> ! {
15704 let envp = argv.add((argc + 1) as usize);
15705 let mut aux = envp;
15706 while !(*aux).is_null() {
15707 aux = aux.add(1);
15708 }
15709 __auxv = aux.add(1) as *const usize;
15710 init_static_tls();
15711 errno_init();
15712
15713 __environ = envp as *mut *mut c_char;
15714 environ = __environ; ___environ = __environ;
15716 _environ = __environ;
15717
15718 if !argv.is_null() && argc > 0 {
15720 let argv0 = *argv;
15721 __progname_full = argv0 as *mut c_char;
15722 program_invocation_name = argv0 as *mut c_char;
15723 let mut base = argv0;
15724 let mut p = argv0;
15725 while *p != 0 {
15726 if *p == b'/' as c_char { base = p.add(1); }
15727 p = p.add(1);
15728 }
15729 __progname = base as *mut c_char;
15730 program_invocation_short_name = base as *mut c_char;
15731 }
15732
15733 __stdio_init();
15734 run_static_init();
15735
15736 let mut set: SigSetT = 0;
15737 sigemptyset(&mut set);
15738 sigaddset(&mut set, SIGCANCEL);
15739 sigprocmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
15740
15741 if !_init.is_null() {
15742 let init_fn: InitFn = core::mem::transmute(_init);
15743 init_fn();
15744 }
15745
15746 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
15750 {
15751 let random_ptr = getauxval(25) as *const u8; if !random_ptr.is_null() {
15753 let a = core::ptr::read_unaligned(random_ptr as *const u64);
15754 let b = core::ptr::read_unaligned(random_ptr.add(8) as *const u64);
15755 __stack_chk_guard = (a ^ b) as usize;
15756 } else {
15757 __stack_chk_guard = 0xdefaced_cafebeef;
15759 }
15760 }
15761
15762 let result = main(argc, argv, envp);
15763
15764 if !_fini.is_null() {
15765 let fini_fn: InitFn = core::mem::transmute(_fini);
15766 fini_fn();
15767 }
15768
15769 exit(result);
15770}
15771
15772type LdsoDlopenFn = unsafe extern "C" fn(*const c_char, c_int) -> *mut c_void;
15773type LdsoDlsymFn = unsafe extern "C" fn(*mut c_void, *const c_char, *mut c_void) -> *mut c_void;
15774type LdsoDlcloseFn = unsafe extern "C" fn(*mut c_void) -> c_int;
15775type LdsoDlerrorFn = unsafe extern "C" fn() -> *const c_char;
15776
15777static mut LDSO_DLOPEN: Option<LdsoDlopenFn> = None;
15778static mut LDSO_DLSYM: Option<LdsoDlsymFn> = None;
15779static mut LDSO_DLCLOSE: Option<LdsoDlcloseFn> = None;
15780static mut LDSO_DLERROR: Option<LdsoDlerrorFn> = None;
15781
15782#[no_mangle]
15783pub unsafe extern "C" fn __ldso_register_dlopen(f: LdsoDlopenFn) {
15784 LDSO_DLOPEN = Some(f);
15785}
15786
15787#[no_mangle]
15788pub unsafe extern "C" fn __ldso_register_dlsym(f: LdsoDlsymFn) {
15789 LDSO_DLSYM = Some(f);
15790}
15791
15792#[no_mangle]
15793pub unsafe extern "C" fn __ldso_register_dlclose(f: LdsoDlcloseFn) {
15794 LDSO_DLCLOSE = Some(f);
15795}
15796
15797#[no_mangle]
15798pub unsafe extern "C" fn __ldso_register_dlerror(f: LdsoDlerrorFn) {
15799 LDSO_DLERROR = Some(f);
15800}
15801
15802#[no_mangle]
15803pub unsafe extern "C" fn dlopen(filename: *const c_char, flags: c_int) -> *mut c_void {
15804 if let Some(f) = LDSO_DLOPEN {
15805 f(filename, flags)
15806 } else {
15807 null_mut()
15808 }
15809}
15810
15811#[no_mangle]
15812pub unsafe extern "C" fn dlsym_impl(
15813 handle: *mut c_void,
15814 symbol: *const c_char,
15815 ra: *mut c_void,
15816) -> *mut c_void {
15817 if let Some(f) = LDSO_DLSYM {
15818 f(handle, symbol, ra)
15819 } else {
15820 null_mut()
15821 }
15822}
15823
15824#[no_mangle]
15828#[unsafe(naked)]
15829#[cfg(target_arch = "x86_64")]
15830pub unsafe extern "C" fn dlsym(_handle: *mut c_void, _symbol: *const c_char) -> *mut c_void {
15831 core::arch::naked_asm!("mov rdx, [rsp]", "jmp dlsym_impl");
15832}
15833
15834#[no_mangle]
15835#[unsafe(naked)]
15836#[cfg(target_arch = "aarch64")]
15837pub unsafe extern "C" fn dlsym(_handle: *mut c_void, _symbol: *const c_char) -> *mut c_void {
15838 core::arch::naked_asm!("mov x2, x30", "b dlsym_impl");
15839}
15840
15841#[no_mangle]
15842#[unsafe(naked)]
15843#[cfg(target_arch = "riscv64")]
15844pub unsafe extern "C" fn dlsym(_handle: *mut c_void, _symbol: *const c_char) -> *mut c_void {
15845 core::arch::naked_asm!("mv a2, ra", "la t0, dlsym_impl", "jr t0");
15846}
15847
15848#[no_mangle]
15849pub unsafe extern "C" fn dlclose(handle: *mut c_void) -> c_int {
15850 if let Some(f) = LDSO_DLCLOSE {
15851 f(handle)
15852 } else {
15853 0
15854 }
15855}
15856
15857#[no_mangle]
15858pub unsafe extern "C" fn dlerror() -> *const c_char {
15859 if let Some(f) = LDSO_DLERROR {
15860 f()
15861 } else {
15862 core::ptr::null()
15863 }
15864}
15865
15866include!("crypt_impl.rs");
15867include!("statvfs.rs");
15868include!("daemon.rs");
15869include!("dn_expand.rs");
15870include!("lrand48.rs");
15871include!("strverscmp.rs");
15872include!("syscall.rs");
15873include!("pthread_atfork.rs");
15874include!("fenv.rs");
15875include!("locale_ctype.rs");
15876include!("regression_stubs.rs");
15877include!("netdb_extra.rs");
15878include!("compat_extra.rs");
15879include!("stdio_extra.rs");
15880include!("ns_parse.rs");
15881include!("fts.rs");
15882include!("ifaddrs.rs");
15883include!("dl_extra.rs");
15884include!("des.rs");
15885include!("path_extra.rs");
15886include!("wordexp.rs");
15887include!("getopt_impl.rs");
15888
15889type regoff_t = c_int;
15894
15895#[repr(C)]
15896pub struct regex_t {
15897 pub re_nsub: usize,
15898 pub __opaque: *mut c_void,
15899 pub __padding: [*mut c_void; 4],
15900 pub __nsub2: usize,
15901 pub __padding2: c_char,
15902}
15903
15904#[repr(C)]
15905pub struct regmatch_t {
15906 pub rm_so: regoff_t,
15907 pub rm_eo: regoff_t,
15908}
15909
15910include!("regex.rs");
15911
15912#[cfg(test)]
15913mod libc_unit_stub {
15914 #[test]
15915 fn stub() {
15916 assert!(true);
15917 }
15918}
15919
15920#[inline]
15925pub(crate) fn fmax_impl(x: f64, y: f64) -> f64 {
15926 if x.is_nan() { return y; }
15927 if y.is_nan() { return x; }
15928 if x == 0.0 && y == 0.0 {
15929 return if x.is_sign_negative() && y.is_sign_negative() { -0.0 } else { 0.0 };
15930 }
15931 if x > y { x } else { y }
15932}
15933
15934#[inline]
15935pub(crate) fn fmin_impl(x: f64, y: f64) -> f64 {
15936 if x.is_nan() { return y; }
15937 if y.is_nan() { return x; }
15938 if x == 0.0 && y == 0.0 {
15939 return if x.is_sign_negative() || y.is_sign_negative() { -0.0 } else { 0.0 };
15940 }
15941 if x < y { x } else { y }
15942}
15943
15944#[inline]
15945pub(crate) fn fmaxf_impl(x: f32, y: f32) -> f32 {
15946 if x.is_nan() { return y; }
15947 if y.is_nan() { return x; }
15948 if x == 0.0 && y == 0.0 {
15949 return if x.is_sign_negative() && y.is_sign_negative() { -0.0 } else { 0.0 };
15950 }
15951 if x > y { x } else { y }
15952}
15953
15954#[inline]
15955pub(crate) fn fminf_impl(x: f32, y: f32) -> f32 {
15956 if x.is_nan() { return y; }
15957 if y.is_nan() { return x; }
15958 if x == 0.0 && y == 0.0 {
15959 return if x.is_sign_negative() || y.is_sign_negative() { -0.0 } else { 0.0 };
15960 }
15961 if x < y { x } else { y }
15962}
15963
15964#[inline(never)]
15965#[no_mangle]
15966pub unsafe extern "C" fn fmax(x: f64, y: f64) -> f64 {
15967 fmax_impl(x, y)
15968}
15969
15970#[inline(never)]
15971#[no_mangle]
15972pub unsafe extern "C" fn fmin(x: f64, y: f64) -> f64 {
15973 fmin_impl(x, y)
15974}
15975
15976#[no_mangle]
15977pub unsafe extern "C" fn fminf(x: f32, y: f32) -> f32 {
15978 fminf_impl(x, y)
15979}
15980
15981#[no_mangle]
15982pub unsafe extern "C" fn fdim(x: f64, y: f64) -> f64 {
15983 if x.is_nan() || y.is_nan() {
15984 return f64::NAN;
15985 }
15986 if x > y { x - y } else { 0.0 }
15987}
15988
15989#[no_mangle]
15990pub unsafe extern "C" fn fma(x: f64, y: f64, z: f64) -> f64 {
15991 if (x.is_infinite() && y == 0.0) || (y.is_infinite() && x == 0.0) {
15992 feraiseexcept(FE_INVALID);
15993 return f64::NAN;
15994 }
15995 if x.is_nan() || y.is_nan() || z.is_nan() {
15996 return f64::NAN;
15997 }
15998 let r = libm::fma(x, y, z);
15999 if r.is_nan() {
16001 feraiseexcept(FE_INVALID);
16002 }
16003 r
16004}
16005
16006#[no_mangle]
16007pub unsafe extern "C" fn ilogb(x: f64) -> i32 {
16008 if x.is_nan() {
16009 feraiseexcept(FE_INVALID);
16010 return -0x7fffffff - 1; }
16012 if x == 0.0 || x.is_infinite() {
16013 feraiseexcept(FE_INVALID);
16014 return if x == 0.0 { -0x7fffffff - 1 } else { 0x7fffffff };
16015 }
16016 let bits = x.to_bits();
16017 let exp = ((bits >> 52) & 0x7ff) as i32;
16018 if exp == 0 {
16019 let mut v = bits & 0xfffffffffffff;
16021 let mut e = -1022;
16022 while v < (1u64 << 52) { v <<= 1; e -= 1; }
16023 e
16024 } else {
16025 exp - 1023
16026 }
16027}
16028
16029#[no_mangle]
16030pub unsafe extern "C" fn logb(x: f64) -> f64 {
16031 if x.is_nan() { return x; }
16032 if x == 0.0 { return __math_divzero(1); }
16033 let bits = x.to_bits();
16034 let exp = ((bits >> 52) & 0x7ff) as i32;
16035 if exp == 0 {
16036 let mut v = bits & 0xfffffffffffff;
16038 let mut e = -1022i32;
16039 while v < (1u64 << 52) { v <<= 1; e -= 1; }
16040 e as f64
16041 } else if exp == 0x7ff {
16042 x * x } else {
16044 (exp - 1023) as f64
16045 }
16046}
16047
16048#[no_mangle]
16049pub unsafe extern "C" fn nearbyint(x: f64) -> f64 {
16050 let had_inexact = fetestexcept(FE_INEXACT) & FE_INEXACT != 0;
16051 let r = libm::rint(x);
16052 if !had_inexact {
16053 feclearexcept(FE_INEXACT);
16054 }
16055 r
16056}
16057
16058#[no_mangle]
16059pub unsafe extern "C" fn nextafter(x: f64, y: f64) -> f64 {
16060 if x.is_nan() || y.is_nan() { return x + y; }
16061 if x == 0.0 && y == 0.0 { return y; }
16062 if x == y { return x; }
16063 let r = libm::nextafter(x, y);
16064 if r.is_infinite() && x.is_finite() {
16065 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16066 } else if r != x {
16067 let bits = r.to_bits();
16068 let is_subnormal = (bits & 0x7ff0000000000000) == 0 && (bits & 0xfffffffffffff) != 0;
16069 if r == 0.0 || is_subnormal {
16070 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16071 }
16072 }
16073 r
16074}
16075
16076#[no_mangle]
16077pub unsafe extern "C" fn nexttoward(x: f64, y: f64) -> f64 {
16078 if x == 0.0 && y == 0.0 {
16080 return if y.is_sign_negative() { -0.0 } else { 0.0 };
16081 }
16082 nextafter(x, y)
16083}
16084
16085#[no_mangle]
16086pub unsafe extern "C" fn remainder(x: f64, y: f64) -> f64 {
16087 if x.is_nan() || y.is_nan() { return x + y; }
16088 if y == 0.0 || x.is_infinite() { return __math_invalid(x); }
16089 libm::remainder(x, y)
16090}
16091
16092#[no_mangle]
16093pub unsafe extern "C" fn remquo(x: f64, y: f64, quo: *mut i32) -> f64 {
16094 if x.is_nan() || y.is_nan() {
16095 if !quo.is_null() { *quo = 0; }
16096 return x + y;
16097 }
16098 if y == 0.0 || x.is_infinite() {
16099 if !quo.is_null() { *quo = 0; }
16100 return __math_invalid(x);
16101 }
16102 let (r, q) = libm::remquo(x, y);
16103 if !quo.is_null() { *quo = q; }
16104 r
16105}
16106
16107#[no_mangle]
16108pub unsafe extern "C" fn exp2(x: f64) -> f64 {
16109 exp2_impl(x)
16110}
16111
16112#[no_mangle]
16113pub unsafe extern "C" fn expm1(x: f64) -> f64 {
16114 let r = libm::expm1(x);
16115 if r != 0.0 && x != 0.0 && libm::fabs(x) < 1e-307 {
16117 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16118 }
16119 r
16120}
16121
16122#[no_mangle]
16123pub unsafe extern "C" fn log1p(x: f64) -> f64 {
16124 if x == -1.0 {
16125 feraiseexcept(FE_DIVBYZERO);
16126 return f64::NEG_INFINITY;
16127 }
16128 libm::log1p(x)
16129}
16130
16131#[no_mangle]
16132pub unsafe extern "C" fn acosh(x: f64) -> f64 {
16133 if x < 1.0 {
16134 feraiseexcept(FE_INVALID);
16135 return f64::NAN;
16136 }
16137 libm::acosh(x)
16138}
16139
16140#[no_mangle]
16141pub unsafe extern "C" fn asinh(x: f64) -> f64 {
16142 if x == 0.0 { return x; }
16143 libm::asinh(x)
16144}
16145
16146#[no_mangle]
16147pub unsafe extern "C" fn atanh(x: f64) -> f64 {
16148 if x == 0.0 { return x; }
16149 let e = ((x.to_bits() >> 52) & 0x7ff) as i32;
16150 if e < 0x3ff - 32 {
16151 feraiseexcept(FE_INEXACT);
16152 if e == 0 { feraiseexcept(FE_UNDERFLOW); }
16153 return x;
16154 }
16155 if x == 1.0 {
16156 feraiseexcept(FE_DIVBYZERO);
16157 return f64::INFINITY;
16158 }
16159 if x == -1.0 {
16160 feraiseexcept(FE_DIVBYZERO);
16161 return f64::NEG_INFINITY;
16162 }
16163 if x.is_nan() { return x; }
16164 let ax = libm::fabs(x);
16165 if ax > 1.0 {
16166 feraiseexcept(FE_INVALID);
16167 return f64::NAN;
16168 }
16169 if ax < 0.5 {
16170 let r = libm::log1p(2.0 * (ax + ax * ax / (1.0 - ax))) / 2.0;
16172 if x < 0.0 { -r } else { r }
16173 } else {
16174 let r = 0.5 * libm::log((1.0 + ax) / (1.0 - ax));
16176 if x < 0.0 { -r } else { r }
16177 }
16178}
16179
16180#[no_mangle]
16181pub unsafe extern "C" fn cbrt(x: f64) -> f64 {
16182 libm::cbrt(x)
16183}
16184
16185#[no_mangle]
16186pub unsafe extern "C" fn erf(x: f64) -> f64 {
16187 erf_impl(x)
16188}
16189
16190#[no_mangle]
16191pub unsafe extern "C" fn erfc(x: f64) -> f64 {
16192 erfc_impl(x)
16193}
16194
16195#[no_mangle]
16196pub unsafe extern "C" fn lgamma(x: f64) -> f64 {
16197 lgamma_impl(x)
16198}
16199
16200#[no_mangle]
16201pub unsafe extern "C" fn tgamma(x: f64) -> f64 {
16202 tgamma_impl(x)
16203}
16204
16205#[no_mangle]
16206pub unsafe extern "C" fn lround(x: f64) -> core::ffi::c_long {
16207 libm::round(x) as core::ffi::c_long
16208}
16209
16210#[no_mangle]
16211pub unsafe extern "C" fn llround(x: f64) -> i64 {
16212 libm::round(x) as i64
16213}
16214
16215#[no_mangle]
16222pub unsafe extern "C" fn cabs(z: (f64, f64)) -> f64 {
16223 libm::sqrt(z.0 * z.0 + z.1 * z.1)
16224}
16225
16226#[no_mangle]
16227pub unsafe extern "C" fn cabsf(z: (f32, f32)) -> f32 {
16228 libm::sqrtf(z.0 * z.0 + z.1 * z.1)
16229}
16230
16231#[no_mangle]
16232pub unsafe extern "C" fn cabsl(z: (f64, f64)) -> f64 {
16233 cabs(z)
16234}
16235
16236#[no_mangle]
16237pub unsafe extern "C" fn carg(z: (f64, f64)) -> f64 {
16238 libm::atan2(z.1, z.0)
16239}
16240
16241#[no_mangle]
16242pub unsafe extern "C" fn cargf(z: (f32, f32)) -> f32 {
16243 libm::atan2f(z.1, z.0)
16244}
16245
16246#[no_mangle]
16247pub unsafe extern "C" fn cargl(z: (f64, f64)) -> f64 {
16248 carg(z)
16249}
16250
16251#[no_mangle]
16252pub unsafe extern "C" fn cimag(z: (f64, f64)) -> f64 {
16253 z.1
16254}
16255
16256#[no_mangle]
16257pub unsafe extern "C" fn cimagf(z: (f32, f32)) -> f32 {
16258 z.1
16259}
16260
16261#[no_mangle]
16262pub unsafe extern "C" fn cimagl(z: (f64, f64)) -> f64 {
16263 z.1
16264}
16265
16266#[no_mangle]
16267pub unsafe extern "C" fn creal(z: (f64, f64)) -> f64 {
16268 z.0
16269}
16270
16271#[no_mangle]
16272pub unsafe extern "C" fn crealf(z: (f32, f32)) -> f32 {
16273 z.0
16274}
16275
16276#[no_mangle]
16277pub unsafe extern "C" fn creall(z: (f64, f64)) -> f64 {
16278 z.0
16279}
16280
16281#[no_mangle]
16282pub unsafe extern "C" fn conj(z: (f64, f64)) -> (f64, f64) {
16283 (z.0, -z.1)
16284}
16285
16286#[no_mangle]
16287pub unsafe extern "C" fn conjf(z: (f32, f32)) -> (f32, f32) {
16288 (z.0, -z.1)
16289}
16290
16291#[no_mangle]
16292pub unsafe extern "C" fn conjl(z: (f64, f64)) -> (f64, f64) {
16293 conj(z)
16294}
16295
16296#[no_mangle]
16297pub unsafe extern "C" fn cproj(z: (f64, f64)) -> (f64, f64) {
16298 if z.0.is_infinite() || z.1.is_infinite() {
16299 (f64::INFINITY, if z.1.is_sign_positive() { 0.0 } else { -0.0 })
16300 } else {
16301 z
16302 }
16303}
16304
16305#[no_mangle]
16306pub unsafe extern "C" fn cprojf(z: (f32, f32)) -> (f32, f32) {
16307 if z.0.is_infinite() || z.1.is_infinite() {
16308 (f32::INFINITY, if z.1.is_sign_positive() { 0.0 } else { -0.0 })
16309 } else {
16310 z
16311 }
16312}
16313
16314#[no_mangle]
16315pub unsafe extern "C" fn cprojl(z: (f64, f64)) -> (f64, f64) {
16316 cproj(z)
16317}
16318
16319#[no_mangle]
16321pub unsafe extern "C" fn cexp(z: (f64, f64)) -> (f64, f64) {
16322 let r = libm::exp(z.0);
16323 (r * libm::cos(z.1), r * libm::sin(z.1))
16324}
16325
16326#[no_mangle]
16327pub unsafe extern "C" fn cexpf(z: (f32, f32)) -> (f32, f32) {
16328 let r = libm::expf(z.0);
16329 (r * libm::cosf(z.1), r * libm::sinf(z.1))
16330}
16331
16332#[no_mangle]
16333pub unsafe extern "C" fn cexpl(z: (f64, f64)) -> (f64, f64) {
16334 cexp(z)
16335}
16336
16337#[no_mangle]
16339pub unsafe extern "C" fn clog(z: (f64, f64)) -> (f64, f64) {
16340 (libm::log(cabs(z)), carg(z))
16341}
16342
16343#[no_mangle]
16344pub unsafe extern "C" fn clogf(z: (f32, f32)) -> (f32, f32) {
16345 (libm::logf(cabsf(z)), cargf(z))
16346}
16347
16348#[no_mangle]
16349pub unsafe extern "C" fn clogl(z: (f64, f64)) -> (f64, f64) {
16350 clog(z)
16351}
16352
16353#[no_mangle]
16355pub unsafe extern "C" fn csqrt(z: (f64, f64)) -> (f64, f64) {
16356 let r = cabs(z);
16357 let sign = if z.1 < 0.0 { -1.0 } else { 1.0 };
16358 (libm::sqrt((r + z.0) / 2.0), sign * libm::sqrt((r - z.0) / 2.0))
16359}
16360
16361#[no_mangle]
16362pub unsafe extern "C" fn csqrtf(z: (f32, f32)) -> (f32, f32) {
16363 let r = cabsf(z);
16364 let sign = if z.1 < 0.0 { -1.0f32 } else { 1.0f32 };
16365 (libm::sqrtf((r + z.0) / 2.0), sign * libm::sqrtf((r - z.0) / 2.0))
16366}
16367
16368#[no_mangle]
16369pub unsafe extern "C" fn csqrtl(z: (f64, f64)) -> (f64, f64) {
16370 csqrt(z)
16371}
16372
16373#[no_mangle]
16375pub unsafe extern "C" fn cpow(z: (f64, f64), w: (f64, f64)) -> (f64, f64) {
16376 let log_z = clog(z);
16377 let exp_arg = (w.0 * log_z.0 - w.1 * log_z.1, w.0 * log_z.1 + w.1 * log_z.0);
16378 cexp(exp_arg)
16379}
16380
16381#[no_mangle]
16382pub unsafe extern "C" fn cpowf(z: (f32, f32), w: (f32, f32)) -> (f32, f32) {
16383 let log_z = clogf(z);
16384 let exp_arg = (w.0 * log_z.0 - w.1 * log_z.1, w.0 * log_z.1 + w.1 * log_z.0);
16385 cexpf(exp_arg)
16386}
16387
16388#[no_mangle]
16389pub unsafe extern "C" fn cpowl(z: (f64, f64), w: (f64, f64)) -> (f64, f64) {
16390 cpow(z, w)
16391}
16392
16393#[no_mangle]
16395pub unsafe extern "C" fn ccos(z: (f64, f64)) -> (f64, f64) {
16396 (libm::cos(z.0) * libm::cosh(z.1), -libm::sin(z.0) * libm::sinh(z.1))
16397}
16398
16399#[no_mangle]
16400pub unsafe extern "C" fn ccosf(z: (f32, f32)) -> (f32, f32) {
16401 (libm::cosf(z.0) * libm::coshf(z.1), -libm::sinf(z.0) * libm::sinhf(z.1))
16402}
16403
16404#[no_mangle]
16405pub unsafe extern "C" fn ccosl(z: (f64, f64)) -> (f64, f64) {
16406 ccos(z)
16407}
16408
16409#[no_mangle]
16411pub unsafe extern "C" fn csin(z: (f64, f64)) -> (f64, f64) {
16412 (libm::sin(z.0) * libm::cosh(z.1), libm::cos(z.0) * libm::sinh(z.1))
16413}
16414
16415#[no_mangle]
16416pub unsafe extern "C" fn csinf(z: (f32, f32)) -> (f32, f32) {
16417 (libm::sinf(z.0) * libm::coshf(z.1), libm::cosf(z.0) * libm::sinhf(z.1))
16418}
16419
16420#[no_mangle]
16421pub unsafe extern "C" fn csinl(z: (f64, f64)) -> (f64, f64) {
16422 csin(z)
16423}
16424
16425#[no_mangle]
16427pub unsafe extern "C" fn ctan(z: (f64, f64)) -> (f64, f64) {
16428 let d = libm::cos(2.0 * z.0) + libm::cosh(2.0 * z.1);
16429 (libm::sin(2.0 * z.0) / d, libm::sinh(2.0 * z.1) / d)
16430}
16431
16432#[no_mangle]
16433pub unsafe extern "C" fn ctanf(z: (f32, f32)) -> (f32, f32) {
16434 let d = libm::cosf(2.0 * z.0) + libm::coshf(2.0 * z.1);
16435 (libm::sinf(2.0 * z.0) / d, libm::sinhf(2.0 * z.1) / d)
16436}
16437
16438#[no_mangle]
16439pub unsafe extern "C" fn ctanl(z: (f64, f64)) -> (f64, f64) {
16440 ctan(z)
16441}
16442
16443#[no_mangle]
16445pub unsafe extern "C" fn ccosh(z: (f64, f64)) -> (f64, f64) {
16446 (libm::cosh(z.0) * libm::cos(z.1), libm::sinh(z.0) * libm::sin(z.1))
16447}
16448
16449#[no_mangle]
16450pub unsafe extern "C" fn ccoshf(z: (f32, f32)) -> (f32, f32) {
16451 (libm::coshf(z.0) * libm::cosf(z.1), libm::sinhf(z.0) * libm::sinf(z.1))
16452}
16453
16454#[no_mangle]
16455pub unsafe extern "C" fn ccoshl(z: (f64, f64)) -> (f64, f64) {
16456 ccosh(z)
16457}
16458
16459#[no_mangle]
16461pub unsafe extern "C" fn csinh(z: (f64, f64)) -> (f64, f64) {
16462 (libm::sinh(z.0) * libm::cos(z.1), libm::cosh(z.0) * libm::sin(z.1))
16463}
16464
16465#[no_mangle]
16466pub unsafe extern "C" fn csinhf(z: (f32, f32)) -> (f32, f32) {
16467 (libm::sinhf(z.0) * libm::cosf(z.1), libm::coshf(z.0) * libm::sinf(z.1))
16468}
16469
16470#[no_mangle]
16471pub unsafe extern "C" fn csinhl(z: (f64, f64)) -> (f64, f64) {
16472 csinh(z)
16473}
16474
16475#[no_mangle]
16477pub unsafe extern "C" fn ctanh(z: (f64, f64)) -> (f64, f64) {
16478 let d = libm::cosh(2.0 * z.0) + libm::cos(2.0 * z.1);
16479 (libm::sinh(2.0 * z.0) / d, libm::sin(2.0 * z.1) / d)
16480}
16481
16482#[no_mangle]
16483pub unsafe extern "C" fn ctanhf(z: (f32, f32)) -> (f32, f32) {
16484 let d = libm::coshf(2.0 * z.0) + libm::cosf(2.0 * z.1);
16485 (libm::sinhf(2.0 * z.0) / d, libm::sinf(2.0 * z.1) / d)
16486}
16487
16488#[no_mangle]
16489pub unsafe extern "C" fn ctanhl(z: (f64, f64)) -> (f64, f64) {
16490 ctanh(z)
16491}
16492
16493#[no_mangle]
16496pub unsafe extern "C" fn cacos(z: (f64, f64)) -> (f64, f64) {
16497 let asin_z = casin(z);
16498 (3.14159265358979323846264338327950288419716939937510582097494459230781640 / 2.0 - asin_z.0, -asin_z.1)
16499}
16500
16501#[no_mangle]
16502pub unsafe extern "C" fn cacosf(z: (f32, f32)) -> (f32, f32) {
16503 let asin_z = casinf(z);
16504 (3.14159265358979323846264338327950288419716939937510582097494459230781640f32 / 2.0 - asin_z.0, -asin_z.1)
16505}
16506
16507#[no_mangle]
16508pub unsafe extern "C" fn cacosl(z: (f64, f64)) -> (f64, f64) {
16509 cacos(z)
16510}
16511
16512#[no_mangle]
16514pub unsafe extern "C" fn casin(z: (f64, f64)) -> (f64, f64) {
16515 let iz = (-z.1, z.0);
16517 let one_minus_z2 = (1.0 - z.0 * z.0 + z.1 * z.1, -2.0 * z.0 * z.1);
16519 let sqrt_val = csqrt(one_minus_z2);
16520 let arg = clog((iz.0 + sqrt_val.0, iz.1 + sqrt_val.1));
16521 (arg.1, -arg.0)
16523}
16524
16525#[no_mangle]
16526pub unsafe extern "C" fn casinf(z: (f32, f32)) -> (f32, f32) {
16527 let iz = (-z.1, z.0);
16528 let one_minus_z2 = (1.0 - z.0 * z.0 + z.1 * z.1, -2.0 * z.0 * z.1);
16529 let sqrt_val = csqrtf(one_minus_z2);
16530 let arg = clogf((iz.0 + sqrt_val.0, iz.1 + sqrt_val.1));
16531 (arg.1, -arg.0)
16532}
16533
16534#[no_mangle]
16535pub unsafe extern "C" fn casinl(z: (f64, f64)) -> (f64, f64) {
16536 casin(z)
16537}
16538
16539#[no_mangle]
16541pub unsafe extern "C" fn catan(z: (f64, f64)) -> (f64, f64) {
16542 let num = (1.0 + z.1, -z.0);
16546 let den = (1.0 - z.1, z.0);
16547 let ratio = cdiv(num, den);
16548 let log_ratio = clog(ratio);
16549 (-log_ratio.1 / 2.0, log_ratio.0 / 2.0)
16551}
16552
16553#[no_mangle]
16554pub unsafe extern "C" fn catanf(z: (f32, f32)) -> (f32, f32) {
16555 let num = (1.0 + z.1, -z.0);
16556 let den = (1.0 - z.1, z.0);
16557 let ratio = cdivf(num, den);
16558 let log_ratio = clogf(ratio);
16559 (-log_ratio.1 / 2.0, log_ratio.0 / 2.0)
16560}
16561
16562#[no_mangle]
16563pub unsafe extern "C" fn catanl(z: (f64, f64)) -> (f64, f64) {
16564 catan(z)
16565}
16566
16567fn cdiv(a: (f64, f64), b: (f64, f64)) -> (f64, f64) {
16569 let d = b.0 * b.0 + b.1 * b.1;
16570 ((a.0 * b.0 + a.1 * b.1) / d, (a.1 * b.0 - a.0 * b.1) / d)
16571}
16572
16573fn cdivf(a: (f32, f32), b: (f32, f32)) -> (f32, f32) {
16574 let d = b.0 * b.0 + b.1 * b.1;
16575 ((a.0 * b.0 + a.1 * b.1) / d, (a.1 * b.0 - a.0 * b.1) / d)
16576}
16577
16578#[no_mangle]
16580pub unsafe extern "C" fn cacosh(z: (f64, f64)) -> (f64, f64) {
16581 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16582 let z2_minus_1 = (z2.0 - 1.0, z2.1);
16583 let sqrt_val = csqrt(z2_minus_1);
16584 clog((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16585}
16586
16587#[no_mangle]
16588pub unsafe extern "C" fn cacoshf(z: (f32, f32)) -> (f32, f32) {
16589 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16590 let z2_minus_1 = (z2.0 - 1.0, z2.1);
16591 let sqrt_val = csqrtf(z2_minus_1);
16592 clogf((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16593}
16594
16595#[no_mangle]
16596pub unsafe extern "C" fn cacoshl(z: (f64, f64)) -> (f64, f64) {
16597 cacosh(z)
16598}
16599
16600#[no_mangle]
16602pub unsafe extern "C" fn casinh(z: (f64, f64)) -> (f64, f64) {
16603 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16604 let z2_plus_1 = (z2.0 + 1.0, z2.1);
16605 let sqrt_val = csqrt(z2_plus_1);
16606 clog((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16607}
16608
16609#[no_mangle]
16610pub unsafe extern "C" fn casinhf(z: (f32, f32)) -> (f32, f32) {
16611 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16612 let z2_plus_1 = (z2.0 + 1.0, z2.1);
16613 let sqrt_val = csqrtf(z2_plus_1);
16614 clogf((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16615}
16616
16617#[no_mangle]
16618pub unsafe extern "C" fn casinhl(z: (f64, f64)) -> (f64, f64) {
16619 casinh(z)
16620}
16621
16622#[no_mangle]
16624pub unsafe extern "C" fn catanh(z: (f64, f64)) -> (f64, f64) {
16625 let num = (1.0 + z.0, z.1);
16626 let den = (1.0 - z.0, -z.1);
16627 let ratio = cdiv(num, den);
16628 let log_ratio = clog(ratio);
16629 (log_ratio.0 / 2.0, log_ratio.1 / 2.0)
16630}
16631
16632#[no_mangle]
16633pub unsafe extern "C" fn catanhf(z: (f32, f32)) -> (f32, f32) {
16634 let num = (1.0 + z.0, z.1);
16635 let den = (1.0 - z.0, -z.1);
16636 let ratio = cdivf(num, den);
16637 let log_ratio = clogf(ratio);
16638 (log_ratio.0 / 2.0, log_ratio.1 / 2.0)
16639}
16640
16641#[no_mangle]
16642pub unsafe extern "C" fn catanhl(z: (f64, f64)) -> (f64, f64) {
16643 catanh(z)
16644}
16645
16646#[inline(never)]
16651#[no_mangle]
16652pub unsafe extern "C" fn fmaxf(x: f32, y: f32) -> f32 {
16653 fmaxf_impl(x, y)
16654}
16655
16656#[no_mangle]
16657pub unsafe extern "C" fn fdimf(x: f32, y: f32) -> f32 {
16658 if x.is_nan() || y.is_nan() {
16659 return f32::NAN;
16660 }
16661 if x > y { x - y } else { 0.0 }
16662}
16663
16664#[no_mangle]
16665pub unsafe extern "C" fn fmaf(x: f32, y: f32, z: f32) -> f32 {
16666 if (x.is_infinite() && y == 0.0) || (y.is_infinite() && x == 0.0) {
16667 feraiseexcept(FE_INVALID);
16668 return f32::NAN;
16669 }
16670 if x.is_nan() || y.is_nan() || z.is_nan() {
16671 return f32::NAN;
16672 }
16673 let r = libm::fmaf(x, y, z);
16674 if r.is_nan() {
16675 feraiseexcept(FE_INVALID);
16676 }
16677 r
16678}
16679
16680#[no_mangle]
16681pub unsafe extern "C" fn ilogbf(x: f32) -> i32 {
16682 if x.is_nan() {
16683 feraiseexcept(FE_INVALID);
16684 return -0x7fffffff - 1;
16685 }
16686 if x == 0.0 || x.is_infinite() {
16687 feraiseexcept(FE_INVALID);
16688 return if x == 0.0 { -0x7fffffff - 1 } else { 0x7fffffff };
16689 }
16690 let bits = x.to_bits();
16691 let exp = ((bits >> 23) & 0xff) as i32;
16692 if exp == 0 {
16693 let mut v = bits & 0x7fffff;
16694 let mut e = -126;
16695 while v < (1u32 << 23) { v <<= 1; e -= 1; }
16696 e
16697 } else {
16698 exp - 127
16699 }
16700}
16701
16702#[no_mangle]
16703pub unsafe extern "C" fn logbf(x: f32) -> f32 {
16704 if x.is_nan() { return x; }
16705 if x == 0.0 { return __math_divzerof(1); }
16706 let bits = x.to_bits();
16707 let exp = ((bits >> 23) & 0xff) as i32;
16708 if exp == 0 {
16709 let mut v = bits & 0x7fffff;
16710 let mut e = -126i32;
16711 while v < (1u32 << 23) { v <<= 1; e -= 1; }
16712 e as f32
16713 } else if exp == 0xff {
16714 x * x
16715 } else {
16716 (exp - 127) as f32
16717 }
16718}
16719
16720#[no_mangle]
16721pub unsafe extern "C" fn nearbyintf(x: f32) -> f32 {
16722 let had_inexact = fetestexcept(FE_INEXACT) & FE_INEXACT != 0;
16723 let r = libm::rintf(x);
16724 if !had_inexact {
16725 feclearexcept(FE_INEXACT);
16726 }
16727 r
16728}
16729
16730#[no_mangle]
16731pub unsafe extern "C" fn nextafterf(x: f32, y: f32) -> f32 {
16732 if x.is_nan() || y.is_nan() { return x + y; }
16733 if x == 0.0 && y == 0.0 { return y; }
16734 if x == y { return x; }
16735 let r = libm::nextafterf(x, y);
16736 if r.is_infinite() && x.is_finite() {
16737 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16738 } else if r != x {
16739 let bits = r.to_bits();
16740 let is_subnormal = (bits & 0x7f800000) == 0 && (bits & 0x7fffff) != 0;
16741 if r == 0.0 || is_subnormal {
16742 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16743 }
16744 }
16745 r
16746}
16747
16748#[no_mangle]
16749#[cfg(target_arch = "x86_64")]
16750pub unsafe extern "C" fn nexttowardf(x: f32, y: f64) -> f32 {
16751 if y.is_nan() { return (x as f64 + y) as f32; }
16752 if x == 0.0 && y == 0.0 {
16753 return if y.is_sign_negative() { -0.0 } else { 0.0 };
16754 }
16755 if (x as f64) == y { return x; }
16756 nextafterf(x, if y > x as f64 { f32::INFINITY } else { f32::NEG_INFINITY })
16757}
16758
16759#[no_mangle]
16760#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
16761pub unsafe extern "C" fn nexttowardf(x: f32, y: f128) -> f32 {
16762 if y.is_nan() { return (x as f128 + y) as f32; }
16763 if (x as f128) == y { return x; }
16764 nextafterf(x, if y > x as f128 { f32::INFINITY } else { f32::NEG_INFINITY })
16765}
16766
16767#[no_mangle]
16768pub unsafe extern "C" fn remainderf(x: f32, y: f32) -> f32 {
16769 if x.is_nan() || y.is_nan() { return x + y; }
16770 if y == 0.0 || x.is_infinite() { return __math_invalidf(x); }
16771 libm::remainderf(x, y)
16772}
16773
16774#[no_mangle]
16775pub unsafe extern "C" fn remquof(x: f32, y: f32, quo: *mut i32) -> f32 {
16776 if x.is_nan() || y.is_nan() {
16777 if !quo.is_null() { *quo = 0; }
16778 return x + y;
16779 }
16780 if y == 0.0 || x.is_infinite() {
16781 if !quo.is_null() { *quo = 0; }
16782 return __math_invalidf(x);
16783 }
16784 let (r, q) = libm::remquof(x, y);
16785 if !quo.is_null() { *quo = q; }
16786 r
16787}
16788
16789#[no_mangle]
16790pub unsafe extern "C" fn exp2f(x: f32) -> f32 {
16791 if x == f32::INFINITY { return f32::INFINITY; }
16792 if x == f32::NEG_INFINITY { return 0.0; }
16793 if x.is_nan() { return f32::NAN; }
16794 let r = libm::exp2f(x);
16795 if r.is_infinite() && x.is_finite() {
16796 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16797 } else if r == 0.0 && x < -149.0 {
16798 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16799 } else if r != 0.0 && x != libm::truncf(x) {
16800 let bits = r.to_bits();
16801 if (bits & 0x7f800000) == 0 {
16802 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16803 }
16804 }
16805 r
16806}
16807
16808#[no_mangle]
16809pub unsafe extern "C" fn expm1f(x: f32) -> f32 {
16810 libm::expm1f(x)
16811}
16812
16813#[no_mangle]
16814pub unsafe extern "C" fn log1pf(x: f32) -> f32 {
16815 if x == -1.0 {
16816 feraiseexcept(FE_DIVBYZERO);
16817 return f32::NEG_INFINITY;
16818 }
16819 libm::log1pf(x)
16820}
16821
16822#[no_mangle]
16823pub unsafe extern "C" fn acoshf(x: f32) -> f32 {
16824 if x < 1.0 {
16825 feraiseexcept(FE_INVALID);
16826 return f32::NAN;
16827 }
16828 libm::acoshf(x)
16829}
16830
16831#[no_mangle]
16832pub unsafe extern "C" fn asinhf(x: f32) -> f32 {
16833 if x == 0.0 { return x; }
16834 libm::asinhf(x)
16835}
16836
16837#[no_mangle]
16838pub unsafe extern "C" fn atanhf(x: f32) -> f32 {
16839 if x == 0.0 { return x; }
16840 let e = ((x.to_bits() >> 23) & 0xff) as i32;
16841 if e < 0x7f - 32 {
16842 feraiseexcept(FE_INEXACT);
16843 if e == 0 { feraiseexcept(FE_UNDERFLOW); }
16844 return x;
16845 }
16846 if x == 1.0 {
16847 feraiseexcept(FE_DIVBYZERO);
16848 return f32::INFINITY;
16849 }
16850 if x == -1.0 {
16851 feraiseexcept(FE_DIVBYZERO);
16852 return f32::NEG_INFINITY;
16853 }
16854 if x.is_nan() { return x; }
16855 let ax = libm::fabsf(x);
16856 if ax > 1.0 {
16857 feraiseexcept(FE_INVALID);
16858 return f32::NAN;
16859 }
16860 if ax < 0.5 {
16861 let r = libm::log1pf(2.0 * (ax + ax * ax / (1.0 - ax))) / 2.0;
16862 if x < 0.0 { -r } else { r }
16863 } else {
16864 let r = 0.5 * libm::logf((1.0 + ax) / (1.0 - ax));
16865 if x < 0.0 { -r } else { r }
16866 }
16867}
16868
16869#[no_mangle]
16870pub unsafe extern "C" fn cbrtf(x: f32) -> f32 {
16871 libm::cbrtf(x)
16872}
16873
16874#[no_mangle]
16875pub unsafe extern "C" fn erff(x: f32) -> f32 {
16876 libm::erff(x)
16877}
16878
16879#[no_mangle]
16880pub unsafe extern "C" fn erfcf(x: f32) -> f32 {
16881 libm::erfcf(x)
16882}
16883
16884#[no_mangle]
16885pub unsafe extern "C" fn lgammaf(x: f32) -> f32 {
16886 if x.is_nan() {
16887 crate::signgam = 1;
16888 return x;
16889 }
16890 if x == 0.0 {
16891 crate::signgam = if x.is_sign_negative() { -1 } else { 1 };
16892 feraiseexcept(FE_DIVBYZERO);
16893 return f32::INFINITY;
16894 }
16895 let (r, sign) = libm::lgammaf_r(x);
16896 crate::signgam = sign;
16897 r
16898}
16899
16900#[no_mangle]
16901pub unsafe extern "C" fn tgammaf(x: f32) -> f32 {
16902 if x.is_nan() { return x; }
16903 if x == 0.0 {
16904 feraiseexcept(FE_DIVBYZERO);
16905 return if x.is_sign_negative() { f32::NEG_INFINITY } else { f32::INFINITY };
16906 }
16907 if x.is_infinite() {
16908 return if x.is_sign_negative() { __math_invalidf(x) } else { f32::INFINITY };
16909 }
16910 if x < 0.0 && x == libm::floorf(x) {
16911 feraiseexcept(FE_INVALID);
16912 return f32::NAN;
16913 }
16914 libm::tgammaf(x)
16915}
16916
16917#[no_mangle]
16918pub unsafe extern "C" fn lroundf(x: f32) -> core::ffi::c_long {
16919 libm::roundf(x) as core::ffi::c_long
16920}
16921
16922#[no_mangle]
16923pub unsafe extern "C" fn llroundf(x: f32) -> i64 {
16924 libm::roundf(x) as i64
16925}
16926
16927#[no_mangle]
16932pub unsafe extern "C" fn wcscasecmp(s1: *const u32, s2: *const u32) -> i32 {
16933 let mut i = 0;
16934 loop {
16935 let c1 = *s1.add(i);
16936 let c2 = *s2.add(i);
16937 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16938 let l1 = if c1 >= 'A' as u32 && c1 <= 'Z' as u32 { c1 + 32 } else { c1 };
16939 let l2 = if c2 >= 'A' as u32 && c2 <= 'Z' as u32 { c2 + 32 } else { c2 };
16940 if l1 != l2 { return (l1 as i32) - (l2 as i32); }
16941 i += 1;
16942 }
16943}
16944
16945#[no_mangle]
16946pub unsafe extern "C" fn wcscasecmp_l(s1: *const u32, s2: *const u32, _loc: *mut core::ffi::c_void) -> i32 {
16947 wcscasecmp(s1, s2)
16948}
16949
16950#[no_mangle]
16951pub unsafe extern "C" fn wcsncasecmp(s1: *const u32, s2: *const u32, n: usize) -> i32 {
16952 let mut i = 0;
16953 while i < n {
16954 let c1 = *s1.add(i);
16955 let c2 = *s2.add(i);
16956 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16957 let l1 = if c1 >= 'A' as u32 && c1 <= 'Z' as u32 { c1 + 32 } else { c1 };
16958 let l2 = if c2 >= 'A' as u32 && c2 <= 'Z' as u32 { c2 + 32 } else { c2 };
16959 if l1 != l2 { return (l1 as i32) - (l2 as i32); }
16960 i += 1;
16961 }
16962 0
16963}
16964
16965#[no_mangle]
16966pub unsafe extern "C" fn wcsncasecmp_l(s1: *const u32, s2: *const u32, n: usize, _loc: *mut core::ffi::c_void) -> i32 {
16967 wcsncasecmp(s1, s2, n)
16968}
16969
16970#[no_mangle]
16971pub unsafe extern "C" fn wcscoll(s1: *const u32, s2: *const u32) -> i32 {
16972 let mut i = 0;
16974 loop {
16975 let c1 = *s1.add(i);
16976 let c2 = *s2.add(i);
16977 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16978 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
16979 i += 1;
16980 }
16981}
16982
16983#[no_mangle]
16984pub unsafe extern "C" fn wcstok(s: *mut u32, sep: *const u32, p: *mut *mut u32) -> *mut u32 {
16985 let mut src = if s.is_null() { *p } else { s };
16986 while *src != 0 && *sep.add(0) == *src { src = src.add(1); }
16988 if *src == 0 { return core::ptr::null_mut(); }
16989 let start = src;
16990 while *src != 0 && *sep.add(0) != *src { src = src.add(1); }
16992 if *src != 0 {
16993 *src = 0;
16994 *p = src.add(1);
16995 } else {
16996 *p = src;
16997 }
16998 start
16999}
17000
17001#[no_mangle]
17002pub unsafe extern "C" fn wcswcs(haystack: *const u32, needle: *const u32) -> *mut u32 {
17003 if *needle == 0 { return haystack as *mut u32; }
17004 let mut i = 0;
17005 while *haystack.add(i) != 0 {
17006 let mut j = 0;
17007 while *needle.add(j) != 0 && *haystack.add(i + j) == *needle.add(j) {
17008 j += 1;
17009 }
17010 if *needle.add(j) == 0 { return haystack.add(i) as *mut u32; }
17011 i += 1;
17012 }
17013 core::ptr::null_mut()
17014}
17015
17016#[no_mangle]
17017pub unsafe extern "C" fn wcswidth(s: *const u32, n: usize) -> i32 {
17018 let mut width = 0i32;
17019 let mut i = 0;
17020 while i < n {
17021 let c = *s.add(i);
17022 if c == 0 { break; }
17023 width += 1;
17025 i += 1;
17026 }
17027 width
17028}
17029
17030#[no_mangle]
17031pub unsafe extern "C" fn wcsftime(s: *mut u32, maxsize: usize, fmt: *const u32, tm: *const c_void) -> usize {
17032 if s.is_null() || fmt.is_null() || maxsize == 0 { return 0; }
17033 let mut cfmt = [0u8; 1024];
17036 let mut o = 0usize;
17037 let mut i = 0usize;
17038 let mut st: c_uint = 0;
17039 while *fmt.add(i) != 0 && o + 8 < cfmt.len() {
17040 let n = wcrtomb(
17041 cfmt.as_mut_ptr().add(o) as *mut c_char,
17042 *fmt.add(i) as c_int,
17043 &mut st as *mut c_uint,
17044 );
17045 if n == !0usize { return 0; }
17046 o += n;
17047 i += 1;
17048 }
17049 cfmt[o] = 0;
17050 let mut out = [0u8; 4096];
17051 let mut lim = maxsize.saturating_mul(4);
17052 if lim > out.len() { lim = out.len(); }
17053 let n = strftime(out.as_mut_ptr() as *mut c_char, lim, cfmt.as_ptr() as *const c_char, tm as *const tm);
17054 if n == 0 { return 0; }
17055 let mut ws = 0usize;
17056 let mut p = 0usize;
17057 while p < n && ws + 1 < maxsize {
17058 let mut wc: c_int = 0;
17059 let mut st2: c_uint = 0;
17060 let r = mbrtowc(&mut wc, out.as_ptr().add(p) as *const c_char, n - p, &mut st2);
17061 if r == !0usize { return 0; }
17062 if r == 0 || r == !1usize { break; }
17063 *s.add(ws) = wc as u32;
17064 ws += 1;
17065 p += r;
17066 }
17067 *s.add(ws) = 0;
17068 ws
17069}
17070
17071#[no_mangle]
17072pub unsafe extern "C" fn mbsnrtowcs(
17073 dst: *mut u32,
17074 src: *mut *const u8,
17075 nms: usize,
17076 len: usize,
17077 st: *mut core::ffi::c_void,
17078) -> usize {
17079 if src.is_null() { return 0; }
17080 let mut s = *src;
17081 if s.is_null() { return 0; }
17082 let state = st as *mut c_uint;
17083 let limit = if dst.is_null() { usize::MAX } else { len };
17084 let mut count = 0usize;
17085 let mut n = nms;
17086 while count < limit && n > 0 {
17087 let c = *s;
17088 if c == 0 {
17089 if !dst.is_null() {
17090 if count < len { *dst.add(count) = 0; }
17091 *src = core::ptr::null();
17092 }
17093 return count;
17094 }
17095 let mut wc: c_int = 0;
17096 let r = mbrtowc(&mut wc, s as *const c_char, n, state);
17097 if r == !0usize {
17098 *src = s;
17099 return !0usize;
17100 }
17101 if r == !1usize { break; }
17102 if !dst.is_null() { *dst.add(count) = wc as u32; }
17103 count += 1;
17104 s = s.add(r);
17105 n -= r;
17106 }
17107 *src = s;
17108 count
17109}
17110
17111#[no_mangle]
17112pub unsafe extern "C" fn wcsnrtombs(dst: *mut u8, src: *mut *const u32, nwc: usize, len: usize, _st: *mut core::ffi::c_void) -> usize {
17113 let mut count = 0;
17114 let mut s = *src;
17115 let mut d = dst;
17116 while count < len && count < nwc {
17117 let c = *s;
17118 if c == 0 { break; }
17119 if !d.is_null() {
17120 if c < 0x80 {
17121 *d = c as u8;
17122 d = d.add(1);
17123 count += 1;
17124 } else if c < 0x800 {
17125 if count + 2 > len { break; }
17126 *d = 0xc0 | (c >> 6) as u8;
17127 *d.add(1) = 0x80 | (c & 0x3f) as u8;
17128 d = d.add(2);
17129 count += 2;
17130 } else if c < 0x10000 {
17131 if count + 3 > len { break; }
17132 *d = 0xe0 | (c >> 12) as u8;
17133 *d.add(1) = 0x80 | ((c >> 6) & 0x3f) as u8;
17134 *d.add(2) = 0x80 | (c & 0x3f) as u8;
17135 d = d.add(3);
17136 count += 3;
17137 } else {
17138 if count + 4 > len { break; }
17139 *d = 0xf0 | (c >> 18) as u8;
17140 *d.add(1) = 0x80 | ((c >> 12) & 0x3f) as u8;
17141 *d.add(2) = 0x80 | ((c >> 6) & 0x3f) as u8;
17142 *d.add(3) = 0x80 | (c & 0x3f) as u8;
17143 d = d.add(4);
17144 count += 4;
17145 }
17146 }
17147 s = s.add(1);
17148 }
17149 if !dst.is_null() { *src = s; }
17150 count
17151}
17152
17153pub type thrd_start_t = Option<unsafe extern "C" fn(arg: *mut core::ffi::c_void) -> i32>;
17160
17161#[no_mangle]
17163pub unsafe extern "C" fn thrd_create(thr: *mut usize, func: thrd_start_t, arg: *mut core::ffi::c_void) -> i32 {
17164 let mut thread: u64 = 0;
17165 let r = pthread_create(&mut thread, core::ptr::null(), core::mem::transmute(func), arg);
17166 if r == 0 {
17167 *thr = thread as usize;
17168 0 } else {
17170 -1 }
17172}
17173
17174#[no_mangle]
17175pub unsafe extern "C" fn thrd_join(thr: usize, res: *mut i32) -> i32 {
17176 let mut retval: *mut core::ffi::c_void = core::ptr::null_mut();
17177 let r = pthread_join(thr as u64, &mut retval);
17178 if r == 0 {
17179 if !res.is_null() { *res = retval as i32; }
17180 0
17181 } else {
17182 -1
17183 }
17184}
17185
17186#[no_mangle]
17187pub unsafe extern "C" fn thrd_exit(res: i32) {
17188 pthread_exit(res as *mut core::ffi::c_void);
17189}
17190
17191#[no_mangle]
17192pub unsafe extern "C" fn thrd_detach(thr: usize) -> i32 {
17193 let r = pthread_detach(thr as u64);
17194 if r == 0 { 0 } else { -1 }
17195}
17196
17197#[no_mangle]
17198pub unsafe extern "C" fn thrd_current() -> usize {
17199 pthread_self() as usize
17200}
17201
17202#[no_mangle]
17203pub unsafe extern "C" fn thrd_equal(thr1: usize, thr2: usize) -> i32 {
17204 (thr1 == thr2) as i32
17205}
17206
17207#[no_mangle]
17208pub unsafe extern "C" fn thrd_sleep(duration: *const core::ffi::c_void, remaining: *mut core::ffi::c_void) -> i32 {
17209 nanosleep(duration as *const timespec, remaining as *mut timespec)
17210}
17211
17212#[no_mangle]
17213pub unsafe extern "C" fn thrd_yield() {
17214 sched_yield();
17215}
17216
17217#[no_mangle]
17219pub unsafe extern "C" fn mtx_init(mtx: *mut usize, _mtx_type: i32) -> i32 {
17220 let r = pthread_mutex_init(mtx as *mut pthread_mutex_t, core::ptr::null());
17221 if r == 0 { 0 } else { -1 }
17222}
17223
17224#[no_mangle]
17225pub unsafe extern "C" fn mtx_lock(mtx: *mut usize) -> i32 {
17226 let r = pthread_mutex_lock(mtx as *mut pthread_mutex_t);
17227 if r == 0 { 0 } else { -1 }
17228}
17229
17230#[no_mangle]
17231pub unsafe extern "C" fn mtx_trylock(mtx: *mut usize) -> i32 {
17232 let r = pthread_mutex_trylock(mtx as *mut pthread_mutex_t);
17233 if r == 0 { 0 } else { -1 }
17234}
17235
17236#[no_mangle]
17237pub unsafe extern "C" fn mtx_unlock(mtx: *mut usize) -> i32 {
17238 let r = pthread_mutex_unlock(mtx as *mut pthread_mutex_t);
17239 if r == 0 { 0 } else { -1 }
17240}
17241
17242#[no_mangle]
17243pub unsafe extern "C" fn mtx_destroy(mtx: *mut usize) {
17244 pthread_mutex_destroy(mtx as *mut pthread_mutex_t);
17245}
17246
17247#[no_mangle]
17248pub unsafe extern "C" fn mtx_timedlock(mtx: *mut usize, ts: *const core::ffi::c_void) -> i32 {
17249 let r = pthread_mutex_timedlock(mtx as *mut pthread_mutex_t, ts as *const timespec);
17250 if r == 0 { 0 } else { -1 }
17251}
17252
17253#[no_mangle]
17255pub unsafe extern "C" fn cnd_init(cnd: *mut usize) -> i32 {
17256 let r = pthread_cond_init(cnd as *mut pthread_cond_t, core::ptr::null());
17257 if r == 0 { 0 } else { -1 }
17258}
17259
17260#[no_mangle]
17261pub unsafe extern "C" fn cnd_signal(cnd: *mut usize) -> i32 {
17262 let r = pthread_cond_signal(cnd as *mut pthread_cond_t);
17263 if r == 0 { 0 } else { -1 }
17264}
17265
17266#[no_mangle]
17267pub unsafe extern "C" fn cnd_broadcast(cnd: *mut usize) -> i32 {
17268 let r = pthread_cond_broadcast(cnd as *mut pthread_cond_t);
17269 if r == 0 { 0 } else { -1 }
17270}
17271
17272#[no_mangle]
17273pub unsafe extern "C" fn cnd_wait(cnd: *mut usize, mtx: *mut usize) -> i32 {
17274 let r = pthread_cond_wait(cnd as *mut pthread_cond_t, mtx as *mut pthread_mutex_t);
17275 if r == 0 { 0 } else { -1 }
17276}
17277
17278#[no_mangle]
17279pub unsafe extern "C" fn cnd_timedwait(cnd: *mut usize, mtx: *mut usize, ts: *const core::ffi::c_void) -> i32 {
17280 let r = pthread_cond_timedwait(cnd as *mut pthread_cond_t, mtx as *mut pthread_mutex_t, ts as *const timespec);
17281 if r == 0 { 0 } else { -1 }
17282}
17283
17284#[no_mangle]
17285pub unsafe extern "C" fn cnd_destroy(cnd: *mut usize) {
17286 pthread_cond_destroy(cnd as *mut pthread_cond_t);
17287}
17288
17289#[no_mangle]
17291pub unsafe extern "C" fn tss_create(key: *mut u32, dtor: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>) -> i32 {
17292 let r = pthread_key_create(key, dtor);
17293 if r == 0 { 0 } else { -1 }
17294}
17295
17296#[no_mangle]
17297pub unsafe extern "C" fn tss_delete(key: u32) {
17298 pthread_key_delete(key);
17299}
17300
17301#[no_mangle]
17302pub unsafe extern "C" fn tss_set(key: u32, val: *mut core::ffi::c_void) -> i32 {
17303 let r = pthread_setspecific(key, val);
17304 if r == 0 { 0 } else { -1 }
17305}
17306
17307#[no_mangle]
17308pub unsafe extern "C" fn tss_get(key: u32) -> *mut core::ffi::c_void {
17309 pthread_getspecific(key)
17310}
17311
17312#[no_mangle]
17314pub unsafe extern "C" fn call_once(flag: *mut u32, func: Option<unsafe extern "C" fn()>) {
17315 if *flag == 0 {
17316 if let Some(f) = func { f(); }
17317 *flag = 1;
17318 }
17319}
17320
17321#[no_mangle]
17327pub unsafe extern "C" fn accept4(fd: i32, addr: *mut core::ffi::c_void, addrlen: *mut u32, flags: i32) -> i32 {
17328 syscall_ret(<Arch as Syscalls>::syscall4(SYS_ACCEPT4, fd as i64, addr as i64, addrlen as i64, flags as i64)) as i32
17329}
17330
17331#[no_mangle]
17337pub unsafe extern "C" fn epoll_create(size: i32) -> i32 {
17338 #[cfg(target_arch = "x86_64")]
17339 { syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE, size as i64)) as i32 }
17340 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
17341 {
17342 if size < 1 {
17343 ERRNO!() = EINVAL;
17344 return -1;
17345 }
17346 syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE1, 0)) as i32
17347 }
17348}
17349
17350#[no_mangle]
17351pub unsafe extern "C" fn epoll_create1(flags: i32) -> i32 {
17352 syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE1, flags as i64)) as i32
17353}
17354
17355#[no_mangle]
17356pub unsafe extern "C" fn epoll_ctl(epfd: i32, op: i32, fd: i32, event: *mut core::ffi::c_void) -> i32 {
17357 syscall_ret(<Arch as Syscalls>::syscall4(SYS_EPOLL_CTL, epfd as i64, op as i64, fd as i64, event as i64)) as i32
17358}
17359
17360#[no_mangle]
17361pub unsafe extern "C" fn epoll_wait(epfd: i32, events: *mut core::ffi::c_void, maxevents: i32, timeout: i32) -> i32 {
17362 #[cfg(target_arch = "x86_64")]
17363 {
17364 syscall_ret(<Arch as Syscalls>::syscall4(
17365 SYS_EPOLL_WAIT,
17366 epfd as i64,
17367 events as i64,
17368 maxevents as i64,
17369 timeout as i64,
17370 )) as i32
17371 }
17372 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
17373 {
17374 epoll_pwait(epfd, events, maxevents, timeout, core::ptr::null())
17375 }
17376}
17377
17378#[no_mangle]
17379pub unsafe extern "C" fn epoll_pwait(
17380 epfd: i32,
17381 events: *mut core::ffi::c_void,
17382 maxevents: i32,
17383 timeout: i32,
17384 sigmask: *const u64,
17385) -> i32 {
17386 syscall_ret(<Arch as Syscalls>::syscall6(
17387 SYS_EPOLL_PWAIT,
17388 epfd as i64,
17389 events as i64,
17390 maxevents as i64,
17391 timeout as i64,
17392 sigmask as i64,
17393 8,
17394 )) as i32
17395}
17396
17397#[no_mangle]
17398pub unsafe extern "C" fn eventfd(initval: u32, flags: i32) -> i32 {
17399 syscall_ret(<Arch as Syscalls>::syscall2(SYS_EVENTFD2, initval as i64, flags as i64)) as i32
17400}
17401
17402#[no_mangle]
17403pub unsafe extern "C" fn eventfd_read(fd: i32, value: *mut u64) -> i32 {
17404 let n = crate::read(fd, value as *mut core::ffi::c_void, 8);
17405 if n == 8 { 0 } else { -1 }
17406}
17407
17408#[no_mangle]
17409pub unsafe extern "C" fn eventfd_write(fd: i32, value: u64) -> i32 {
17410 let n = crate::write(fd, &value as *const u64 as *const core::ffi::c_void, 8);
17411 if n == 8 { 0 } else { -1 }
17412}
17413
17414#[no_mangle]
17415pub unsafe extern "C" fn signalfd(fd: i32, mask: *const u64, flags: i32) -> i32 {
17416 syscall_ret(<Arch as Syscalls>::syscall4(SYS_SIGNALFD4, fd as i64, mask as i64, 8, flags as i64)) as i32
17417}
17418
17419#[no_mangle]
17420pub unsafe extern "C" fn timerfd_create(clockid: i32, flags: i32) -> i32 {
17421 syscall_ret(<Arch as Syscalls>::syscall2(SYS_TIMERFD_CREATE, clockid as i64, flags as i64)) as i32
17422}
17423
17424#[no_mangle]
17425pub 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 {
17426 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
17427}
17428
17429#[no_mangle]
17430pub unsafe extern "C" fn timerfd_gettime(fd: i32, curr_value: *mut core::ffi::c_void) -> i32 {
17431 syscall_ret(<Arch as Syscalls>::syscall2(SYS_TIMERFD_GETTIME, fd as i64, curr_value as i64)) as i32
17432}
17433
17434#[no_mangle]
17439pub unsafe extern "C" fn prctl(option: i32, mut args: ...) -> i32 {
17440 let a1 = args.next_arg::<i64>();
17441 let a2 = args.next_arg::<i64>();
17442 let a3 = args.next_arg::<i64>();
17443 let a4 = args.next_arg::<i64>();
17444 syscall_ret(<Arch as Syscalls>::syscall5(SYS_PRCTL, option as i64, a1, a2, a3, a4)) as i32
17445}
17446
17447#[no_mangle]
17448pub unsafe extern "C" fn quotactl(cmd: i32, special: *const core::ffi::c_char, id: i32, addr: *mut core::ffi::c_char) -> i32 {
17449 syscall_ret(<Arch as Syscalls>::syscall4(sysno(179, 60), cmd as i64, special as i64, id as i64, addr as i64)) as i32
17450}
17451
17452#[no_mangle]
17453pub unsafe extern "C" fn klogctl(type_: i32, bufp: *mut core::ffi::c_char, len: i32) -> i32 {
17454 syscall_ret(<Arch as Syscalls>::syscall3(sysno(103, 116), type_ as i64, bufp as i64, len as i64)) as i32
17455}
17456
17457static mut SYSLOG_IDENT: [core::ffi::c_char; 64] = [0; 64];
17458static mut SYSLOG_OPTIONS: i32 = 0;
17459static mut SYSLOG_FACILITY: i32 = 1;
17460
17461#[no_mangle]
17462pub unsafe extern "C" fn openlog(ident: *const core::ffi::c_char, option: i32, facility: i32) {
17463 SYSLOG_OPTIONS = option;
17464 SYSLOG_FACILITY = facility & 0x3f8;
17465 SYSLOG_IDENT[0] = 0;
17466 if !ident.is_null() {
17467 let mut i = 0;
17468 while i < 63 && *ident.add(i) != 0 {
17469 SYSLOG_IDENT[i] = *ident.add(i);
17470 i += 1;
17471 }
17472 SYSLOG_IDENT[i] = 0;
17473 }
17474}
17475
17476#[repr(C)]
17477struct SockAddrUn {
17478 sun_family: u16,
17479 sun_path: [core::ffi::c_char; 108],
17480}
17481
17482unsafe fn syslog_emit(priority: i32, msg: *const core::ffi::c_char, len: usize) {
17483 let mut out = [0u8; 1200];
17484 let mut o = 0usize;
17485 let pri = (SYSLOG_FACILITY | (priority & 7)) as u32;
17486 out[o] = b'<'; o += 1;
17487 if pri >= 100 { out[o] = b'0' + (pri / 100) as u8; o += 1; }
17488 if pri >= 10 { out[o] = b'0' + ((pri / 10) % 10) as u8; o += 1; }
17489 out[o] = b'0' + (pri % 10) as u8; o += 1;
17490 out[o] = b'>'; o += 1;
17491 let mut i = 0;
17492 while i < 63 && SYSLOG_IDENT[i] != 0 && o + 1 < out.len() {
17493 out[o] = SYSLOG_IDENT[i] as u8; o += 1; i += 1;
17494 }
17495 if SYSLOG_OPTIONS & 1 != 0 {
17496 out[o] = b'['; o += 1;
17497 let mut pid = crate::getpid() as u32;
17498 let mut digits = [0u8; 10];
17499 let mut d = 0;
17500 if pid == 0 { digits[0] = b'0'; d = 1; }
17501 while pid > 0 { digits[d] = b'0' + (pid % 10) as u8; pid /= 10; d += 1; }
17502 while d > 0 { d -= 1; out[o] = digits[d]; o += 1; }
17503 out[o] = b']'; o += 1;
17504 }
17505 out[o] = b':'; o += 1; out[o] = b' '; o += 1;
17506 let copy = core::cmp::min(len, out.len() - o - 1);
17507 core::ptr::copy_nonoverlapping(msg as *const u8, out.as_mut_ptr().add(o), copy);
17508 o += copy;
17509 let fd = crate::socket(AF_UNIX, SOCK_DGRAM, 0);
17510 if fd >= 0 {
17511 let mut sa: SockAddrUn = core::mem::zeroed();
17512 sa.sun_family = AF_UNIX as u16;
17513 let path = b"/dev/log";
17514 for i in 0..path.len() { sa.sun_path[i] = path[i] as core::ffi::c_char; }
17515 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);
17516 crate::close(fd);
17517 if r >= 0 { return; }
17518 }
17519 crate::write(2, out.as_ptr() as *const core::ffi::c_void, o);
17520 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
17521}
17522
17523#[no_mangle]
17524pub unsafe extern "C" fn vsyslog(priority: c_int, fmt: *const c_char, ap: VaList) {
17525 let mut msg = [0 as c_char; 1024];
17526 let n = vsnprintf(msg.as_mut_ptr(), msg.len(), fmt, ap);
17527 if n > 0 { syslog_emit(priority, msg.as_ptr(), core::cmp::min(n as usize, msg.len() - 1)); }
17528}
17529
17530#[no_mangle]
17531pub unsafe extern "C" fn syslog(priority: c_int, fmt: *const c_char, args: ...) {
17532 vsyslog(priority, fmt, args);
17533}
17534
17535#[no_mangle]
17536pub unsafe extern "C" fn closelog() {
17537 }
17539
17540#[no_mangle]
17541pub unsafe extern "C" fn setlogmask(mask: i32) -> i32 {
17542 static mut LOG_MASK: i32 = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80;
17543 let old = LOG_MASK;
17544 if mask != 0 { LOG_MASK = mask; }
17545 old
17546}
17547
17548#[no_mangle]
17549pub unsafe extern "C" fn acct(filename: *const core::ffi::c_char) -> i32 {
17550 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ACCT, filename as i64)) as i32
17551}
17552
17553#[no_mangle]
17554pub unsafe extern "C" fn swapon(path: *const core::ffi::c_char, flags: i32) -> i32 {
17555 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SWAPON, path as i64, flags as i64)) as i32
17556}
17557
17558#[no_mangle]
17559pub unsafe extern "C" fn swapoff(path: *const core::ffi::c_char) -> i32 {
17560 syscall_ret(<Arch as Syscalls>::syscall1(SYS_SWAPOFF, path as i64)) as i32
17561}
17562
17563#[no_mangle]
17564pub unsafe extern "C" fn syncfs(fd: i32) -> i32 {
17565 syscall_ret(<Arch as Syscalls>::syscall1(SYS_SYNCFS, fd as i64)) as i32
17566}
17567
17568#[no_mangle]
17569pub unsafe extern "C" fn sync_file_range(fd: i32, offset: i64, nbytes: u64, flags: u32) -> i32 {
17570 syscall_ret(<Arch as Syscalls>::syscall4(sysno(277, 84), fd as i64, offset, nbytes as i64, flags as i64)) as i32
17571}
17572
17573#[no_mangle]
17574pub unsafe extern "C" fn posix_fadvise(fd: i32, offset: i64, len: u64, advice: i32) -> i32 {
17575 let r = <Arch as Syscalls>::syscall4(sysno(221, 223), fd as i64, offset, len as i64, advice as i64);
17577 if r < 0 { (-r) as i32 } else { 0 }
17578}
17579
17580#[no_mangle]
17581pub unsafe extern "C" fn posix_fallocate(fd: i32, offset: i64, len: u64) -> i32 {
17582 let r = <Arch as Syscalls>::syscall3(SYS_FALLOCATE, fd as i64, offset, len as i64);
17583 if r < 0 { (-r) as i32 } else { 0 }
17584}
17585
17586#[no_mangle]
17587pub unsafe extern "C" fn readahead(fd: i32, offset: i64, count: usize) -> isize {
17588 syscall_ret(<Arch as Syscalls>::syscall3(sysno(187, 213), fd as i64, offset, count as i64)) as isize
17591}
17592
17593#[no_mangle]
17594pub unsafe extern "C" fn fallocate(fd: i32, mode: i32, offset: i64, len: u64) -> i32 {
17595 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FALLOCATE, fd as i64, mode as i64, offset, len as i64)) as i32
17596}
17597
17598#[no_mangle]
17603pub unsafe extern "C" fn tcgetattr(fd: i32, termios_p: *mut core::ffi::c_void) -> i32 {
17604 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5401, termios_p as i64)) as i32
17605}
17606
17607#[no_mangle]
17608pub unsafe extern "C" fn tcsetattr(fd: i32, optional_actions: i32, termios_p: *const core::ffi::c_void) -> i32 {
17609 let cmd = match optional_actions {
17610 0 => 0x5402,
17611 1 => 0x5403,
17612 2 => 0x5404,
17613 _ => 0x5402,
17614 };
17615 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, cmd, termios_p as i64)) as i32
17616}
17617
17618#[no_mangle]
17619pub unsafe extern "C" fn tcdrain(fd: i32) -> i32 {
17620 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5409, 1)) as i32
17621}
17622
17623#[no_mangle]
17624pub unsafe extern "C" fn tcflush(fd: i32, queue_selector: i32) -> i32 {
17625 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540B, queue_selector as i64)) as i32
17626}
17627
17628#[no_mangle]
17629pub unsafe extern "C" fn tcflow(fd: i32, action: i32) -> i32 {
17630 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540A, action as i64)) as i32
17631}
17632
17633#[no_mangle]
17634pub unsafe extern "C" fn tcsendbreak(fd: i32, duration: i32) -> i32 {
17635 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5425, duration as i64)) as i32
17636}
17637
17638#[no_mangle]
17639pub unsafe extern "C" fn tcgetsid(fd: i32) -> i32 {
17640 let mut sid: i32 = 0;
17641 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5429, &mut sid as *mut i32 as i64);
17642 if r < 0 { -1 } else { sid }
17643}
17644
17645#[no_mangle]
17646pub unsafe extern "C" fn tcgetpgrp(fd: i32) -> i32 {
17647 let mut pgrp: i32 = 0;
17648 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540F, &mut pgrp as *mut i32 as i64);
17649 if r < 0 { -1 } else { pgrp }
17650}
17651
17652#[no_mangle]
17653pub unsafe extern "C" fn tcsetpgrp(fd: i32, pgrp: i32) -> i32 {
17654 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5410, &pgrp as *const i32 as i64)) as i32
17655}
17656
17657#[no_mangle]
17668pub unsafe extern "C" fn mq_open(name: *const core::ffi::c_char, oflag: i32, mut args: ...) -> i32 {
17669 if name.is_null() { ERRNO!() = EINVAL; return -1; }
17670 let mut p = name as *const u8;
17671 if *p == b'/' { p = p.add(1); }
17672 let mut mode: u32 = 0;
17673 let mut attr: *const core::ffi::c_void = core::ptr::null();
17674 if oflag & 0o100 != 0 {
17675 mode = args.next_arg::<u32>();
17676 attr = args.next_arg::<*const core::ffi::c_void>();
17677 }
17678 syscall_ret(<Arch as Syscalls>::syscall4(
17679 sysno(240, 180),
17680 p as i64,
17681 oflag as i64,
17682 mode as i64,
17683 attr as i64,
17684 )) as i32
17685}
17686
17687#[no_mangle]
17688pub unsafe extern "C" fn mq_close(mqdes: i32) -> i32 {
17689 crate::close(mqdes as i32)
17690}
17691
17692#[no_mangle]
17693pub unsafe extern "C" fn mq_unlink(name: *const core::ffi::c_char) -> i32 {
17694 if name.is_null() { ERRNO!() = EINVAL; return -1; }
17695 let mut p = name as *const u8;
17696 if *p == b'/' { p = p.add(1); }
17697 let r = <Arch as Syscalls>::syscall1(sysno(241, 181), p as i64);
17698 if r < 0 {
17699 let e = if (-r) as c_int == 1 { 13 } else { (-r) as c_int };
17701 ERRNO!() = e;
17702 -1
17703 } else {
17704 0
17705 }
17706}
17707
17708#[no_mangle]
17709pub unsafe extern "C" fn mq_send(mqdes: i32, msg_ptr: *const core::ffi::c_char, msg_len: usize, msg_prio: u32) -> i32 {
17710 mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, core::ptr::null())
17711}
17712
17713#[no_mangle]
17714pub unsafe extern "C" fn mq_receive(mqdes: i32, msg_ptr: *mut core::ffi::c_char, msg_len: usize, msg_prio: *mut u32) -> isize {
17715 mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, core::ptr::null())
17716}
17717
17718#[no_mangle]
17719pub unsafe extern "C" fn mq_timedsend(
17720 mqdes: i32,
17721 msg_ptr: *const core::ffi::c_char,
17722 msg_len: usize,
17723 msg_prio: u32,
17724 abs_timeout: *const core::ffi::c_void,
17725) -> i32 {
17726 syscall_ret(<Arch as Syscalls>::syscall5(
17727 sysno(242, 182),
17728 mqdes as i64,
17729 msg_ptr as i64,
17730 msg_len as i64,
17731 msg_prio as i64,
17732 abs_timeout as i64,
17733 )) as i32
17734}
17735
17736#[no_mangle]
17737pub unsafe extern "C" fn mq_timedreceive(
17738 mqdes: i32,
17739 msg_ptr: *mut core::ffi::c_char,
17740 msg_len: usize,
17741 msg_prio: *mut u32,
17742 abs_timeout: *const core::ffi::c_void,
17743) -> isize {
17744 syscall_ret(<Arch as Syscalls>::syscall5(
17745 sysno(243, 183),
17746 mqdes as i64,
17747 msg_ptr as i64,
17748 msg_len as i64,
17749 msg_prio as i64,
17750 abs_timeout as i64,
17751 )) as isize
17752}
17753
17754#[repr(C)]
17755pub struct SigEventFull {
17756 sigev_value: usize,
17757 sigev_signo: i32,
17758 sigev_notify: i32,
17759 sigev_function: usize,
17760 sigev_attributes: usize,
17761 sigev_pad: [u8; 32],
17762}
17763
17764struct MqNotifyArgs {
17765 sem: sem_t,
17766 sock: i32,
17767 mqd: i32,
17768 err: i32,
17769 func: usize,
17770 value: usize,
17771}
17772
17773unsafe extern "C" fn mq_notify_thread(arg: *mut c_void) -> *mut c_void {
17774 let a = &mut *(arg as *mut MqNotifyArgs);
17775 let sock = a.sock;
17776 let mqd = a.mqd;
17777 let func = a.func;
17778 let value = a.value;
17779 let zeros = [0u8; 32];
17780 let sev2 = SigEventFull {
17781 sigev_value: zeros.as_ptr() as usize,
17782 sigev_signo: sock,
17783 sigev_notify: 2, sigev_function: 0,
17785 sigev_attributes: 0,
17786 sigev_pad: [0; 32],
17787 };
17788 let r = <Arch as Syscalls>::syscall2(sysno(244, 184), mqd as i64, &sev2 as *const SigEventFull as i64);
17789 a.err = if r < 0 { (-r) as i32 } else { 0 };
17790 sem_post(&mut a.sem);
17791 if a.err != 0 { return core::ptr::null_mut(); }
17792 pthread_detach(pthread_self());
17793 let mut buf = [0u8; 32];
17794 let n = recv(sock, buf.as_mut_ptr() as *mut c_void, buf.len(), 0x4000 | 0x100);
17795 crate::close(sock);
17796 if n as usize == buf.len() && buf[buf.len() - 1] == 1 && func != 0 {
17797 let f: extern "C" fn(usize) = core::mem::transmute(func);
17798 f(value);
17799 }
17800 core::ptr::null_mut()
17801}
17802
17803#[no_mangle]
17804pub unsafe extern "C" fn mq_notify(mqdes: i32, sev: *const core::ffi::c_void) -> i32 {
17805 if sev.is_null() {
17806 return syscall_ret(<Arch as Syscalls>::syscall2(sysno(244, 184), mqdes as i64, 0)) as i32;
17807 }
17808 let ev = &*(sev as *const SigEventFull);
17809 if ev.sigev_notify != 2 {
17810 return syscall_ret(<Arch as Syscalls>::syscall2(sysno(244, 184), mqdes as i64, sev as i64)) as i32;
17811 }
17812
17813 let sock = socket(16 , 3 | 0x80000 , 0);
17816 if sock < 0 { return -1; }
17817 let mut a = MqNotifyArgs {
17818 sem: core::mem::zeroed(),
17819 sock,
17820 mqd: mqdes,
17821 err: 0,
17822 func: ev.sigev_function,
17823 value: ev.sigev_value,
17824 };
17825 sem_init(&mut a.sem, 0, 0);
17826
17827 let mut attr: pthread_attr_t = core::mem::zeroed();
17828 if ev.sigev_attributes != 0 {
17829 attr = core::ptr::read(ev.sigev_attributes as *const pthread_attr_t);
17830 } else {
17831 pthread_attr_init(&mut attr);
17832 }
17833 pthread_attr_setdetachstate(&mut attr, PTHREAD_CREATE_JOINABLE);
17834
17835 let mut all: SigSetT = 0;
17836 sigfillset(&mut all);
17837 let mut orig: SigSetT = 0;
17838 pthread_sigmask(0 , &all, &mut orig);
17839
17840 let mut td: PthreadT = 0;
17841 let r = pthread_create(&mut td, &attr, mq_notify_thread as *const () as usize, &mut a as *mut MqNotifyArgs as *mut c_void);
17842 pthread_sigmask(2 , &orig, core::ptr::null_mut());
17843 if r != 0 {
17844 crate::close(sock);
17845 ERRNO!() = 11;
17846 return -1;
17847 }
17848 sem_wait(&mut a.sem);
17849 sem_destroy(&mut a.sem);
17850 if a.err != 0 {
17851 crate::close(sock);
17852 pthread_join(td, core::ptr::null_mut());
17853 ERRNO!() = a.err;
17854 return -1;
17855 }
17856 0
17857}
17858
17859#[no_mangle]
17860pub unsafe extern "C" fn mq_getattr(mqdes: i32, attr: *mut core::ffi::c_void) -> i32 {
17861 mq_setattr(mqdes, core::ptr::null(), attr)
17862}
17863
17864#[no_mangle]
17865pub unsafe extern "C" fn mq_setattr(
17866 mqdes: i32,
17867 new: *const core::ffi::c_void,
17868 old: *mut core::ffi::c_void,
17869) -> i32 {
17870 syscall_ret(<Arch as Syscalls>::syscall3(
17871 sysno(245, 185),
17872 mqdes as i64,
17873 new as i64,
17874 old as i64,
17875 )) as i32
17876}
17877
17878#[no_mangle]
17883pub unsafe extern "C" fn pthread_getaffinity_np(thread: usize, cpusetsize: usize, cpuset: *mut u8) -> i32 {
17884 sched_getaffinity(thread as i32, cpusetsize, cpuset)
17885}
17886
17887#[no_mangle]
17888pub unsafe extern "C" fn pthread_setaffinity_np(thread: usize, cpusetsize: usize, cpuset: *const u8) -> i32 {
17889 sched_setaffinity(thread as i32, cpusetsize, cpuset)
17890}
17891
17892#[no_mangle]
17897pub unsafe extern "C" fn sched_yield() -> i32 {
17898 syscall_ret(<Arch as Syscalls>::syscall0(sysno(24, 124))) as i32
17899}
17900
17901#[no_mangle]
17902pub unsafe extern "C" fn sched_get_priority_max(policy: i32) -> i32 {
17903 syscall_ret(<Arch as Syscalls>::syscall1(sysno(146, 125), policy as i64)) as i32
17904}
17905
17906#[no_mangle]
17907pub unsafe extern "C" fn sched_get_priority_min(policy: i32) -> i32 {
17908 syscall_ret(<Arch as Syscalls>::syscall1(sysno(147, 126), policy as i64)) as i32
17909}
17910
17911#[no_mangle]
17912pub unsafe extern "C" fn sched_getparam(pid: i32, param: *mut core::ffi::c_void) -> i32 {
17913 syscall_ret(<Arch as Syscalls>::syscall2(sysno(143, 121), pid as i64, param as i64)) as i32
17914}
17915
17916#[no_mangle]
17917pub unsafe extern "C" fn sched_setparam(pid: i32, param: *const core::ffi::c_void) -> i32 {
17918 syscall_ret(<Arch as Syscalls>::syscall2(sysno(142, 118), pid as i64, param as i64)) as i32
17919}
17920
17921#[no_mangle]
17922pub unsafe extern "C" fn sched_getscheduler(pid: i32) -> i32 {
17923 syscall_ret(<Arch as Syscalls>::syscall1(sysno(145, 120), pid as i64)) as i32
17924}
17925
17926#[no_mangle]
17927pub unsafe extern "C" fn sched_setscheduler(pid: i32, policy: i32, param: *const core::ffi::c_void) -> i32 {
17928 syscall_ret(<Arch as Syscalls>::syscall3(sysno(144, 119), pid as i64, policy as i64, param as i64)) as i32
17929}
17930
17931#[no_mangle]
17932pub unsafe extern "C" fn sched_setaffinity(pid: i32, cpusetsize: usize, cpuset: *const u8) -> i32 {
17933 syscall_ret(<Arch as Syscalls>::syscall3(sysno(203, 122), pid as i64, cpusetsize as i64, cpuset as i64)) as i32
17934}
17935
17936#[no_mangle]
17937pub unsafe extern "C" fn sched_getaffinity(pid: i32, cpusetsize: usize, cpuset: *mut u8) -> i32 {
17938 let r = <Arch as Syscalls>::syscall3(sysno(204, 123), pid as i64, cpusetsize as i64, cpuset as i64);
17939 if r < 0 {
17940 ERRNO!() = (-r) as c_int;
17941 return -1;
17942 }
17943 0
17945}
17946
17947#[no_mangle]
17948pub unsafe extern "C" fn sched_getcpu() -> i32 {
17949 let mut cpu: i32 = 0;
17950 <Arch as Syscalls>::syscall3(sysno(309, 168), &mut cpu as *mut i32 as i64, 0, 0);
17951 cpu
17952}
17953
17954#[no_mangle]
17955pub unsafe extern "C" fn sched_rr_get_interval(pid: i32, tp: *mut core::ffi::c_void) -> i32 {
17956 syscall_ret(<Arch as Syscalls>::syscall2(sysno(148, 127), pid as i64, tp as i64)) as i32
17957}
17958
17959#[no_mangle]
17964pub unsafe extern "C" fn timer_create(clockid: i32, sevp: *mut core::ffi::c_void, timerid: *mut i32) -> i32 {
17965 syscall_ret(<Arch as Syscalls>::syscall3(sysno(222, 107), clockid as i64, sevp as i64, timerid as i64)) as i32
17966}
17967
17968#[no_mangle]
17969pub unsafe extern "C" fn timer_delete(timerid: i32) -> i32 {
17970 syscall_ret(<Arch as Syscalls>::syscall1(sysno(226, 111), timerid as i64)) as i32
17971}
17972
17973#[no_mangle]
17974pub 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 {
17975 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
17976}
17977
17978#[no_mangle]
17979pub unsafe extern "C" fn timer_gettime(timerid: i32, curr_value: *mut core::ffi::c_void) -> i32 {
17980 syscall_ret(<Arch as Syscalls>::syscall2(sysno(224, 108), timerid as i64, curr_value as i64)) as i32
17981}
17982
17983#[no_mangle]
17984pub unsafe extern "C" fn timer_getoverrun(timerid: i32) -> i32 {
17985 syscall_ret(<Arch as Syscalls>::syscall1(sysno(225, 109), timerid as i64)) as i32
17986}
17987
17988#[no_mangle]
17989pub unsafe extern "C" fn clock_adjtime(_clockid: i32, buf: *mut core::ffi::c_void) -> i32 {
17990 syscall_ret(<Arch as Syscalls>::syscall2(SYS_ADJTIMEX, buf as i64, 0)) as i32
17991}
17992
17993#[no_mangle]
17994pub unsafe extern "C" fn clock_getcpuclockid(pid: i32, clockid: *mut i32) -> i32 {
17995 if clockid.is_null() { return EINVAL; }
17996 let id: i32 = ((-(pid as i64) - 1) * 8 + 2) as i32;
17997 let mut ts: timespec = core::mem::zeroed();
17998 let r = <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, id as i64, &mut ts as *mut timespec as i64);
17999 if r < 0 {
18000 let e = (-r) as c_int;
18001 return if e == EINVAL { 3 } else { e };
18002 }
18003 *clockid = id;
18004 0
18005}
18006
18007#[no_mangle]
18012pub unsafe extern "C" fn strcoll(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char) -> i32 {
18013 let mut i = 0;
18015 loop {
18016 let c1 = *s1.add(i) as u8;
18017 let c2 = *s2.add(i) as u8;
18018 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
18019 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
18020 i += 1;
18021 }
18022}
18023
18024#[no_mangle]
18025pub unsafe extern "C" fn strxfrm(dest: *mut core::ffi::c_char, src: *const core::ffi::c_char, n: usize) -> usize {
18026 let mut i = 0;
18027 while i < n {
18028 let c = *src.add(i);
18029 *dest.add(i) = c;
18030 if c == 0 { break; }
18031 i += 1;
18032 }
18033 i
18034}
18035
18036#[no_mangle]
18041pub 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 {
18042 let dir = opendir(dirp);
18043 if dir.is_null() { return -1; }
18044 let mut count = 0;
18045 loop {
18046 let ent = readdir(dir);
18047 if ent.is_null() { break; }
18048 count += 1;
18049 }
18050 closedir(dir);
18051 count
18052}
18053
18054#[no_mangle]
18055pub unsafe extern "C" fn alphasort(a: *const *const core::ffi::c_void, b: *const *const core::ffi::c_void) -> i32 {
18056 let s1 = *a as *const core::ffi::c_char;
18057 let s2 = *b as *const core::ffi::c_char;
18058 crate::strcmp(s1 as *const u8, s2 as *const u8)
18059}
18060
18061#[no_mangle]
18062pub unsafe extern "C" fn versionsort(a: *const *const core::ffi::c_void, b: *const *const core::ffi::c_void) -> i32 {
18063 let s1 = *a as *const core::ffi::c_char;
18064 let s2 = *b as *const core::ffi::c_char;
18065 crate::strcmp(s1 as *const u8, s2 as *const u8)
18066}
18067
18068unsafe fn vwarn_impl(fmt: *const c_char, ap: VaList, with_errno: bool) {
18076 let mut buf = [0 as c_char; 1024];
18077 let n = vsnprintf(buf.as_mut_ptr(), buf.len(), fmt, ap);
18078 if n > 0 {
18079 let l = core::cmp::min(n as usize, buf.len() - 1);
18080 crate::write(2, buf.as_ptr() as *const c_void, l);
18081 }
18082 if with_errno {
18083 let e = ERRNO!();
18084 crate::write(2, b": ".as_ptr() as *const c_void, 2);
18085 let msg = strerror(e);
18086 crate::write(2, msg as *const c_void, crate::strlen(msg));
18087 }
18088 crate::write(2, b"\n".as_ptr() as *const c_void, 1);
18089}
18090
18091#[no_mangle]
18092pub unsafe extern "C" fn verr(eval: c_int, fmt: *const c_char, ap: VaList) {
18093 vwarn_impl(fmt, ap, true);
18094 crate::exit(eval);
18095}
18096
18097#[no_mangle]
18098pub unsafe extern "C" fn verrx(eval: c_int, fmt: *const c_char, ap: VaList) {
18099 vwarn_impl(fmt, ap, false);
18100 crate::exit(eval);
18101}
18102
18103#[no_mangle]
18104pub unsafe extern "C" fn vwarn(fmt: *const c_char, ap: VaList) {
18105 vwarn_impl(fmt, ap, true);
18106}
18107
18108#[no_mangle]
18109pub unsafe extern "C" fn vwarnx(fmt: *const c_char, ap: VaList) {
18110 vwarn_impl(fmt, ap, false);
18111}
18112
18113#[no_mangle]
18114pub unsafe extern "C" fn err(eval: c_int, fmt: *const c_char, args: ...) {
18115 verr(eval, fmt, args);
18116}
18117
18118#[no_mangle]
18119pub unsafe extern "C" fn errx(eval: c_int, fmt: *const c_char, args: ...) {
18120 verrx(eval, fmt, args);
18121}
18122
18123#[no_mangle]
18124pub unsafe extern "C" fn warn(fmt: *const c_char, args: ...) {
18125 vwarn(fmt, args);
18126}
18127
18128#[no_mangle]
18129pub unsafe extern "C" fn warnx(fmt: *const c_char, args: ...) {
18130 vwarnx(fmt, args);
18131}
18132
18133#[no_mangle]
18138pub unsafe extern "C" fn ecvt(value: f64, ndigit: i32, decpt: *mut i32, sign: *mut i32) -> *mut core::ffi::c_char {
18139 static mut BUF: [core::ffi::c_char; 80] = [0; 80];
18140 if value < 0.0 { *sign = 1; } else { *sign = 0; }
18141 let v = if value < 0.0 { -value } else { value };
18142 if v == 0.0 { *decpt = 0; BUF[0] = 0; return BUF.as_mut_ptr(); }
18143 let mut d = 0i32;
18144 let mut tmp = v;
18145 while tmp >= 10.0 { tmp /= 10.0; d += 1; }
18146 while tmp < 1.0 { tmp *= 10.0; d -= 1; }
18147 *decpt = d + 1;
18148 let mut i = 0;
18149 let mut val = tmp;
18150 while i < ndigit as usize && i < 79 {
18151 let digit = val as i32;
18152 BUF[i] = (b'0' + digit as u8) as c_char;
18153 val = (val - digit as f64) * 10.0;
18154 i += 1;
18155 }
18156 BUF[i] = 0;
18157 BUF.as_mut_ptr()
18158}
18159
18160#[no_mangle]
18161pub unsafe extern "C" fn fcvt(value: f64, ndigit: i32, decpt: *mut i32, sign: *mut i32) -> *mut core::ffi::c_char {
18162 static mut BUF: [core::ffi::c_char; 80] = [0; 80];
18163 if value < 0.0 { *sign = 1; } else { *sign = 0; }
18164 let v = if value < 0.0 { -value } else { value };
18165 if v == 0.0 { *decpt = 0; BUF[0] = 0; return BUF.as_mut_ptr(); }
18166 let mut d = 0i32;
18167 let mut tmp = v;
18168 while tmp >= 10.0 { tmp /= 10.0; d += 1; }
18169 while tmp < 1.0 { tmp *= 10.0; d -= 1; }
18170 *decpt = d + 1;
18171 let mut val = tmp;
18172 let mut i = 0;
18173 while i < (*decpt) as usize && i < 79 {
18174 let digit = val as i32;
18175 BUF[i] = (b'0' + digit as u8) as c_char;
18176 val = (val - digit as f64) * 10.0;
18177 i += 1;
18178 }
18179 if ndigit > 0 && i < 79 {
18180 BUF[i] = '.' as c_char;
18181 i += 1;
18182 let mut frac = val;
18183 let mut j = 0;
18184 while j < ndigit as usize && i < 79 {
18185 let digit = frac as i32;
18186 BUF[i] = (b'0' + digit as u8) as c_char;
18187 frac = (frac - digit as f64) * 10.0;
18188 i += 1;
18189 j += 1;
18190 }
18191 }
18192 BUF[i] = 0;
18193 BUF.as_mut_ptr()
18194}
18195
18196#[no_mangle]
18197pub unsafe extern "C" fn gcvt(value: f64, _ndigit: i32, buf: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
18198 if value == 0.0 {
18200 *buf = '0' as c_char;
18201 *buf.add(1) = 0;
18202 return buf;
18203 }
18204 let mut i = 0;
18205 let v = if value < 0.0 { *buf = '-' as c_char; i = 1; -value } else { value };
18206 let mut int_part = v as i64;
18208 let mut digits = [0u8; 32];
18209 let mut di = 0;
18210 if int_part == 0 {
18211 digits[0] = 0;
18212 di = 1;
18213 } else {
18214 while int_part > 0 && di < 32 {
18215 digits[di] = (int_part % 10) as u8;
18216 int_part /= 10;
18217 di += 1;
18218 }
18219 }
18220 while di > 0 && i < 79 {
18221 di -= 1;
18222 *buf.add(i) = (b'0' + digits[di]) as c_char;
18223 i += 1;
18224 }
18225 *buf.add(i) = 0;
18226 buf
18227}
18228
18229static mut SHELLS: [*const core::ffi::c_char; 3] = [
18234 b"/bin/sh\0".as_ptr() as *const core::ffi::c_char,
18235 b"/bin/bash\0".as_ptr() as *const core::ffi::c_char,
18236 core::ptr::null(),
18237];
18238static mut SHELL_IDX: usize = 0;
18239
18240#[no_mangle]
18241pub unsafe extern "C" fn getusershell() -> *mut core::ffi::c_char {
18242 let s = SHELLS[SHELL_IDX];
18243 if s.is_null() {
18244 SHELL_IDX = 0;
18245 return core::ptr::null_mut();
18246 }
18247 SHELL_IDX += 1;
18248 s as *mut core::ffi::c_char
18249}
18250
18251#[no_mangle]
18252pub unsafe extern "C" fn setusershell() {
18253 SHELL_IDX = 0;
18254}
18255
18256#[no_mangle]
18257pub unsafe extern "C" fn endusershell() {
18258 SHELL_IDX = 0;
18259}
18260
18261#[no_mangle]
18266pub unsafe extern "C" fn ether_aton(s: *const core::ffi::c_char) -> *mut u8 {
18267 static mut EA: [u8; 6] = [0; 6];
18268 if ether_aton_r(s, EA.as_mut_ptr()).is_null() { core::ptr::null_mut() } else { EA.as_mut_ptr() }
18269}
18270
18271#[no_mangle]
18272pub unsafe extern "C" fn ether_aton_r(s: *const core::ffi::c_char, ea: *mut u8) -> *mut u8 {
18273 if ea.is_null() { return core::ptr::null_mut(); }
18274 let mut i = 0;
18275 let mut j = 0;
18276 let mut val: u32 = 0;
18277 let mut digits = 0;
18278 while *s.add(i) != 0 && j < 6 {
18279 let c = *s.add(i);
18280 if c == ':' as c_char {
18281 if digits == 0 { return core::ptr::null_mut(); }
18282 *ea.add(j) = val as u8;
18283 j += 1;
18284 val = 0;
18285 digits = 0;
18286 } 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) {
18287 let d = if c >= '0' as c_char && c <= '9' as c_char { (c - '0' as c_char) as u32 }
18288 else if c >= 'a' as c_char { (c - 'a' as c_char + 10) as u32 }
18289 else { (c - 'A' as c_char + 10) as u32 };
18290 val = val * 16 + d;
18291 if val > 255 { return core::ptr::null_mut(); }
18292 digits += 1;
18293 if digits > 2 { return core::ptr::null_mut(); }
18294 } else {
18295 return core::ptr::null_mut();
18296 }
18297 i += 1;
18298 }
18299 if digits == 0 || j != 5 { return core::ptr::null_mut(); }
18300 *ea.add(j) = val as u8;
18301 ea
18302}
18303
18304#[no_mangle]
18305pub unsafe extern "C" fn ether_ntoa(ea: *const u8) -> *mut core::ffi::c_char {
18306 static mut BUF: [core::ffi::c_char; 18] = [0; 18];
18307 ether_ntoa_r(ea, BUF.as_mut_ptr());
18308 BUF.as_mut_ptr()
18309}
18310
18311#[no_mangle]
18312pub unsafe extern "C" fn ether_ntoa_r(ea: *const u8, buf: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
18313 let a = *ea.add(0); let b = *ea.add(1); let c = *ea.add(2);
18314 let d = *ea.add(3); let e = *ea.add(4); let f = *ea.add(5);
18315 let hex = b"0123456789abcdef\0".as_ptr() as *const u8;
18316 let mut i = 0;
18317 *buf.add(i) = *hex.add((a >> 4) as usize) as c_char; i += 1;
18318 *buf.add(i) = *hex.add((a & 0xf) as usize) as c_char; i += 1;
18319 *buf.add(i) = ':' as c_char; i += 1;
18320 *buf.add(i) = *hex.add((b >> 4) as usize) as c_char; i += 1;
18321 *buf.add(i) = *hex.add((b & 0xf) as usize) as c_char; i += 1;
18322 *buf.add(i) = ':' as c_char; i += 1;
18323 *buf.add(i) = *hex.add((c >> 4) as usize) as c_char; i += 1;
18324 *buf.add(i) = *hex.add((c & 0xf) as usize) as c_char; i += 1;
18325 *buf.add(i) = ':' as c_char; i += 1;
18326 *buf.add(i) = *hex.add((d >> 4) as usize) as c_char; i += 1;
18327 *buf.add(i) = *hex.add((d & 0xf) as usize) as c_char; i += 1;
18328 *buf.add(i) = ':' as c_char; i += 1;
18329 *buf.add(i) = *hex.add((e >> 4) as usize) as c_char; i += 1;
18330 *buf.add(i) = *hex.add((e & 0xf) as usize) as c_char; i += 1;
18331 *buf.add(i) = ':' as c_char; i += 1;
18332 *buf.add(i) = *hex.add((f >> 4) as usize) as c_char; i += 1;
18333 *buf.add(i) = *hex.add((f & 0xf) as usize) as c_char; i += 1;
18334 *buf.add(i) = 0;
18335 buf
18336}
18337
18338#[no_mangle]
18343pub unsafe extern "C" fn getutxent() -> *mut core::ffi::c_void {
18344 getutent()
18345}
18346
18347#[no_mangle]
18348pub unsafe extern "C" fn getutxid(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
18349 getutid(ut)
18350}
18351
18352#[no_mangle]
18353pub unsafe extern "C" fn getutxline(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
18354 getutline(ut)
18355}
18356
18357#[no_mangle]
18358pub unsafe extern "C" fn pututxline(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
18359 pututline(ut)
18360}
18361
18362#[no_mangle]
18363pub unsafe extern "C" fn setutxent() {
18364 setutent()
18365}
18366
18367#[no_mangle]
18368pub unsafe extern "C" fn endutxent() {
18369 endutent()
18370}
18371
18372#[no_mangle]
18377pub unsafe extern "C" fn execv(path: *const core::ffi::c_char, argv: *const *const core::ffi::c_char) -> i32 {
18378 crate::execve(path, argv, __environ as *const *const core::ffi::c_char)
18379}
18380
18381#[no_mangle]
18382pub unsafe extern "C" fn execlp(file: *const core::ffi::c_char, _args: ...) -> i32 {
18383 let mut argv: [*const core::ffi::c_char; 64] = [core::ptr::null(); 64];
18385 let mut i = 0;
18386 let mut args = _args;
18387 loop {
18388 let arg = args.next_arg::<*const core::ffi::c_char>();
18389 if arg.is_null() { break; }
18390 argv[i] = arg;
18391 i += 1;
18392 if i >= 63 { break; }
18393 }
18394 argv[i] = core::ptr::null();
18395 execvp(file, argv.as_ptr())
18396}
18397
18398#[no_mangle]
18399pub unsafe extern "C" fn execvp(file: *const core::ffi::c_char, argv: *const *const core::ffi::c_char) -> i32 {
18400 execvpe(file, argv, __environ as *const *const core::ffi::c_char)
18401}
18402
18403#[no_mangle]
18404pub unsafe extern "C" fn fexecve(fd: i32, argv: *const *const core::ffi::c_char, envp: *const *const core::ffi::c_char) -> i32 {
18405 let mut path: [core::ffi::c_char; 64] = [0; 64];
18407 let mut i = 0;
18408 let src = b"/proc/self/fd/\0".as_ptr() as *const core::ffi::c_char;
18409 while i < 63 && *src.add(i) != 0 { path[i] = *src.add(i); i += 1; }
18410 let mut n = fd as usize;
18411 if n == 0 { path[i] = '0' as c_char; i += 1; }
18412 while n > 0 && i < 63 {
18413 path[i] = (b'0' + (n % 10) as u8) as c_char;
18414 n /= 10;
18415 i += 1;
18416 }
18417 path[i] = 0;
18418 crate::execve(path.as_ptr(), argv, envp)
18419}
18420
18421#[no_mangle]
18426pub unsafe extern "C" fn confstr(name: i32, buf: *mut core::ffi::c_char, len: usize) -> usize {
18427 let value: &[u8] = if name == 0 {
18430 b"/bin:/usr/bin"
18431 } else if (1..=37).contains(&name) {
18432 b""
18433 } else {
18434 ERRNO!() = EINVAL;
18435 return 0;
18436 };
18437 let need = value.len() + 1;
18438 if !buf.is_null() && len > 0 {
18439 let n = core::cmp::min(value.len(), len - 1);
18440 core::ptr::copy_nonoverlapping(value.as_ptr(), buf as *mut u8, n);
18441 *buf.add(n) = 0;
18442 }
18443 need
18444}
18445
18446#[no_mangle]
18447pub unsafe extern "C" fn pathconf(_path: *const core::ffi::c_char, name: i32) -> i64 {
18448 match name {
18450 0 => 4096, 1 => 255, 2 => 255, 3 => 255, 4 => 4096, 5 => 4096, 6 => 1, 7 => 0, 8 => 0, _ => -1,
18460 }
18461}
18462
18463#[no_mangle]
18464pub unsafe extern "C" fn fpathconf(_fd: i32, name: i32) -> i64 {
18465 match name {
18467 0 => 4096, 1 => 255, 2 => 255, 3 => 255, 4 => 4096, 5 => 4096, 6 => 1, 7 => 0, 8 => 0, _ => -1,
18477 }
18478}
18479
18480#[no_mangle]
18485pub unsafe extern "C" fn exp10(x: f64) -> f64 {
18486 libm::pow(10.0, x)
18487}
18488
18489#[no_mangle]
18490pub unsafe extern "C" fn exp10f(x: f32) -> f32 {
18491 libm::powf(10.0, x)
18492}
18493
18494#[no_mangle]
18499pub unsafe extern "C" fn explicit_bzero(s: *mut u8, n: usize) {
18500 core::ptr::write_bytes(s, 0, n);
18501 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
18502}
18503
18504#[no_mangle]
18505pub unsafe extern "C" fn memccpy(dest: *mut u8, src: *const u8, c: i32, n: usize) -> *mut u8 {
18506 let mut i = 0;
18507 while i < n {
18508 let byte = *src.add(i);
18509 *dest.add(i) = byte;
18510 if byte == c as u8 {
18511 return dest.add(i + 1);
18512 }
18513 i += 1;
18514 }
18515 core::ptr::null_mut()
18516}
18517
18518#[no_mangle]
18523pub unsafe extern "C" fn faccessat(dirfd: i32, pathname: *const core::ffi::c_char, mode: i32, flags: i32) -> i32 {
18524 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FACCESSAT, dirfd as i64, pathname as i64, mode as i64, flags as i64)) as i32
18525}
18526
18527#[no_mangle]
18528pub unsafe extern "C" fn fchmodat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32, flags: i32) -> i32 {
18529 if flags == 0 {
18530 return syscall_ret(<Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, pathname as i64, mode as i64, 0)) as i32;
18531 }
18532 if flags != 0x100 {
18533 ERRNO!() = EINVAL;
18535 return -1;
18536 }
18537 syscall_ret(<Arch as Syscalls>::syscall4(sysno(452, 452), dirfd as i64, pathname as i64, mode as i64, flags as i64)) as i32
18538}
18539
18540#[no_mangle]
18541pub unsafe extern "C" fn fchownat(dirfd: i32, pathname: *const core::ffi::c_char, uid: u32, gid: u32, flags: i32) -> i32 {
18542 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
18543}
18544
18545#[no_mangle]
18546pub unsafe extern "C" fn linkat(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char, flags: i32) -> i32 {
18547 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
18548}
18549
18550#[no_mangle]
18551pub unsafe extern "C" fn mkdirat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18552 syscall_ret(<Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, pathname as i64, mode as i64)) as i32
18553}
18554
18555#[no_mangle]
18556pub unsafe extern "C" fn mkfifoat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18557 mknodat(dirfd, pathname, mode | 0o010000, 0)
18558}
18559
18560#[no_mangle]
18561pub unsafe extern "C" fn mknodat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32, dev: u64) -> i32 {
18562 syscall_ret(<Arch as Syscalls>::syscall4(sysno(259, 33), dirfd as i64, pathname as i64, mode as i64, dev as i64)) as i32
18563}
18564
18565#[no_mangle]
18566pub unsafe extern "C" fn readlinkat(dirfd: i32, pathname: *const core::ffi::c_char, buf: *mut core::ffi::c_char, bufsiz: usize) -> isize {
18567 syscall_ret(<Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, pathname as i64, buf as i64, bufsiz as i64)) as isize
18568}
18569
18570#[no_mangle]
18571pub unsafe extern "C" fn renameat(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char) -> i32 {
18572 syscall_ret(<Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, 0)) as i32
18573}
18574
18575#[no_mangle]
18576pub unsafe extern "C" fn renameat2(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char, flags: u32) -> i32 {
18577 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
18578}
18579
18580#[no_mangle]
18581pub unsafe extern "C" fn symlinkat(target: *const core::ffi::c_char, newdirfd: i32, linkpath: *const core::ffi::c_char) -> i32 {
18582 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64)) as i32
18583}
18584
18585#[no_mangle]
18586pub unsafe extern "C" fn unlinkat(dirfd: i32, pathname: *const core::ffi::c_char, flags: i32) -> i32 {
18587 syscall_ret(<Arch as Syscalls>::syscall3(SYS_UNLINKAT, dirfd as i64, pathname as i64, flags as i64)) as i32
18588}
18589
18590#[no_mangle]
18591pub unsafe extern "C" fn utimes(filename: *const core::ffi::c_char, times: *const core::ffi::c_void) -> i32 {
18592 utimensat(AT_FDCWD, filename, times as *const timespec, 0)
18593}
18594
18595#[no_mangle]
18596pub unsafe extern "C" fn futimes(fd: i32, times: *const core::ffi::c_void) -> i32 {
18597 utimensat(fd, core::ptr::null(), times as *const timespec, 0)
18598}
18599
18600#[no_mangle]
18605pub unsafe extern "C" fn inotify_init() -> i32 {
18606 syscall_ret(<Arch as Syscalls>::syscall1(sysno(253, 26), 0)) as i32
18607}
18608
18609#[no_mangle]
18610pub unsafe extern "C" fn inotify_init1(flags: i32) -> i32 {
18611 syscall_ret(<Arch as Syscalls>::syscall1(sysno(294, 26), flags as i64)) as i32
18612}
18613
18614#[no_mangle]
18615pub unsafe extern "C" fn inotify_add_watch(fd: i32, pathname: *const core::ffi::c_char, mask: u32) -> i32 {
18616 syscall_ret(<Arch as Syscalls>::syscall3(sysno(254, 27), fd as i64, pathname as i64, mask as i64)) as i32
18617}
18618
18619#[no_mangle]
18620pub unsafe extern "C" fn inotify_rm_watch(fd: i32, wd: i32) -> i32 {
18621 syscall_ret(<Arch as Syscalls>::syscall2(sysno(255, 28), fd as i64, wd as i64)) as i32
18622}
18623
18624#[no_mangle]
18625pub unsafe extern "C" fn fanotify_init(flags: i32, event_f_flags: i32) -> i32 {
18626 syscall_ret(<Arch as Syscalls>::syscall2(sysno(300, 262), flags as i64, event_f_flags as i64)) as i32
18627}
18628
18629#[no_mangle]
18630pub unsafe extern "C" fn fanotify_mark(fd: i32, flags: i32, mask: u64, dirfd: i32, pathname: *const core::ffi::c_char) -> i32 {
18631 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
18632}
18633
18634#[no_mangle]
18639pub unsafe extern "C" fn ffs(x: i32) -> i32 {
18640 if x == 0 { return 0; }
18641 x.trailing_zeros() as i32 + 1
18642}
18643
18644#[no_mangle]
18645pub unsafe extern "C" fn ffsl(x: i64) -> i32 {
18646 if x == 0 { return 0; }
18647 x.trailing_zeros() as i32 + 1
18648}
18649
18650#[no_mangle]
18651pub unsafe extern "C" fn ffsll(x: i64) -> i32 {
18652 if x == 0 { return 0; }
18653 x.trailing_zeros() as i32 + 1
18654}
18655
18656#[no_mangle]
18661pub unsafe extern "C" fn fchdir(fd: i32) -> i32 {
18662 syscall_ret(<Arch as Syscalls>::syscall1(SYS_FCHDIR, fd as i64)) as i32
18663}
18664
18665#[no_mangle]
18666pub unsafe extern "C" fn fchown(fd: i32, uid: u32, gid: u32) -> i32 {
18667 syscall_ret(<Arch as Syscalls>::syscall3(SYS_FCHOWN, fd as i64, uid as i64, gid as i64)) as i32
18668}
18669
18670#[no_mangle]
18671pub unsafe extern "C" fn fdopendir(fd: i32) -> *mut core::ffi::c_void {
18672 if fd < 0 { ERRNO!() = 9; return core::ptr::null_mut(); }
18673 dir_stream_new(fd)
18674}
18675
18676#[no_mangle]
18677pub unsafe extern "C" fn getdtablesize() -> i32 {
18678 let mut rlim: Rlimit = core::mem::zeroed();
18679 if getrlimit(RLIMIT_NOFILE, &mut rlim) == 0 {
18680 rlim.rlim_cur as i32
18681 } else {
18682 1024
18683 }
18684}
18685
18686#[no_mangle]
18687pub unsafe extern "C" fn getentropy(buf: *mut u8, buflen: usize) -> i32 {
18688 if buflen > 256 {
18689 ERRNO!() = EIO_VAL;
18690 return -1;
18691 }
18692 let mut pos = buf;
18693 let mut left = buflen;
18694 while left > 0 {
18695 let r = getrandom(pos, left, 0);
18696 if r < 0 {
18697 if ERRNO!() == EINTR_VAL {
18698 continue;
18699 }
18700 return -1;
18701 }
18702 pos = pos.add(r as usize);
18703 left -= r as usize;
18704 }
18705 0
18706}
18707
18708#[no_mangle]
18709pub unsafe extern "C" fn getrandom(buf: *mut u8, buflen: usize, flags: u32) -> isize {
18710 let r = <Arch as Syscalls>::syscall3(sysno(318, 278), buf as i64, buflen as i64, flags as i64);
18711 if r < 0 {
18712 ERRNO!() = (-r) as c_int;
18713 -1
18714 } else {
18715 r as isize
18716 }
18717}
18718
18719#[no_mangle]
18720pub unsafe extern "C" fn killpg(pgrp: i32, sig: i32) -> i32 {
18721 syscall_ret(<Arch as Syscalls>::syscall2(SYS_KILL, -pgrp as i64, sig as i64)) as i32
18722}
18723
18724#[no_mangle]
18725pub unsafe extern "C" fn mkfifo(pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18726 mknod(pathname, 0o010000 | mode, 0)
18727}
18728
18729#[no_mangle]
18734pub unsafe extern "C" fn aligned_alloc(alignment: usize, size: usize) -> *mut core::ffi::c_void {
18735 alloc_aligned_impl(alignment, size) as *mut core::ffi::c_void
18736}
18737
18738#[no_mangle]
18739pub unsafe extern "C" fn memalign(alignment: usize, size: usize) -> *mut core::ffi::c_void {
18740 alloc_aligned_impl(alignment, size) as *mut core::ffi::c_void
18741}
18742
18743#[no_mangle]
18744pub unsafe extern "C" fn posix_memalign(memptr: *mut *mut core::ffi::c_void, alignment: usize, size: usize) -> i32 {
18745 if memptr.is_null() { return EINVAL; }
18746 if alignment < core::mem::size_of::<*mut core::ffi::c_void>() || !alignment.is_power_of_two() {
18747 return EINVAL;
18748 }
18749 let p = alloc_aligned_impl(alignment, size);
18750 if p.is_null() { return ENOMEM; }
18751 *memptr = p as *mut core::ffi::c_void;
18752 0
18753}
18754
18755#[no_mangle]
18756pub unsafe extern "C" fn valloc(size: usize) -> *mut core::ffi::c_void {
18757 alloc_aligned_impl(PAGE, size) as *mut core::ffi::c_void
18758}
18759
18760#[no_mangle]
18773pub unsafe extern "C" fn gettext(msgid: *const core::ffi::c_char) -> *const core::ffi::c_char {
18774 msgid
18775}
18776
18777#[no_mangle]
18778pub unsafe extern "C" fn dgettext(_domainname: *const core::ffi::c_char, msgid: *const core::ffi::c_char) -> *const core::ffi::c_char {
18779 msgid
18780}
18781
18782#[no_mangle]
18783pub unsafe extern "C" fn dcgettext(_domainname: *const core::ffi::c_char, msgid: *const core::ffi::c_char, _category: i32) -> *const core::ffi::c_char {
18784 msgid
18785}
18786
18787#[no_mangle]
18788pub unsafe extern "C" fn ngettext(msgid1: *const core::ffi::c_char, msgid2: *const core::ffi::c_char, n: u64) -> *const core::ffi::c_char {
18789 if n == 1 { msgid1 } else { msgid2 }
18790}
18791
18792#[no_mangle]
18793pub 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 {
18794 if n == 1 { msgid1 } else { msgid2 }
18795}
18796
18797#[no_mangle]
18798pub 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 {
18799 if n == 1 { msgid1 } else { msgid2 }
18800}
18801
18802#[no_mangle]
18803pub unsafe extern "C" fn textdomain(domainname: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18804 static mut DOMAIN: [core::ffi::c_char; 256] = [0; 256];
18805 if domainname.is_null() { return DOMAIN.as_mut_ptr(); }
18806 let mut i = 0;
18807 while i < 255 && *domainname.add(i) != 0 {
18808 DOMAIN[i] = *domainname.add(i);
18809 i += 1;
18810 }
18811 DOMAIN[i] = 0;
18812 DOMAIN.as_mut_ptr()
18813}
18814
18815#[no_mangle]
18816pub unsafe extern "C" fn bindtextdomain(_domainname: *const core::ffi::c_char, dirname: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18817 dirname as *mut core::ffi::c_char
18818}
18819
18820#[no_mangle]
18821pub unsafe extern "C" fn bind_textdomain_codeset(_domainname: *const core::ffi::c_char, codeset: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18822 codeset as *mut core::ffi::c_char
18823}
18824
18825#[no_mangle]
18830pub unsafe extern "C" fn wmemcpy(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18831 let mut i = 0;
18832 while i < n {
18833 *dest.add(i) = *src.add(i);
18834 i += 1;
18835 }
18836 dest
18837}
18838
18839#[no_mangle]
18840pub unsafe extern "C" fn wmemmove(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18841 if dest as usize <= src as usize {
18842 let mut i = 0;
18843 while i < n {
18844 *dest.add(i) = *src.add(i);
18845 i += 1;
18846 }
18847 } else {
18848 let mut i = n;
18849 while i > 0 {
18850 i -= 1;
18851 *dest.add(i) = *src.add(i);
18852 }
18853 }
18854 dest
18855}
18856
18857#[no_mangle]
18858pub unsafe extern "C" fn wmemset(dest: *mut u32, c: u32, n: usize) -> *mut u32 {
18859 let mut i = 0;
18860 while i < n {
18861 *dest.add(i) = c;
18862 i += 1;
18863 }
18864 dest
18865}
18866
18867#[no_mangle]
18868pub unsafe extern "C" fn wmemcmp(s1: *const u32, s2: *const u32, n: usize) -> i32 {
18869 let mut i = 0;
18870 while i < n {
18871 let c1 = *s1.add(i);
18872 let c2 = *s2.add(i);
18873 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
18874 i += 1;
18875 }
18876 0
18877}
18878
18879#[no_mangle]
18880pub unsafe extern "C" fn wmemchr(s: *const u32, c: u32, n: usize) -> *mut u32 {
18881 let mut i = 0;
18882 while i < n {
18883 if *s.add(i) == c { return s.add(i) as *mut u32; }
18884 i += 1;
18885 }
18886 core::ptr::null_mut()
18887}
18888
18889#[no_mangle]
18890pub unsafe extern "C" fn wcpcpy(dest: *mut u32, src: *const u32) -> *mut u32 {
18891 let mut i = 0;
18892 loop {
18893 let c = *src.add(i);
18894 *dest.add(i) = c;
18895 if c == 0 { return dest.add(i); }
18896 i += 1;
18897 }
18898}
18899
18900#[no_mangle]
18901pub unsafe extern "C" fn wcpncpy(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18902 let mut i = 0;
18903 while i < n {
18904 let c = *src.add(i);
18905 *dest.add(i) = c;
18906 if c == 0 { return dest.add(i); }
18907 i += 1;
18908 }
18909 dest.add(n)
18910}
18911
18912#[no_mangle]
18913pub unsafe extern "C" fn wprintf(fmt: *const wchar_t, args: ...) -> c_int {
18914 vfwprintf(stdout, fmt, args)
18915}
18916
18917#[no_mangle]
18918pub unsafe extern "C" fn vwprintf(fmt: *const wchar_t, ap: core::ffi::VaList) -> c_int {
18919 vfwprintf(stdout, fmt, ap)
18920}
18921
18922#[no_mangle]
18927pub unsafe extern "C" fn c16rtomb(s: *mut u8, c16: u16, ps: *mut core::ffi::c_void) -> usize {
18928 let state = ps as *mut u32;
18930 let saved: u32 = if state.is_null() { 0 } else { *state };
18931 if s.is_null() {
18932 if !state.is_null() { *state = 0; }
18933 return 1;
18934 }
18935 let cp: u32;
18936 if saved != 0 {
18937 if c16 < 0xdc00 || c16 > 0xdfff {
18938 if !state.is_null() { *state = 0; }
18939 ERRNO!() = EILSEQ;
18940 return !0usize;
18941 }
18942 cp = 0x10000 + (((saved - 0xd800) << 10) | ((c16 as u32) - 0xdc00));
18943 if !state.is_null() { *state = 0; }
18944 } else if c16 >= 0xd800 && c16 <= 0xdbff {
18945 if !state.is_null() { *state = c16 as u32; }
18946 return 0;
18947 } else if c16 >= 0xdc00 && c16 <= 0xdfff {
18948 ERRNO!() = EILSEQ;
18949 return !0usize;
18950 } else {
18951 cp = c16 as u32;
18952 }
18953 if cp < 0x80 {
18954 *s = cp as u8;
18955 1
18956 } else if cp < 0x800 {
18957 *s = (0xc0 | (cp >> 6)) as u8;
18958 *s.add(1) = (0x80 | (cp & 0x3f)) as u8;
18959 2
18960 } else if cp < 0x10000 {
18961 *s = (0xe0 | (cp >> 12)) as u8;
18962 *s.add(1) = (0x80 | ((cp >> 6) & 0x3f)) as u8;
18963 *s.add(2) = (0x80 | (cp & 0x3f)) as u8;
18964 3
18965 } else {
18966 *s = (0xf0 | (cp >> 18)) as u8;
18967 *s.add(1) = (0x80 | ((cp >> 12) & 0x3f)) as u8;
18968 *s.add(2) = (0x80 | ((cp >> 6) & 0x3f)) as u8;
18969 *s.add(3) = (0x80 | (cp & 0x3f)) as u8;
18970 4
18971 }
18972}
18973
18974#[no_mangle]
18975pub unsafe extern "C" fn c32rtomb(s: *mut u8, c32: u32, _ps: *mut core::ffi::c_void) -> usize {
18976 if s.is_null() { return 1; }
18977 if c32 > 0x10ffff || (c32 >= 0xd800 && c32 <= 0xdfff) {
18978 ERRNO!() = EILSEQ;
18979 return !0usize;
18980 }
18981 if c32 < 0x80 {
18982 *s = c32 as u8;
18983 1
18984 } else if c32 < 0x800 {
18985 *s = (0xc0 | (c32 >> 6)) as u8;
18986 *s.add(1) = (0x80 | (c32 & 0x3f)) as u8;
18987 2
18988 } else if c32 < 0x10000 {
18989 *s = (0xe0 | (c32 >> 12)) as u8;
18990 *s.add(1) = (0x80 | ((c32 >> 6) & 0x3f)) as u8;
18991 *s.add(2) = (0x80 | (c32 & 0x3f)) as u8;
18992 3
18993 } else {
18994 *s = (0xf0 | (c32 >> 18)) as u8;
18995 *s.add(1) = (0x80 | ((c32 >> 12) & 0x3f)) as u8;
18996 *s.add(2) = (0x80 | ((c32 >> 6) & 0x3f)) as u8;
18997 *s.add(3) = (0x80 | (c32 & 0x3f)) as u8;
18998 4
18999 }
19000}
19001
19002#[no_mangle]
19003pub unsafe extern "C" fn mbrtoc16(pc16: *mut u16, s: *const u8, n: usize, _ps: *mut core::ffi::c_void) -> usize {
19004 if s.is_null() { return 0; }
19005 if n == 0 { return 1; }
19006 let c = *s;
19007 if c == 0 { return 0; }
19008 if c < 0x80 {
19009 if !pc16.is_null() { *pc16 = c as u16; }
19010 return 1;
19011 }
19012 if c < 0xC2 { return 1; } if c < 0xE0 {
19014 if n < 2 { return 1; }
19015 let c2 = *s.add(1);
19016 if (c2 & 0xC0) != 0x80 { return 1; }
19017 if !pc16.is_null() { *pc16 = ((((c & 0x1F) as u32) << 6) | ((c2 & 0x3F) as u32)) as u16; }
19018 return 2;
19019 }
19020 if c < 0xF0 {
19021 if n < 3 { return 1; }
19022 let c2 = *s.add(1);
19023 let c3 = *s.add(2);
19024 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 { return 1; }
19025 if !pc16.is_null() { *pc16 = ((((c & 0x0F) as u32) << 12) | (((c2 & 0x3F) as u32) << 6) | ((c3 & 0x3F) as u32)) as u16; }
19026 return 3;
19027 }
19028 1
19029}
19030
19031#[no_mangle]
19032pub unsafe extern "C" fn mbrtoc32(pc32: *mut u32, s: *const u8, n: usize, _ps: *mut core::ffi::c_void) -> usize {
19033 if s.is_null() { return 0; }
19034 if n == 0 { return 1; }
19035 let c = *s;
19036 if c == 0 { return 0; }
19037 if c < 0x80 {
19038 if !pc32.is_null() { *pc32 = c as u32; }
19039 return 1;
19040 }
19041 if c < 0xC2 { return 1; } if c < 0xE0 {
19043 if n < 2 { return 1; }
19044 let c2 = *s.add(1);
19045 if (c2 & 0xC0) != 0x80 { return 1; }
19046 if !pc32.is_null() { *pc32 = (((c & 0x1F) as u32) << 6) | ((c2 & 0x3F) as u32); }
19047 return 2;
19048 }
19049 if c < 0xF0 {
19050 if n < 3 { return 1; }
19051 let c2 = *s.add(1);
19052 let c3 = *s.add(2);
19053 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 { return 1; }
19054 if !pc32.is_null() { *pc32 = (((c & 0x0F) as u32) << 12) | (((c2 & 0x3F) as u32) << 6) | ((c3 & 0x3F) as u32); }
19055 return 3;
19056 }
19057 if c < 0xF5 {
19058 if n < 4 { return 1; }
19059 let c2 = *s.add(1);
19060 let c3 = *s.add(2);
19061 let c4 = *s.add(3);
19062 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80 { return 1; }
19063 if !pc32.is_null() { *pc32 = (((c & 0x07) as u32) << 18) | (((c2 & 0x3F) as u32) << 12) | (((c3 & 0x3F) as u32) << 6) | ((c4 & 0x3F) as u32); }
19064 return 4;
19065 }
19066 1
19067}
19068
19069#[no_mangle]
19081pub unsafe extern "C" fn chown(path: *const core::ffi::c_char, uid: u32, gid: u32) -> i32 {
19082 syscall_ret(<Arch as Syscalls>::syscall5(
19083 SYS_FCHOWNAT,
19084 AT_FDCWD as i64,
19085 path as i64,
19086 uid as i64,
19087 gid as i64,
19088 0,
19089 )) as i32
19090}
19091
19092#[no_mangle]
19093pub unsafe extern "C" fn lchown(path: *const core::ffi::c_char, uid: u32, gid: u32) -> i32 {
19094 syscall_ret(<Arch as Syscalls>::syscall5(
19095 SYS_FCHOWNAT,
19096 AT_FDCWD as i64,
19097 path as i64,
19098 uid as i64,
19099 gid as i64,
19100 0x100, )) as i32
19102}
19103
19104#[no_mangle]
19109pub unsafe extern "C" fn chroot(path: *const core::ffi::c_char) -> i32 {
19110 syscall_ret(<Arch as Syscalls>::syscall1(SYS_CHROOT, path as i64)) as i32
19111}
19112
19113#[no_mangle]
19114pub unsafe extern "C" fn get_current_dir_name() -> *mut core::ffi::c_char {
19115 static mut BUF: [core::ffi::c_char; 4096] = [0; 4096];
19116 let r = getcwd(BUF.as_mut_ptr(), 4096);
19117 if r.is_null() { core::ptr::null_mut() } else { BUF.as_mut_ptr() }
19118}
19119
19120#[no_mangle]
19125pub unsafe extern "C" fn creat(pathname: *const core::ffi::c_char, mode: u32) -> i32 {
19126 open(pathname, 1 | 0o100 | 0o1000, mode as i32)
19128}
19129
19130#[no_mangle]
19131pub unsafe extern "C" fn openat(dirfd: i32, pathname: *const core::ffi::c_char, flags: i32, mode: u32) -> i32 {
19132 syscall_ret(<Arch as Syscalls>::syscall4(SYS_OPENAT, dirfd as i64, pathname as i64, flags as i64, mode as i64)) as i32
19133}
19134
19135#[no_mangle]
19136pub unsafe extern "C" fn pwrite(fd: i32, buf: *const u8, count: usize, offset: i64) -> isize {
19137 syscall_ret(<Arch as Syscalls>::syscall4(sysno(18, 68), fd as i64, buf as i64, count as i64, offset)) as isize
19138}
19139
19140#[no_mangle]
19141pub unsafe extern "C" fn readv(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32) -> isize {
19142 syscall_ret(<Arch as Syscalls>::syscall3(sysno(19, 65), fd as i64, iov as i64, iovcnt as i64)) as isize
19143}
19144
19145#[no_mangle]
19146pub unsafe extern "C" fn writev(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32) -> isize {
19147 syscall_ret(<Arch as Syscalls>::syscall3(sysno(20, 66), fd as i64, iov as i64, iovcnt as i64)) as isize
19148}
19149
19150#[no_mangle]
19155pub unsafe extern "C" fn flock(fd: i32, operation: i32) -> i32 {
19156 syscall_ret(<Arch as Syscalls>::syscall2(SYS_FLOCK, fd as i64, operation as i64)) as i32
19157}
19158
19159#[no_mangle]
19160pub unsafe extern "C" fn lockf(fd: i32, cmd: i32, len: i64) -> i32 {
19161 let r = <Arch as Syscalls>::syscall3(SYS_FCNTL, fd as i64, if cmd == 0 { 7 } else if cmd == 1 { 6 } else { 5 } , len);
19162 if r < 0 { return -1; }
19163 0
19164}
19165
19166#[no_mangle]
19171pub unsafe extern "C" fn getdomainname(name: *mut core::ffi::c_char, len: usize) -> i32 {
19172 if name.is_null() || len == 0 {
19173 ERRNO!() = EINVAL;
19174 return -1;
19175 }
19176 let mut uts: UtsName = core::mem::zeroed();
19177 let r = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
19178 if r < 0 {
19179 ERRNO!() = (-r) as c_int;
19180 return -1;
19181 }
19182 let mut n = 0usize;
19183 while n < uts.domainname.len() && uts.domainname[n] != 0 { n += 1; }
19184 if n >= len {
19185 ERRNO!() = EINVAL;
19186 return -1;
19187 }
19188 core::ptr::copy_nonoverlapping(uts.domainname.as_ptr(), name as *mut u8, n);
19189 *name.add(n) = 0;
19190 0
19191}
19192
19193#[no_mangle]
19194pub unsafe extern "C" fn setdomainname(name: *const core::ffi::c_char, len: usize) -> i32 {
19195 syscall_ret(<Arch as Syscalls>::syscall2(sysno(171, 162), name as i64, len as i64)) as i32
19196}
19197
19198#[no_mangle]
19199pub unsafe extern "C" fn sethostname(name: *const core::ffi::c_char, len: usize) -> i32 {
19200 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64)) as i32
19201}
19202
19203#[no_mangle]
19204pub unsafe extern "C" fn getlogin_r(name: *mut core::ffi::c_char, bufsize: usize) -> i32 {
19205 let user = crate::getenv(b"USER\0".as_ptr() as *const core::ffi::c_char);
19207 if user.is_null() { return 2; }
19208 let mut i = 0;
19209 while i < bufsize - 1 && *user.add(i) != 0 {
19210 *name.add(i) = *user.add(i);
19211 i += 1;
19212 }
19213 *name.add(i) = 0;
19214 0
19215}
19216
19217#[no_mangle]
19218pub unsafe extern "C" fn cuserid(s: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
19219 let user = crate::getenv(b"USER\0".as_ptr() as *const core::ffi::c_char);
19220 if user.is_null() { return core::ptr::null_mut(); }
19221 if s.is_null() {
19222 static mut BUF: [core::ffi::c_char; 32] = [0; 32];
19223 let mut i = 0;
19224 while i < 31 && *user.add(i) != 0 { BUF[i] = *user.add(i); i += 1; }
19225 BUF[i] = 0;
19226 BUF.as_mut_ptr()
19227 } else {
19228 let mut i = 0;
19229 while i < 31 && *user.add(i) != 0 { *s.add(i) = *user.add(i); i += 1; }
19230 *s.add(i) = 0;
19231 s
19232 }
19233}
19234
19235#[repr(C)]
19240#[derive(Copy, Clone)]
19241pub struct Passwd {
19242 pub pw_name: *mut c_char,
19243 pub pw_passwd: *mut c_char,
19244 pub pw_uid: u32,
19245 pub pw_gid: u32,
19246 pub pw_gecos: *mut c_char,
19247 pub pw_dir: *mut c_char,
19248 pub pw_shell: *mut c_char,
19249}
19250
19251#[repr(C)]
19252#[derive(Copy, Clone)]
19253pub struct Group {
19254 pub gr_name: *mut c_char,
19255 pub gr_passwd: *mut c_char,
19256 pub gr_gid: u32,
19257 pub gr_mem: *mut *mut c_char,
19258}
19259
19260static mut PWD_ENT: Passwd = Passwd {
19261 pw_name: core::ptr::null_mut(), pw_passwd: core::ptr::null_mut(),
19262 pw_uid: 0, pw_gid: 0, pw_gecos: core::ptr::null_mut(),
19263 pw_dir: core::ptr::null_mut(), pw_shell: core::ptr::null_mut(),
19264};
19265static mut PWD_BUF: [c_char; 1024] = [0; 1024];
19266static mut PWD_FILE: *mut FILE = core::ptr::null_mut();
19267
19268static mut GRP_ENT: Group = Group {
19269 gr_name: core::ptr::null_mut(), gr_passwd: core::ptr::null_mut(),
19270 gr_gid: 0, gr_mem: core::ptr::null_mut(),
19271};
19272static mut GRP_BUF: [c_char; 2048] = [0; 2048];
19273static mut GRP_MEM: [*mut c_char; 32] = [core::ptr::null_mut(); 32];
19274static mut GRP_FILE: *mut FILE = core::ptr::null_mut();
19275
19276unsafe fn parse_passwd(line: *const c_char, ent: *mut Passwd, buf: *mut c_char, buflen: usize) -> bool {
19277 let mut src = line;
19278 let mut o = 0usize;
19279 let mut fields: [*mut c_char; 7] = [core::ptr::null_mut(); 7];
19280 let mut n = 0usize;
19281 while n < 7 {
19282 let start = o;
19283 while *src != 0 && *src != b':' as c_char {
19284 if o + 1 >= buflen { return false; }
19285 *buf.add(o) = *src;
19286 o += 1;
19287 src = src.add(1);
19288 }
19289 *buf.add(o) = 0;
19290 o += 1;
19291 fields[n] = buf.add(start);
19292 n += 1;
19293 if *src == 0 { break; }
19294 src = src.add(1);
19295 }
19296 if n < 7 { return false; }
19297 (*ent).pw_name = fields[0];
19298 (*ent).pw_passwd = fields[1];
19299 (*ent).pw_uid = crate::strtol(fields[2], core::ptr::null_mut(), 10) as u32;
19300 (*ent).pw_gid = crate::strtol(fields[3], core::ptr::null_mut(), 10) as u32;
19301 (*ent).pw_gecos = fields[4];
19302 (*ent).pw_dir = fields[5];
19303 (*ent).pw_shell = fields[6];
19304 true
19305}
19306
19307unsafe fn parse_group(line: *const c_char, ent: *mut Group, buf: *mut c_char, buflen: usize) -> bool {
19308 let mut src = line;
19309 let mut o = 0usize;
19310 let mut fields: [*mut c_char; 4] = [core::ptr::null_mut(); 4];
19311 let mut n = 0usize;
19312 while n < 4 {
19313 let start = o;
19314 while *src != 0 && *src != b':' as c_char {
19315 if o + 1 >= buflen { return false; }
19316 *buf.add(o) = *src;
19317 o += 1;
19318 src = src.add(1);
19319 }
19320 *buf.add(o) = 0;
19321 o += 1;
19322 fields[n] = buf.add(start);
19323 n += 1;
19324 if *src == 0 { break; }
19325 src = src.add(1);
19326 }
19327 if n < 4 { return false; }
19328 (*ent).gr_name = fields[0];
19329 (*ent).gr_passwd = fields[1];
19330 (*ent).gr_gid = crate::strtol(fields[2], core::ptr::null_mut(), 10) as u32;
19331 let mut mi = 0usize;
19332 let mut m = fields[3];
19333 if *m != 0 {
19334 loop {
19335 if mi + 1 >= GRP_MEM.len() { break; }
19336 GRP_MEM[mi] = m;
19337 mi += 1;
19338 while *m != 0 && *m != b',' as c_char { m = m.add(1); }
19339 if *m == 0 { break; }
19340 *m = 0;
19341 m = m.add(1);
19342 }
19343 }
19344 GRP_MEM[mi] = core::ptr::null_mut();
19345 (*ent).gr_mem = GRP_MEM.as_mut_ptr();
19346 true
19347}
19348
19349#[no_mangle]
19350pub unsafe extern "C" fn getpwnam(name: *const c_char) -> *mut Passwd {
19351 if name.is_null() { return core::ptr::null_mut(); }
19352 setpwent();
19353 loop {
19354 let p = getpwent();
19355 if p.is_null() { break; }
19356 if crate::strcmp((*p).pw_name as *const u8, name as *const u8) == 0 { endpwent(); return p; }
19357 }
19358 endpwent();
19359 core::ptr::null_mut()
19360}
19361
19362#[no_mangle]
19363pub unsafe extern "C" fn getpwuid(uid: u32) -> *mut Passwd {
19364 setpwent();
19365 loop {
19366 let p = getpwent();
19367 if p.is_null() { break; }
19368 if (*p).pw_uid == uid { endpwent(); return p; }
19369 }
19370 endpwent();
19371 core::ptr::null_mut()
19372}
19373
19374#[no_mangle]
19375pub unsafe extern "C" fn setpwent() {
19376 endpwent();
19377 PWD_FILE = crate::fopen(b"/etc/passwd\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
19378}
19379
19380#[no_mangle]
19381pub unsafe extern "C" fn getpwent() -> *mut Passwd {
19382 if PWD_FILE.is_null() { setpwent(); if PWD_FILE.is_null() { return core::ptr::null_mut(); } }
19383 let mut line = [0 as c_char; 1024];
19384 loop {
19385 if crate::fgets(line.as_mut_ptr(), 1024, PWD_FILE).is_null() { return core::ptr::null_mut(); }
19386 if parse_passwd(line.as_ptr(), &raw mut PWD_ENT, PWD_BUF.as_mut_ptr(), PWD_BUF.len()) {
19387 return &raw mut PWD_ENT;
19388 }
19389 }
19390}
19391
19392#[no_mangle]
19393pub unsafe extern "C" fn endpwent() {
19394 if !PWD_FILE.is_null() { crate::fclose(PWD_FILE); PWD_FILE = core::ptr::null_mut(); }
19395}
19396
19397#[no_mangle]
19398pub 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 {
19399 if result.is_null() { return EINVAL; }
19400 let p = getpwnam(name);
19401 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *pwd = *p; *result = pwd; 0 }
19402}
19403
19404#[no_mangle]
19405pub unsafe extern "C" fn getpwuid_r(uid: u32, pwd: *mut Passwd, _buf: *mut c_char, _buflen: usize, result: *mut *mut Passwd) -> c_int {
19406 if result.is_null() { return EINVAL; }
19407 let p = getpwuid(uid);
19408 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *pwd = *p; *result = pwd; 0 }
19409}
19410
19411#[no_mangle]
19412pub unsafe extern "C" fn fgetpwent(f: *mut FILE) -> *mut Passwd {
19413 if f.is_null() { return core::ptr::null_mut(); }
19414 let mut line = [0 as c_char; 1024];
19415 loop {
19416 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
19417 if parse_passwd(line.as_ptr(), &raw mut PWD_ENT, PWD_BUF.as_mut_ptr(), PWD_BUF.len()) {
19418 return &raw mut PWD_ENT;
19419 }
19420 }
19421}
19422
19423#[no_mangle]
19424pub unsafe extern "C" fn putpwent(f: *mut FILE, p: *const Passwd) -> c_int {
19425 if f.is_null() || p.is_null() { return -1; }
19426 crate::fprintf(f, b"%s:%s:%u:%u:%s:%s:%s\n\0".as_ptr() as *const c_char,
19427 (*p).pw_name, (*p).pw_passwd, (*p).pw_uid, (*p).pw_gid,
19428 (*p).pw_gecos, (*p).pw_dir, (*p).pw_shell)
19429}
19430
19431#[no_mangle]
19432pub unsafe extern "C" fn getgrnam(name: *const c_char) -> *mut Group {
19433 if name.is_null() { return core::ptr::null_mut(); }
19434 setgrent();
19435 loop {
19436 let g = getgrent();
19437 if g.is_null() { break; }
19438 if crate::strcmp((*g).gr_name as *const u8, name as *const u8) == 0 { endgrent(); return g; }
19439 }
19440 endgrent();
19441 core::ptr::null_mut()
19442}
19443
19444#[no_mangle]
19445pub unsafe extern "C" fn getgrgid(gid: u32) -> *mut Group {
19446 setgrent();
19447 loop {
19448 let g = getgrent();
19449 if g.is_null() { break; }
19450 if (*g).gr_gid == gid { endgrent(); return g; }
19451 }
19452 endgrent();
19453 core::ptr::null_mut()
19454}
19455
19456#[no_mangle]
19457pub unsafe extern "C" fn setgrent() {
19458 endgrent();
19459 GRP_FILE = crate::fopen(b"/etc/group\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
19460}
19461
19462#[no_mangle]
19463pub unsafe extern "C" fn getgrent() -> *mut Group {
19464 if GRP_FILE.is_null() { setgrent(); if GRP_FILE.is_null() { return core::ptr::null_mut(); } }
19465 let mut line = [0 as c_char; 1024];
19466 loop {
19467 if crate::fgets(line.as_mut_ptr(), 1024, GRP_FILE).is_null() { return core::ptr::null_mut(); }
19468 if parse_group(line.as_ptr(), &raw mut GRP_ENT, GRP_BUF.as_mut_ptr(), GRP_BUF.len()) {
19469 return &raw mut GRP_ENT;
19470 }
19471 }
19472}
19473
19474#[no_mangle]
19475pub unsafe extern "C" fn endgrent() {
19476 if !GRP_FILE.is_null() { crate::fclose(GRP_FILE); GRP_FILE = core::ptr::null_mut(); }
19477}
19478
19479#[no_mangle]
19480pub 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 {
19481 if result.is_null() { return EINVAL; }
19482 let g = getgrnam(name);
19483 if g.is_null() { *result = core::ptr::null_mut(); 0 } else { *grp = *g; *result = grp; 0 }
19484}
19485
19486#[no_mangle]
19487pub unsafe extern "C" fn getgrgid_r(gid: u32, grp: *mut Group, _buf: *mut c_char, _buflen: usize, result: *mut *mut Group) -> c_int {
19488 if result.is_null() { return EINVAL; }
19489 let g = getgrgid(gid);
19490 if g.is_null() { *result = core::ptr::null_mut(); 0 } else { *grp = *g; *result = grp; 0 }
19491}
19492
19493#[no_mangle]
19494pub unsafe extern "C" fn fgetgrent(f: *mut FILE) -> *mut Group {
19495 if f.is_null() { return core::ptr::null_mut(); }
19496 let mut line = [0 as c_char; 1024];
19497 loop {
19498 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
19499 if parse_group(line.as_ptr(), &raw mut GRP_ENT, GRP_BUF.as_mut_ptr(), GRP_BUF.len()) {
19500 return &raw mut GRP_ENT;
19501 }
19502 }
19503}
19504
19505#[no_mangle]
19506pub unsafe extern "C" fn putgrent(f: *mut FILE, g: *const Group) -> c_int {
19507 if f.is_null() || g.is_null() { return -1; }
19508 crate::fprintf(f, b"%s:%s:%u:\0".as_ptr() as *const c_char, (*g).gr_name, (*g).gr_passwd, (*g).gr_gid);
19509 if !(*g).gr_mem.is_null() {
19510 let mut i = 0;
19511 while !(*(*g).gr_mem.add(i)).is_null() {
19512 if i > 0 { crate::fputc(b',' as c_int, f); }
19513 crate::fputs(*(*g).gr_mem.add(i), f);
19514 i += 1;
19515 }
19516 }
19517 crate::fputc(b'\n' as c_int, f);
19518 0
19519}
19520
19521#[no_mangle]
19526pub unsafe extern "C" fn setgroups(ngroups: usize, gidset: *const u32) -> i32 {
19527 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SETGROUPS, ngroups as i64, gidset as i64)) as i32
19528}
19529
19530#[no_mangle]
19531pub unsafe extern "C" fn setresuid(ruid: u32, euid: u32, suid: u32) -> i32 {
19532 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETRESUID, ruid as i64, euid as i64, suid as i64)) as i32
19533}
19534
19535#[no_mangle]
19536pub unsafe extern "C" fn setresgid(rgid: u32, egid: u32, sgid: u32) -> i32 {
19537 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETRESGID, rgid as i64, egid as i64, sgid as i64)) as i32
19538}
19539
19540#[no_mangle]
19541pub unsafe extern "C" fn getresuid(ruid: *mut u32, euid: *mut u32, suid: *mut u32) -> i32 {
19542 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETRESUID, ruid as i64, euid as i64, suid as i64)) as i32
19543}
19544
19545#[no_mangle]
19546pub unsafe extern "C" fn getresgid(rgid: *mut u32, egid: *mut u32, sgid: *mut u32) -> i32 {
19547 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETRESGID, rgid as i64, egid as i64, sgid as i64)) as i32
19548}
19549
19550#[repr(C)]
19558struct KernelMsgHdr {
19559 msg_name: *mut c_void,
19560 msg_namelen: u32,
19561 __pad0: u32,
19562 msg_iov: *mut c_void,
19563 msg_iovlen: u64,
19564 msg_control: *mut c_void,
19565 msg_controllen: u64,
19566 msg_flags: u32,
19567 __pad1: u32,
19568}
19569
19570#[repr(C)]
19571struct UserMsgHdr {
19572 msg_name: *mut c_void,
19573 msg_namelen: u32,
19574 msg_iov: *mut c_void,
19575 msg_iovlen: i32,
19576 __pad1: i32,
19577 msg_control: *mut c_void,
19578 msg_controllen: u32,
19579 __pad2: i32,
19580 msg_flags: i32,
19581}
19582
19583unsafe fn msg_to_kernel(msg: *const UserMsgHdr, out: &mut KernelMsgHdr) {
19584 *out = KernelMsgHdr {
19585 msg_name: (*msg).msg_name,
19586 msg_namelen: (*msg).msg_namelen,
19587 __pad0: 0,
19588 msg_iov: (*msg).msg_iov,
19589 msg_iovlen: (*msg).msg_iovlen as u32 as u64,
19590 msg_control: (*msg).msg_control,
19591 msg_controllen: (*msg).msg_controllen as u64,
19592 msg_flags: (*msg).msg_flags as u32,
19593 __pad1: 0,
19594 };
19595}
19596
19597#[no_mangle]
19598pub unsafe extern "C" fn sendmsg(fd: i32, msg: *const core::ffi::c_void, flags: i32) -> isize {
19599 if msg.is_null() {
19600 ERRNO!() = EINVAL;
19601 return -1;
19602 }
19603 let mut k: KernelMsgHdr = core::mem::zeroed();
19604 msg_to_kernel(msg as *const UserMsgHdr, &mut k);
19605 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SENDMSG, fd as i64, &k as *const KernelMsgHdr as i64, flags as i64)) as isize
19606}
19607
19608#[no_mangle]
19609pub unsafe extern "C" fn recvmsg(fd: i32, msg: *mut core::ffi::c_void, flags: i32) -> isize {
19610 if msg.is_null() {
19611 ERRNO!() = EINVAL;
19612 return -1;
19613 }
19614 let user = msg as *mut UserMsgHdr;
19615 let mut k: KernelMsgHdr = core::mem::zeroed();
19616 msg_to_kernel(user, &mut k);
19617 let r = syscall_ret(<Arch as Syscalls>::syscall3(SYS_RECVMSG, fd as i64, &mut k as *mut KernelMsgHdr as i64, flags as i64));
19618 (*user).msg_flags = k.msg_flags as i32;
19619 (*user).msg_controllen = k.msg_controllen as u32;
19620 r as isize
19621}
19622
19623#[no_mangle]
19624pub unsafe extern "C" fn sendmmsg(fd: i32, msgvec: *mut core::ffi::c_void, vlen: u32, flags: i32) -> i32 {
19625 syscall_ret(<Arch as Syscalls>::syscall4(sysno(307, 269), fd as i64, msgvec as i64, vlen as i64, flags as i64)) as i32
19626}
19627
19628#[no_mangle]
19629pub unsafe extern "C" fn recvmmsg(fd: i32, msgvec: *mut core::ffi::c_void, vlen: u32, flags: i32, timeout: *mut core::ffi::c_void) -> i32 {
19630 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
19631}
19632
19633#[no_mangle]
19634pub unsafe extern "C" fn getpeername(fd: i32, addr: *mut core::ffi::c_void, addrlen: *mut u32) -> i32 {
19635 syscall_ret(<Arch as Syscalls>::syscall3(sysno(52, 205), fd as i64, addr as i64, addrlen as i64)) as i32
19636}
19637
19638#[no_mangle]
19639pub unsafe extern "C" fn getsockopt(fd: i32, level: i32, optname: i32, optval: *mut core::ffi::c_void, optlen: *mut u32) -> i32 {
19640 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
19641}
19642
19643#[no_mangle]
19648pub unsafe extern "C" fn ftrylockfile(file: *mut FILE) -> i32 {
19649 if file.is_null() { return EINVAL; }
19650 if (*file).lock < 0 { return 0; }
19651 let tid = sys_gettid() as c_int;
19652 let v = a_load(&raw const (*file).lock);
19653 if v == tid {
19654 (*file).lockcount += 1;
19655 return 0;
19656 }
19657 if v == 0 && a_cas(&raw mut (*file).lock, 0, tid) == 0 {
19658 (*file).lockcount = 1;
19659 return 0;
19660 }
19661 EBUSY
19662}
19663
19664#[no_mangle]
19665pub unsafe extern "C" fn getc_unlocked(file: *mut core::ffi::c_char) -> i32 {
19666 getc(file as *mut FILE)
19667}
19668
19669#[no_mangle]
19670pub unsafe extern "C" fn getchar_unlocked() -> i32 {
19671 getchar()
19672}
19673
19674#[no_mangle]
19675pub unsafe extern "C" fn putc_unlocked(c: i32, file: *mut core::ffi::c_char) -> i32 {
19676 putc(c, file as *mut FILE)
19677}
19678
19679#[no_mangle]
19680pub unsafe extern "C" fn putchar_unlocked(c: i32) -> i32 {
19681 putchar(c)
19682}
19683
19684#[no_mangle] pub static mut optarg: *mut core::ffi::c_char = core::ptr::null_mut();
19689#[no_mangle] pub static mut optind: i32 = 1;
19690#[no_mangle] pub static mut opterr: i32 = 1;
19691#[no_mangle] pub static mut optopt: i32 = '?' as i32;
19692#[no_mangle] pub static mut optreset: i32 = 0;
19693
19694#[no_mangle]
19699pub unsafe extern "C" fn getitimer(which: i32, curr_value: *mut core::ffi::c_void) -> i32 {
19700 syscall_ret(<Arch as Syscalls>::syscall2(sysno(36, 102), which as i64, curr_value as i64)) as i32
19701}
19702
19703#[no_mangle]
19704pub unsafe extern "C" fn setitimer(which: i32, new_value: *const core::ffi::c_void, old_value: *mut core::ffi::c_void) -> i32 {
19705 syscall_ret(<Arch as Syscalls>::syscall3(sysno(38, 103), which as i64, new_value as i64, old_value as i64)) as i32
19706}
19707
19708#[no_mangle]
19713pub unsafe extern "C" fn getloadavg(loadavg: *mut f64, nelem: i32) -> i32 {
19714 let fd = crate::open(b"/proc/loadavg\0".as_ptr() as *const core::ffi::c_char, 0, 0);
19715 if fd < 0 { return -1; }
19716 let mut buf: [u8; 64] = [0; 64];
19717 let n = crate::read(fd, buf.as_mut_ptr() as *mut core::ffi::c_void, 63);
19718 crate::close(fd);
19719 if n <= 0 { return -1; }
19720 buf[n as usize] = 0;
19721 let mut i = 0;
19722 while i < nelem as usize && i < 3 {
19723 let val = crate::strtod((buf.as_ptr() as *const core::ffi::c_char).add(i * 5), core::ptr::null_mut());
19724 *loadavg.add(i) = val;
19725 i += 1;
19726 }
19727 i as i32
19728}
19729
19730#[no_mangle]
19731pub unsafe extern "C" fn get_nprocs() -> i32 {
19732 sysconf(84) as i32 }
19734
19735#[no_mangle]
19736pub unsafe extern "C" fn get_nprocs_conf() -> i32 {
19737 sysconf(83) as i32 }
19739
19740#[no_mangle]
19741pub unsafe extern "C" fn get_avphys_pages() -> i64 {
19742 sysconf(86) }
19744
19745#[no_mangle]
19746pub unsafe extern "C" fn get_phys_pages() -> i64 {
19747 sysconf(85) }
19749
19750#[no_mangle]
19755pub unsafe extern "C" fn capget(header: *mut core::ffi::c_void, data: *mut core::ffi::c_void) -> i32 {
19756 syscall_ret(<Arch as Syscalls>::syscall2(SYS_CAPGET, header as i64, data as i64)) as i32
19757}
19758
19759#[no_mangle]
19760pub unsafe extern "C" fn capset(header: *const core::ffi::c_void, data: *const core::ffi::c_void) -> i32 {
19761 syscall_ret(<Arch as Syscalls>::syscall2(SYS_CAPSET, header as i64, data as i64)) as i32
19762}
19763
19764#[no_mangle]
19765pub unsafe extern "C" fn arch_prctl(code: i32, addr: u64) -> i32 {
19766 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 }
19767}
19768
19769#[no_mangle]
19774pub unsafe extern "C" fn cfgetospeed(termios_p: *const core::ffi::c_void) -> u32 {
19775 unsafe { *(termios_p as *const u32).add(1) }
19776}
19777
19778#[no_mangle]
19779pub unsafe extern "C" fn cfgetispeed(termios_p: *const core::ffi::c_void) -> u32 {
19780 unsafe { *(termios_p as *const u32).add(2) }
19781}
19782
19783#[no_mangle]
19784pub unsafe extern "C" fn cfsetospeed(termios_p: *mut core::ffi::c_void, speed: u32) -> i32 {
19785 unsafe { *(termios_p as *mut u32).add(1) = speed; }
19786 0
19787}
19788
19789#[no_mangle]
19790pub unsafe extern "C" fn cfsetispeed(termios_p: *mut core::ffi::c_void, speed: u32) -> i32 {
19791 unsafe { *(termios_p as *mut u32).add(2) = speed; }
19792 0
19793}
19794
19795#[no_mangle]
19796pub unsafe extern "C" fn cfmakeraw(termios_p: *mut core::ffi::c_void) {
19797 unsafe {
19798 let p = termios_p as *mut u32;
19799 *p.add(0) &= !0o37;
19800 *p.add(0) &= !(0o4000 | 0o2000 | 0o10000 | 0o20);
19801 *p.add(0) |= 0o60;
19802 *p.add(3) &= !0o17;
19803 *p.add(3) &= !(0o1000 | 0o40000000);
19804 *p.add(1) = 1;
19805 *p.add(2) = 0;
19806 }
19807}
19808
19809#[no_mangle]
19814pub unsafe extern "C" fn getrusage(who: i32, usage: *mut core::ffi::c_void) -> i32 {
19815 syscall_ret(<Arch as Syscalls>::syscall2(sysno(98, 165), who as i64, usage as i64)) as i32
19816}
19817
19818#[no_mangle]
19819pub unsafe extern "C" fn getpriority(which: i32, who: u32) -> i32 {
19820 let r = <Arch as Syscalls>::syscall2(SYS_GETPRIORITY, which as i64, who as i64);
19822 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
19823 20 - r as i32
19824}
19825
19826#[no_mangle]
19827pub unsafe extern "C" fn setpriority(which: i32, who: u32, prio: i32) -> i32 {
19828 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETPRIORITY, which as i64, who as i64, prio as i64)) as i32
19829}
19830
19831#[no_mangle]
19832pub unsafe extern "C" fn prlimit(pid: u32, resource: i32, new_limit: *const core::ffi::c_void, old_limit: *mut core::ffi::c_void) -> i32 {
19833 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
19834}
19835
19836#[no_mangle]
19841pub unsafe extern "C" fn clone(
19842 func: usize,
19843 stack: *mut u8,
19844 flags: c_int,
19845 arg: *mut c_void,
19846 mut args: ...
19847) -> c_int {
19848 const CLONE_PIDFD_C: c_int = 0x00001000;
19850 const CLONE_VM_C: c_int = 0x00000100;
19851 const CLONE_THREAD_C: c_int = 0x00010000;
19852 const CLONE_SETTLS_C: c_int = 0x00080000;
19853 const CLONE_PARENT_SETTID_C: c_int = 0x00100000;
19854 const CLONE_CHILD_SETTID_C: c_int = 0x01000000;
19855 const CLONE_CHILD_CLEARTID_C: c_int = 0x00200000;
19856 let _ = CLONE_VM_C;
19857 if flags & (CLONE_THREAD_C | CLONE_SETTLS_C | CLONE_CHILD_CLEARTID_C) != 0
19858 || stack.is_null()
19859 {
19860 ERRNO!() = EINVAL;
19861 return -1;
19862 }
19863 let mut ptid: *mut c_int = core::ptr::null_mut();
19864 let mut tls: c_ulong = 0;
19865 let mut ctid: *mut c_int = core::ptr::null_mut();
19866 if flags & (CLONE_PIDFD_C | CLONE_PARENT_SETTID_C | CLONE_CHILD_SETTID_C) != 0 {
19867 ptid = args.next_arg::<*mut c_int>();
19868 }
19869 if flags & CLONE_CHILD_SETTID_C != 0 {
19870 tls = args.next_arg::<c_ulong>();
19871 ctid = args.next_arg::<*mut c_int>();
19872 }
19873 let r = __rc_clone(func, stack, flags as c_ulong, arg, ptid, tls, ctid);
19874 if r < 0 {
19875 ERRNO!() = (-r) as c_int;
19876 -1
19877 } else {
19878 r as c_int
19879 }
19880}
19881
19882#[no_mangle]
19883pub unsafe extern "C" fn _Fork() -> i32 {
19884 crate::fork()
19885}
19886
19887#[no_mangle]
19888pub 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 {
19889 let mut master: i32 = 0;
19890 let mut slave: i32 = 0;
19891 if openpty(&mut master, &mut slave, name, termp, winp) < 0 { return -1; }
19892 let pid = crate::fork();
19893 if pid < 0 { crate::close(master); crate::close(slave); return -1; }
19894 if pid == 0 {
19895 crate::close(master);
19896 crate::setsid();
19897 crate::dup2(slave, 0);
19898 crate::dup2(slave, 1);
19899 crate::dup2(slave, 2);
19900 } else {
19901 crate::close(slave);
19902 if !amaster.is_null() { *amaster = master; }
19903 }
19904 pid
19905}
19906
19907#[no_mangle]
19908pub 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 {
19909 let master = crate::open(b"/dev/ptmx\0".as_ptr() as *const core::ffi::c_char, 0o2000, 0);
19910 if master < 0 { return -1; }
19911 grantpt(master);
19912 unlockpt(master);
19913 let slave_name = ptsname(master);
19914 if slave_name.is_null() { crate::close(master); return -1; }
19915 let slave = crate::open(slave_name, 0o2000, 0);
19916 if slave < 0 { crate::close(master); return -1; }
19917 if !amaster.is_null() { *amaster = master; }
19918 if !aslave.is_null() { *aslave = slave; }
19919 if !name.is_null() { crate::strcpy(name as *mut u8, slave_name as *const u8); }
19920 0
19921}
19922
19923#[no_mangle]
19924pub unsafe extern "C" fn login_tty(fd: i32) -> i32 {
19925 crate::setsid();
19926 crate::dup2(fd, 0);
19927 crate::dup2(fd, 1);
19928 crate::dup2(fd, 2);
19929 0
19930}
19931
19932#[no_mangle]
19937pub unsafe extern "C" fn __dls2b() {}
19938#[no_mangle]
19939pub unsafe extern "C" fn __dls3() {}
19940#[no_mangle]
19941pub unsafe extern "C" fn _dlstart() {}
19942
19943#[no_mangle]
19948pub unsafe extern "C" fn index(s: *const core::ffi::c_char, c: i32) -> *mut core::ffi::c_char {
19949 let mut i = 0;
19950 loop {
19951 let ch = *s.add(i);
19952 if ch == c as core::ffi::c_char { return s.add(i) as *mut core::ffi::c_char; }
19953 if ch == 0 { return core::ptr::null_mut(); }
19954 i += 1;
19955 }
19956}
19957
19958#[no_mangle]
19959pub unsafe extern "C" fn rindex(s: *const core::ffi::c_char, c: i32) -> *mut core::ffi::c_char {
19960 let mut last = core::ptr::null_mut();
19961 let mut i = 0;
19962 loop {
19963 let ch = *s.add(i);
19964 if ch == 0 { return last; }
19965 if ch == c as core::ffi::c_char { last = s.add(i) as *mut core::ffi::c_char; }
19966 i += 1;
19967 }
19968}
19969
19970#[no_mangle]
19975pub unsafe extern "C" fn imaxabs(j: i64) -> i64 {
19976 j.abs()
19977}
19978
19979#[no_mangle]
19980pub unsafe extern "C" fn imaxdiv(numer: i64, denom: i64) -> (i64, i64) {
19981 (numer / denom, numer % denom)
19982}
19983
19984#[no_mangle]
19989pub static mut h_errno: i32 = 0;
19990
19991#[no_mangle]
19992pub unsafe extern "C" fn __h_errno_location() -> *mut i32 {
19993 &mut h_errno
19994}
19995
19996#[no_mangle]
19997pub unsafe extern "C" fn herror(s: *const core::ffi::c_char) {
19998 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
19999 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20000 crate::write(2, hstrerror(*__h_errno_location()) as *const core::ffi::c_void, crate::strlen(hstrerror(*__h_errno_location())));
20001 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20002}
20003
20004#[no_mangle]
20005pub unsafe extern "C" fn hstrerror(_err: i32) -> *const core::ffi::c_char {
20006 b"Unknown error\0".as_ptr() as *const core::ffi::c_char
20007}
20008
20009#[no_mangle]
20014pub unsafe extern "C" fn gettid() -> i32 {
20015 syscall_ret(<Arch as Syscalls>::syscall0(SYS_GETTID)) as i32
20016}
20017
20018#[no_mangle]
20023pub unsafe extern "C" fn ioctl(fd: i32, request: u32, mut args: ...) -> i32 {
20024 let arg = args.next_arg::<i64>();
20025 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, request as i64, arg)) as i32
20026}
20027
20028#[no_mangle]
20029pub unsafe extern "C" fn ioperm(from: u64, num: u64, turn_on: i32) -> i32 {
20030 #[cfg(target_arch = "x86_64")]
20031 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOPERM, from as i64, num as i64, turn_on as i64)) as i32 }
20032 #[cfg(not(target_arch = "x86_64"))]
20033 {
20034 let _ = (from, num, turn_on);
20035 ERRNO!() = ENOSYS_VAL;
20036 -1
20037 }
20038}
20039
20040#[no_mangle]
20041pub unsafe extern "C" fn iopl(level: i32) -> i32 {
20042 #[cfg(target_arch = "x86_64")]
20043 { syscall_ret(<Arch as Syscalls>::syscall1(SYS_IOPL, level as i64)) as i32 }
20044 #[cfg(not(target_arch = "x86_64"))]
20045 {
20046 let _ = level;
20047 ERRNO!() = ENOSYS_VAL;
20048 -1
20049 }
20050}
20051
20052#[no_mangle]
20057pub unsafe extern "C" fn getxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
20058 syscall_ret(<Arch as Syscalls>::syscall4(sysno(191, 8), path as i64, name as i64, value as i64, size as i64)) as isize
20059}
20060
20061#[no_mangle]
20062pub unsafe extern "C" fn lgetxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
20063 syscall_ret(<Arch as Syscalls>::syscall4(sysno(192, 9), path as i64, name as i64, value as i64, size as i64)) as isize
20064}
20065
20066#[no_mangle]
20067pub unsafe extern "C" fn fgetxattr(fd: i32, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
20068 syscall_ret(<Arch as Syscalls>::syscall4(sysno(193, 10), fd as i64, name as i64, value as i64, size as i64)) as isize
20069}
20070
20071#[no_mangle]
20072pub unsafe extern "C" fn listxattr(path: *const core::ffi::c_char, list: *mut u8, size: usize) -> isize {
20073 syscall_ret(<Arch as Syscalls>::syscall3(sysno(194, 11), path as i64, list as i64, size as i64)) as isize
20074}
20075
20076#[no_mangle]
20077pub unsafe extern "C" fn llistxattr(path: *const core::ffi::c_char, list: *mut u8, size: usize) -> isize {
20078 syscall_ret(<Arch as Syscalls>::syscall3(sysno(195, 12), path as i64, list as i64, size as i64)) as isize
20079}
20080
20081#[no_mangle]
20082pub unsafe extern "C" fn flistxattr(fd: i32, list: *mut u8, size: usize) -> isize {
20083 syscall_ret(<Arch as Syscalls>::syscall3(sysno(196, 13), fd as i64, list as i64, size as i64)) as isize
20084}
20085
20086#[no_mangle]
20087pub 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 {
20088 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
20089}
20090
20091#[no_mangle]
20092pub 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 {
20093 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
20094}
20095
20096#[no_mangle]
20097pub unsafe extern "C" fn fsetxattr(fd: i32, name: *const core::ffi::c_char, value: *const u8, size: usize, flags: i32) -> i32 {
20098 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
20099}
20100
20101#[no_mangle]
20102pub unsafe extern "C" fn removexattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char) -> i32 {
20103 syscall_ret(<Arch as Syscalls>::syscall2(sysno(197, 14), path as i64, name as i64)) as i32
20104}
20105
20106#[no_mangle]
20107pub unsafe extern "C" fn lremovexattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char) -> i32 {
20108 syscall_ret(<Arch as Syscalls>::syscall2(sysno(198, 15), path as i64, name as i64)) as i32
20109}
20110
20111#[no_mangle]
20112pub unsafe extern "C" fn fremovexattr(fd: i32, name: *const core::ffi::c_char) -> i32 {
20113 syscall_ret(<Arch as Syscalls>::syscall2(sysno(199, 16), fd as i64, name as i64)) as i32
20114}
20115
20116#[no_mangle]
20121pub unsafe extern "C" fn adjtime(_delta: *const core::ffi::c_void, olddelta: *mut core::ffi::c_void) -> i32 {
20122 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ADJTIMEX, olddelta as i64)) as i32
20123}
20124
20125#[no_mangle]
20126pub unsafe extern "C" fn adjtimex(buf: *mut core::ffi::c_void) -> i32 {
20127 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ADJTIMEX, buf as i64)) as i32
20128}
20129
20130const TIOCGPTN: i64 = 0x80045430;
20139const TIOCSPTLCK: i64 = 0x40045431;
20140
20141#[no_mangle]
20142pub unsafe extern "C" fn grantpt(_fd: i32) -> i32 {
20143 0
20145}
20146
20147#[no_mangle]
20148pub unsafe extern "C" fn unlockpt(fd: i32) -> i32 {
20149 let mut unlock: i32 = 0;
20150 let r = <Arch as Syscalls>::syscall3(
20151 SYS_IOCTL,
20152 fd as i64,
20153 TIOCSPTLCK,
20154 &mut unlock as *mut i32 as i64,
20155 );
20156 if r < 0 { -1 } else { 0 }
20157}
20158
20159#[no_mangle]
20160pub unsafe extern "C" fn ptsname(fd: i32) -> *mut core::ffi::c_char {
20161 static mut BUF: [core::ffi::c_char; 32] = [0; 32];
20162 let mut pty_nr: i32 = 0;
20163 if <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, TIOCGPTN, &mut pty_nr as *mut i32 as i64) < 0 {
20164 return core::ptr::null_mut();
20165 }
20166 BUF[0] = '/' as c_char; BUF[1] = 'd' as c_char; BUF[2] = 'e' as c_char; BUF[3] = 'v' as c_char;
20168 BUF[4] = '/' as c_char; BUF[5] = 'p' as c_char; BUF[6] = 't' as c_char; BUF[7] = 's' as c_char;
20169 BUF[8] = '/' as c_char;
20170 let mut n = pty_nr as usize;
20171 let mut i = 9;
20172 if n == 0 { BUF[i] = '0' as c_char; i += 1; }
20173 while n > 0 && i < 31 {
20174 BUF[i] = (b'0' + (n % 10) as u8) as c_char;
20175 n /= 10;
20176 i += 1;
20177 }
20178 BUF[i] = 0;
20179 BUF.as_mut_ptr()
20180}
20181
20182#[no_mangle]
20187pub unsafe extern "C" fn finite(x: f64) -> i32 {
20188 (!x.is_nan() && !x.is_infinite()) as i32
20189}
20190
20191#[no_mangle]
20192pub unsafe extern "C" fn finitef(x: f32) -> i32 {
20193 (!x.is_nan() && !x.is_infinite()) as i32
20194}
20195
20196#[no_mangle]
20197pub unsafe extern "C" fn __fpclassifyl(x: f64) -> i32 {
20198 __fpclassify(x)
20199}
20200
20201#[no_mangle]
20202pub unsafe extern "C" fn __signbitl(x: f64) -> i32 {
20203 __signbit(x)
20204}
20205
20206#[no_mangle]
20215pub unsafe extern "C" fn j0(x: f64) -> f64 {
20216 j0_impl(x)
20217}
20218
20219#[no_mangle]
20220pub unsafe extern "C" fn j0f(x: f32) -> f32 {
20221 libm::j0f(x)
20222}
20223
20224#[no_mangle]
20225pub unsafe extern "C" fn j1(x: f64) -> f64 {
20226 libm::j1(x)
20227}
20228
20229#[no_mangle]
20230pub unsafe extern "C" fn j1f(x: f32) -> f32 {
20231 libm::j1f(x)
20232}
20233
20234#[no_mangle]
20235pub unsafe extern "C" fn jn(n: i32, x: f64) -> f64 {
20236 libm::jn(n, x)
20237}
20238
20239#[no_mangle]
20240pub unsafe extern "C" fn jnf(n: i32, x: f32) -> f32 {
20241 libm::jnf(n, x)
20242}
20243
20244#[no_mangle]
20245pub unsafe extern "C" fn y0(x: f64) -> f64 {
20246 y0_impl(x)
20247}
20248
20249#[no_mangle]
20250pub unsafe extern "C" fn y0f(x: f32) -> f32 {
20251 if x.is_nan() { return x; }
20252 if x < 0.0 { return __math_invalidf(x); }
20253 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f32::NEG_INFINITY; }
20254 libm::y0f(x)
20255}
20256
20257#[no_mangle]
20258pub unsafe extern "C" fn y1(x: f64) -> f64 {
20259 if x.is_nan() { return x; }
20260 if x < 0.0 { return __math_invalid(x); }
20261 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f64::NEG_INFINITY; }
20262 libm::y1(x)
20263}
20264
20265#[no_mangle]
20266pub unsafe extern "C" fn y1f(x: f32) -> f32 {
20267 if x.is_nan() { return x; }
20268 if x < 0.0 { return __math_invalidf(x); }
20269 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f32::NEG_INFINITY; }
20270 libm::y1f(x)
20271}
20272
20273#[no_mangle]
20274pub unsafe extern "C" fn yn(n: i32, x: f64) -> f64 {
20275 if x.is_nan() { return x; }
20276 if x < 0.0 { return __math_invalid(x); }
20277 if x == 0.0 {
20278 feraiseexcept(FE_DIVBYZERO);
20279 if n >= 0 { return f64::NEG_INFINITY; }
20280 }
20281 libm::yn(n, x)
20282}
20283
20284#[no_mangle]
20285pub unsafe extern "C" fn ynf(n: i32, x: f32) -> f32 {
20286 if x.is_nan() { return x; }
20287 if x < 0.0 { return __math_invalidf(x); }
20288 if x == 0.0 {
20289 feraiseexcept(FE_DIVBYZERO);
20290 if n >= 0 { return f32::NEG_INFINITY; }
20291 }
20292 libm::ynf(n, x)
20293}
20294
20295#[no_mangle]
20300pub unsafe extern "C" fn __ctype_b_loc() -> *mut *const u16 {
20301 static mut TABLE: *const u16 = core::ptr::null();
20302 &mut TABLE
20303}
20304
20305#[no_mangle]
20306pub unsafe extern "C" fn __ctype_tolower_loc() -> *mut *const i32 {
20307 static mut TABLE: *const i32 = core::ptr::null();
20308 &mut TABLE
20309}
20310
20311#[no_mangle]
20312pub unsafe extern "C" fn __ctype_toupper_loc() -> *mut *const i32 {
20313 static mut TABLE: *const i32 = core::ptr::null();
20314 &mut TABLE
20315}
20316
20317#[no_mangle]
20318pub unsafe extern "C" fn __isalnum_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20319 (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
20320}
20321
20322#[no_mangle]
20323pub unsafe extern "C" fn __isalpha_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20324 (c >= 'A' as i32 && c <= 'Z' as i32 || c >= 'a' as i32 && c <= 'z' as i32) as i32
20325}
20326
20327#[no_mangle]
20328pub unsafe extern "C" fn __isblank_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20329 (c == ' ' as i32 || c == '\t' as i32) as i32
20330}
20331
20332#[no_mangle]
20333pub unsafe extern "C" fn __iscntrl_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20334 (c < 0x20 || c == 0x7f) as i32
20335}
20336
20337#[no_mangle]
20338pub unsafe extern "C" fn __isdigit_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20339 (c >= '0' as i32 && c <= '9' as i32) as i32
20340}
20341
20342#[no_mangle]
20343pub unsafe extern "C" fn __isgraph_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20344 (c > 0x20 && c < 0x7f) as i32
20345}
20346
20347#[no_mangle]
20348pub unsafe extern "C" fn __islower_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20349 (c >= 'a' as i32 && c <= 'z' as i32) as i32
20350}
20351
20352#[no_mangle]
20353pub unsafe extern "C" fn __isprint_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20354 (c >= 0x20 && c < 0x7f) as i32
20355}
20356
20357#[no_mangle]
20358pub unsafe extern "C" fn __ispunct_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20359 (c >= 0x21 && c <= 0x2f || c >= 0x3a && c <= 0x40 || c >= 0x5b && c <= 0x60 || c >= 0x7b && c <= 0x7e) as i32
20360}
20361
20362#[no_mangle]
20363pub unsafe extern "C" fn __isspace_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20364 (c == ' ' as i32 || c >= 0x09 && c <= 0x0d) as i32
20365}
20366
20367#[no_mangle]
20368pub unsafe extern "C" fn __isupper_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20369 (c >= 'A' as i32 && c <= 'Z' as i32) as i32
20370}
20371
20372#[no_mangle]
20373pub unsafe extern "C" fn __isxdigit_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20374 (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
20375}
20376
20377#[no_mangle]
20382pub unsafe extern "C" fn __iswalnum_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20383 (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
20384}
20385
20386#[no_mangle]
20387pub unsafe extern "C" fn __iswalpha_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20388 (c >= 'A' as u32 && c <= 'Z' as u32 || c >= 'a' as u32 && c <= 'z' as u32) as i32
20389}
20390
20391#[no_mangle]
20392pub unsafe extern "C" fn __iswblank_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20393 (c == ' ' as u32 || c == '\t' as u32) as i32
20394}
20395
20396#[no_mangle]
20397pub unsafe extern "C" fn __iswcntrl_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20398 (c < 0x20 || c == 0x7f) as i32
20399}
20400
20401#[no_mangle]
20402pub unsafe extern "C" fn __iswdigit_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20403 (c >= '0' as u32 && c <= '9' as u32) as i32
20404}
20405
20406#[no_mangle]
20407pub unsafe extern "C" fn __iswgraph_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20408 (c > 0x20 && c < 0x7f) as i32
20409}
20410
20411#[no_mangle]
20412pub unsafe extern "C" fn __iswlower_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20413 (c >= 'a' as u32 && c <= 'z' as u32) as i32
20414}
20415
20416#[no_mangle]
20417pub unsafe extern "C" fn __iswprint_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20418 (c >= 0x20 && c < 0x7f) as i32
20419}
20420
20421#[no_mangle]
20422pub unsafe extern "C" fn __iswpunct_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20423 (c >= 0x21 && c <= 0x2f || c >= 0x3a && c <= 0x40 || c >= 0x5b && c <= 0x60 || c >= 0x7b && c <= 0x7e) as i32
20424}
20425
20426#[no_mangle]
20427pub unsafe extern "C" fn __iswspace_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20428 (c == ' ' as u32 || c >= 0x09 && c <= 0x0d) as i32
20429}
20430
20431#[no_mangle]
20432pub unsafe extern "C" fn __iswupper_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20433 (c >= 'A' as u32 && c <= 'Z' as u32) as i32
20434}
20435
20436#[no_mangle]
20437pub unsafe extern "C" fn __iswxdigit_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20438 (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
20439}
20440
20441#[no_mangle]
20442pub unsafe extern "C" fn __iswctype_l(c: u32, ctype: u32, _loc: *mut core::ffi::c_void) -> i32 {
20443 crate::iswctype(c as wint_t, ctype as wctype_t)
20444}
20445
20446#[no_mangle]
20447pub unsafe extern "C" fn __towlower_l(c: u32, _loc: *mut core::ffi::c_void) -> u32 {
20448 crate::towlower(c)
20449}
20450
20451#[no_mangle]
20452pub unsafe extern "C" fn __towupper_l(c: u32, _loc: *mut core::ffi::c_void) -> u32 {
20453 crate::towupper(c)
20454}
20455
20456#[no_mangle]
20457pub unsafe extern "C" fn __towctrans_l(c: u32, _trans: u32, _loc: *mut core::ffi::c_void) -> u32 {
20458 c
20459}
20460
20461#[no_mangle]
20474pub 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) {
20475 crate::write(2, b"Assertion failed: ".as_ptr() as *const core::ffi::c_void, 18);
20476 if !expr.is_null() { crate::write(2, expr as *const core::ffi::c_void, crate::strlen(expr)); }
20477 crate::write(2, b" (".as_ptr() as *const core::ffi::c_void, 2);
20478 if !file.is_null() { crate::write(2, file as *const core::ffi::c_void, crate::strlen(file)); }
20479 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20480 let mut n = line as usize;
20481 let mut digits: [u8; 32] = [0; 32];
20482 let mut di = 0;
20483 if n == 0 { digits[0] = 0; di = 1; }
20484 while n > 0 && di < 32 { digits[di] = (n % 10) as u8; n /= 10; di += 1; }
20485 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); }
20486 crate::write(2, b")".as_ptr() as *const core::ffi::c_void, 1);
20487 if !func.is_null() { crate::write(2, func as *const core::ffi::c_void, crate::strlen(func)); }
20488 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20489 crate::abort()
20490}
20491
20492#[no_mangle]
20493pub unsafe extern "C" fn at_quick_exit(_func: Option<unsafe extern "C" fn()>) -> i32 {
20494 0
20496}
20497
20498#[no_mangle]
20499pub unsafe extern "C" fn brk(addr: *mut u8) -> i32 {
20500 syscall_ret(<Arch as Syscalls>::syscall1(sysno(12, 214), addr as i64)) as i32
20501}
20502
20503#[no_mangle]
20504pub 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 {
20505 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
20506}
20507
20508#[no_mangle]
20509pub unsafe extern "C" fn ctermid(s: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
20510 static mut BUF: [core::ffi::c_char; 20] = [0; 20];
20511 let dst = if s.is_null() { BUF.as_mut_ptr() } else { s };
20512 let src = b"/dev/tty\0".as_ptr() as *const core::ffi::c_char;
20513 let mut i = 0;
20514 while i < 9 { *dst.add(i) = *src.add(i); i += 1; }
20515 dst
20516}
20517
20518#[no_mangle]
20519pub unsafe extern "C" fn delete_module(name: *const core::ffi::c_char, flags: u32) -> i32 {
20520 syscall_ret(<Arch as Syscalls>::syscall2(SYS_DELETE_MODULE, name as i64, flags as i64)) as i32
20521}
20522
20523
20524
20525
20526
20527#[no_mangle]
20528pub unsafe extern "C" fn __duplocale(loc: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
20529 loc
20530}
20531
20532#[no_mangle]
20533pub unsafe extern "C" fn euidaccess(pathname: *const core::ffi::c_char, mode: i32) -> i32 {
20534 faccessat(AT_FDCWD, pathname, mode, 0x200)
20535}
20536
20537#[no_mangle]
20538pub unsafe extern "C" fn fgetln(f: *mut core::ffi::c_void, lenp: *mut usize) -> *mut core::ffi::c_char {
20539 static mut BUF: [core::ffi::c_char; 4096] = [0; 4096];
20540 let mut i = 0;
20541 while i < 4095 {
20542 let c = getc(f as *mut FILE);
20543 if c < 0 { break; }
20544 BUF[i] = c as c_char;
20545 i += 1;
20546 if c == '\n' as i32 { break; }
20547 }
20548 BUF[i] = 0;
20549 if !lenp.is_null() { *lenp = i; }
20550 if i == 0 { core::ptr::null_mut() } else { BUF.as_mut_ptr() }
20551}
20552
20553#[no_mangle]
20554pub unsafe extern "C" fn fgetws(ws: *mut u32, n: i32, f: *mut core::ffi::c_void) -> *mut u32 {
20555 let mut i = 0;
20556 while i < n - 1 {
20557 let c = getwc(f as *mut core::ffi::c_void);
20558 if c == 0 { break; }
20559 *ws.add(i as usize) = c;
20560 i += 1;
20561 if c == '\n' as u32 { break; }
20562 }
20563 *ws.add(i as usize) = 0;
20564 if i == 0 { core::ptr::null_mut() } else { ws }
20565}
20566
20567#[no_mangle]
20568pub 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 {
20569 if !label.is_null() { crate::write(2, label as *const core::ffi::c_void, crate::strlen(label)); }
20570 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20571 if !text.is_null() { crate::write(2, text as *const core::ffi::c_void, crate::strlen(text)); }
20572 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20573 0
20574}
20575
20576#[no_mangle]
20577pub unsafe extern "C" fn ftime(tp: *mut core::ffi::c_void) -> i32 {
20578 let mut tv: timeval = core::mem::zeroed();
20579 if gettimeofday(&mut tv, core::ptr::null_mut()) == 0 {
20580 let tb = tp as *mut Timeb;
20581 (*tb).time = tv.tv_sec;
20582 (*tb).millitm = (tv.tv_usec / 1000) as u16;
20583 (*tb).timezone = 0;
20584 (*tb).dstflag = 0;
20585 0
20586 } else {
20587 -1
20588 }
20589}
20590
20591#[no_mangle]
20592pub unsafe extern "C" fn getdents(fd: i32, dirp: *mut u8, count: usize) -> isize {
20593 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, dirp as i64, count as i64)) as isize
20594}
20595
20596#[no_mangle]
20597pub unsafe extern "C" fn gethostid() -> i64 {
20598 let fd = crate::open(b"/proc/sys/kernel/random/boot_id\0".as_ptr() as *const core::ffi::c_char, 0, 0);
20600 if fd < 0 { return 0; }
20601 let mut buf: [u8; 64] = [0; 64];
20602 let n = crate::read(fd, buf.as_mut_ptr() as *mut core::ffi::c_void, 63);
20603 crate::close(fd);
20604 if n <= 0 { return 0; }
20605 buf[n as usize] = 0;
20606 crate::strtol(buf.as_ptr() as *const core::ffi::c_char, core::ptr::null_mut(), 16)
20607}
20608
20609#[no_mangle]
20610pub unsafe extern "C" fn getpass(prompt: *const core::ffi::c_char) -> *mut core::ffi::c_char {
20611 static mut BUF: [core::ffi::c_char; 128] = [0; 128];
20612 crate::write(2, prompt as *const core::ffi::c_void, crate::strlen(prompt));
20614 let n = crate::read(0, BUF.as_mut_ptr() as *mut core::ffi::c_void, 127);
20616 if n > 0 {
20617 let end = if BUF[(n - 1) as usize] == '\n' as c_char { n - 1 } else { n };
20618 BUF[end as usize] = 0;
20619 } else {
20620 BUF[0] = 0;
20621 }
20622 BUF.as_mut_ptr()
20623}
20624
20625#[no_mangle]
20626pub 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 {
20627 let s = *optionp;
20628 if s.is_null() { return -1; }
20629 let mut end = s;
20631 while *end != 0 && *end != ',' as c_char && *end != '=' as c_char { end = end.add(1); }
20632 let eq = *end == '=' as c_char;
20633 if eq { *end = 0; *valuep = end.add(1); }
20634 let mut i = 0;
20636 loop {
20637 let tok = *tokens.add(i);
20638 if tok.is_null() { break; }
20639 if crate::strcmp(s as *const u8, tok as *const u8) == 0 {
20640 while *end != 0 && *end != ',' as c_char { end = end.add(1); }
20642 if *end == ',' as c_char { end = end.add(1); }
20643 *optionp = end;
20644 return i as i32;
20645 }
20646 i += 1;
20647 }
20648 -1
20649}
20650
20651#[no_mangle]
20652pub unsafe extern "C" fn getw(f: *mut core::ffi::c_void) -> i32 {
20653 let c0 = getc(f as *mut FILE);
20654 if c0 < 0 { return -1; }
20655 let c1 = getc(f as *mut FILE);
20656 if c1 < 0 { return -1; }
20657 let c2 = getc(f as *mut FILE);
20658 if c2 < 0 { return -1; }
20659 let c3 = getc(f as *mut FILE);
20660 if c3 < 0 { return -1; }
20661 (c0 | (c1 << 8) | (c2 << 16) | (c3 << 24)) as i32
20662}
20663
20664#[no_mangle]
20665pub unsafe extern "C" fn getwc(f: *mut core::ffi::c_void) -> u32 {
20666 getc(f as *mut FILE) as u32
20667}
20668
20669#[no_mangle]
20670pub unsafe extern "C" fn init_module(module_image: *mut u8, len: usize, param_values: *const core::ffi::c_char) -> i32 {
20671 syscall_ret(<Arch as Syscalls>::syscall3(SYS_INIT_MODULE, module_image as i64, len as i64, param_values as i64)) as i32
20672}
20673
20674
20675
20676#[no_mangle]
20677pub unsafe extern "C" fn issetugid() -> i32 {
20678 let ruid = crate::getuid();
20679 let euid = crate::geteuid();
20680 let rgid = crate::getgid();
20681 let egid = crate::getegid();
20682 (ruid != euid || rgid != egid) as i32
20683}
20684
20685#[repr(C)]
20690struct PollTimespec {
20691 tv_sec: i64,
20692 tv_nsec: i64,
20693}
20694
20695#[no_mangle]
20696pub unsafe extern "C" fn poll(fds: *mut core::ffi::c_void, nfds: u32, timeout: i32) -> i32 {
20697 #[cfg(target_arch = "x86_64")]
20698 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_POLL, fds as i64, nfds as i64, timeout as i64)) as i32 }
20699 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
20700 {
20701 let mut ts = PollTimespec { tv_sec: 0, tv_nsec: 0 };
20705 let ts_ptr = if timeout < 0 {
20706 core::ptr::null()
20707 } else {
20708 ts.tv_sec = (timeout / 1000) as i64;
20709 ts.tv_nsec = ((timeout % 1000) as i64) * 1_000_000;
20710 &ts as *const PollTimespec as *const core::ffi::c_void
20711 };
20712 syscall_ret(<Arch as Syscalls>::syscall5(
20713 SYS_PPOLL,
20714 fds as i64,
20715 nfds as i64,
20716 ts_ptr as i64,
20717 0,
20718 8,
20719 )) as i32
20720 }
20721}
20722
20723#[no_mangle]
20724pub unsafe extern "C" fn ppoll(fds: *mut core::ffi::c_void, nfds: u32, timeout: *const core::ffi::c_void, sigmask: *const u64) -> i32 {
20725 syscall_ret(<Arch as Syscalls>::syscall5(SYS_PPOLL, fds as i64, nfds as i64, timeout as i64, sigmask as i64, 8)) as i32
20726}
20727
20728#[no_mangle]
20729pub 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 {
20730 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
20731}
20732
20733#[no_mangle]
20742pub unsafe extern "C" fn quick_exit(status: i32) -> ! {
20743 crate::_exit(status)
20744}
20745
20746#[no_mangle]
20751pub unsafe extern "C" fn lstat(path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20752 let r = <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, buf as i64, 0x100);
20753 if r < 0 {
20754 ERRNO!() = (-r) as c_int;
20755 -1
20756 } else {
20757 0
20758 }
20759}
20760
20761#[no_mangle]
20762pub unsafe extern "C" fn __xstat(_ver: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20763 crate::stat(path, buf as *mut Stat)
20764}
20765
20766#[no_mangle]
20767pub unsafe extern "C" fn __lxstat(_ver: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20768 crate::lstat(path, buf)
20769}
20770
20771#[no_mangle]
20772pub unsafe extern "C" fn __fxstat(_ver: i32, fd: i32, buf: *mut core::ffi::c_void) -> i32 {
20773 crate::fstat(fd, buf as *mut Stat)
20774}
20775
20776#[no_mangle]
20777pub unsafe extern "C" fn __fxstatat(_ver: i32, _dirfd: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void, _flags: i32) -> i32 {
20778 crate::stat(path, buf as *mut Stat)
20779}
20780
20781#[no_mangle]
20786pub unsafe extern "C" fn mempcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
20787 core::ptr::copy_nonoverlapping(src, dest, n);
20788 dest.add(n)
20789}
20790
20791#[no_mangle]
20796pub unsafe extern "C" fn mkostemp(template: *mut core::ffi::c_char, _flags: i32) -> i32 {
20797 mkstemp(template)
20798}
20799
20800#[no_mangle]
20801pub unsafe extern "C" fn mkstemps(template: *mut core::ffi::c_char, suffixlen: i32) -> i32 {
20802 mkstemps_impl(template, suffixlen)
20803}
20804
20805#[no_mangle]
20810pub unsafe extern "C" fn ptrace(request: i32, mut args: ...) -> i64 {
20811 let pid = args.next_arg::<c_long>();
20812 let addr = args.next_arg::<c_long>();
20813 let data = args.next_arg::<c_long>();
20814 if (1..=3).contains(&request) {
20817 let mut result: c_long = 0;
20818 let r = <Arch as Syscalls>::syscall4(
20819 sysno(101, 117),
20820 request as i64,
20821 pid,
20822 addr,
20823 &mut result as *mut c_long as i64,
20824 );
20825 if r < 0 {
20826 ERRNO!() = (-r) as c_int;
20827 return -1;
20828 }
20829 return result;
20830 }
20831 syscall_ret(<Arch as Syscalls>::syscall4(sysno(101, 117), request as i64, pid, addr, data))
20832}
20833
20834#[no_mangle]
20835pub unsafe extern "C" fn personality(persona: u64) -> i64 {
20836 <Arch as Syscalls>::syscall1(sysno(135, 92), persona as i64)
20837}
20838
20839#[no_mangle]
20840pub unsafe extern "C" fn reboot(cmd: c_int) -> i32 {
20841 syscall_ret(<Arch as Syscalls>::syscall3(
20843 SYS_REBOOT,
20844 0xfee1dead,
20845 672274793,
20846 cmd as i64,
20847 )) as i32
20848}
20849
20850#[no_mangle]
20851pub unsafe extern "C" fn pivot_root(new_root: *const core::ffi::c_char, put_old: *const core::ffi::c_char) -> i32 {
20852 syscall_ret(<Arch as Syscalls>::syscall2(SYS_PIVOT_ROOT, new_root as i64, put_old as i64)) as i32
20853}
20854
20855#[no_mangle]
20856pub 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 {
20857 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
20858}
20859
20860#[no_mangle]
20861pub unsafe extern "C" fn umount(target: *const core::ffi::c_char) -> i32 {
20862 syscall_ret(<Arch as Syscalls>::syscall2(SYS_UMOUNT2, target as i64, 0)) as i32
20863}
20864
20865#[no_mangle]
20866pub unsafe extern "C" fn umount2(target: *const core::ffi::c_char, flags: i32) -> i32 {
20867 syscall_ret(<Arch as Syscalls>::syscall2(SYS_UMOUNT2, target as i64, flags as i64)) as i32
20868}
20869
20870#[no_mangle]
20880pub unsafe extern "C" fn psiginfo(_pinfo: *const core::ffi::c_void, s: *const core::ffi::c_char) {
20881 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
20882 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20883}
20884
20885#[no_mangle]
20886pub unsafe extern "C" fn psignal(sig: i32, s: *const core::ffi::c_char) {
20887 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
20888 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20889 crate::write(2, strsignal(sig) as *const core::ffi::c_void, crate::strlen(strsignal(sig)));
20890 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20891}
20892
20893#[no_mangle]
20894pub unsafe extern "C" fn strsignal(sig: c_int) -> *const c_char {
20895 static NAMES: [&[u8]; 32] = [
20896 b"Unknown signal\0",
20897 b"Hangup\0",
20898 b"Interrupt\0",
20899 b"Quit\0",
20900 b"Illegal instruction\0",
20901 b"Trace/breakpoint trap\0",
20902 b"Aborted\0",
20903 b"Bus error\0",
20904 b"Floating point exception\0",
20905 b"Killed\0",
20906 b"User defined signal 1\0",
20907 b"Segmentation fault\0",
20908 b"User defined signal 2\0",
20909 b"Broken pipe\0",
20910 b"Alarm clock\0",
20911 b"Terminated\0",
20912 b"Stack fault\0",
20913 b"Child process status\0",
20914 b"Continued\0",
20915 b"Stopped (signal)\0",
20916 b"Stopped\0",
20917 b"Stopped (tty input)\0",
20918 b"Stopped (tty output)\0",
20919 b"Urgent I/O condition\0",
20920 b"CPU time limit exceeded\0",
20921 b"File size limit exceeded\0",
20922 b"Virtual timer expired\0",
20923 b"Profiling timer expired\0",
20924 b"Window changed\0",
20925 b"I/O possible\0",
20926 b"Power failure\0",
20927 b"Bad system call\0",
20928 ];
20929 static mut RT_BUF: [c_char; 32] = [0; 32];
20930 if sig > 0 && sig < 32 {
20931 return NAMES[sig as usize].as_ptr() as *const c_char;
20932 }
20933 if sig >= 32 && sig < 65 {
20934 let mut o = 0usize;
20935 for &c in b"Real-time signal \0" {
20936 if c == 0 { break; }
20937 RT_BUF[o] = c as c_char;
20938 o += 1;
20939 }
20940 let mut v = (sig - 32) as u32;
20941 let mut digits = [0u8; 10];
20942 let mut d = 0usize;
20943 if v == 0 { digits[0] = b'0'; d = 1; }
20944 while v > 0 { digits[d] = b'0' + (v % 10) as u8; v /= 10; d += 1; }
20945 while d > 0 { d -= 1; RT_BUF[o] = digits[d] as c_char; o += 1; }
20946 RT_BUF[o] = 0;
20947 return RT_BUF.as_ptr();
20948 }
20949 b"Unknown signal\0".as_ptr() as *const c_char
20950}
20951
20952#[no_mangle]
20953pub unsafe extern "C" fn __strerror_l(errnum: i32, _loc: *mut core::ffi::c_void) -> *const core::ffi::c_char {
20954 crate::strerror(errnum)
20955}
20956
20957#[no_mangle]
20962pub unsafe extern "C" fn preadv(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64) -> isize {
20963 syscall_ret(<Arch as Syscalls>::syscall5(
20966 sysno(295, 69),
20967 fd as i64,
20968 iov as i64,
20969 iovcnt as i64,
20970 offset,
20971 offset >> 32,
20972 )) as isize
20973}
20974
20975#[no_mangle]
20976pub unsafe extern "C" fn pwritev(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64) -> isize {
20977 syscall_ret(<Arch as Syscalls>::syscall5(
20978 sysno(296, 70),
20979 fd as i64,
20980 iov as i64,
20981 iovcnt as i64,
20982 offset,
20983 offset >> 32,
20984 )) as isize
20985}
20986
20987#[no_mangle]
20988pub unsafe extern "C" fn preadv2(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64, flags: u32) -> isize {
20989 syscall_ret(<Arch as Syscalls>::syscall6(
20992 sysno(327, 286),
20993 fd as i64,
20994 iov as i64,
20995 iovcnt as i64,
20996 offset,
20997 offset >> 32,
20998 flags as i64,
20999 )) as isize
21000}
21001
21002#[no_mangle]
21003pub unsafe extern "C" fn pwritev2(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64, flags: u32) -> isize {
21004 syscall_ret(<Arch as Syscalls>::syscall6(
21005 sysno(328, 287),
21006 fd as i64,
21007 iov as i64,
21008 iovcnt as i64,
21009 offset,
21010 offset >> 32,
21011 flags as i64,
21012 )) as isize
21013}
21014
21015#[no_mangle]
21020pub unsafe extern "C" fn nice(inc: i32) -> i32 {
21021 let mut prio = inc;
21022 if inc > -40 && inc < 40 {
21023 prio += getpriority(0, 0);
21024 }
21025 if prio > 19 { prio = 19; }
21026 if prio < -20 { prio = -20; }
21027 if setpriority(0, 0, prio) != 0 {
21028 if ERRNO!() == 13 { ERRNO!() = 1; } return -1;
21030 }
21031 prio
21032}
21033
21034#[no_mangle]
21039pub unsafe extern "C" fn l64a(value: i64) -> *mut core::ffi::c_char {
21040 static mut BUF: [core::ffi::c_char; 7] = [0; 7];
21041 let mut v = value as u64;
21042 let mut i = 0;
21043 while v > 0 && i < 6 {
21044 let c = (v & 0x3f) as u8;
21045 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;
21046 v >>= 6;
21047 i += 1;
21048 }
21049 BUF[i] = 0;
21050 BUF.as_mut_ptr()
21051}
21052
21053#[no_mangle]
21054pub unsafe extern "C" fn lchmod(path: *const core::ffi::c_char, mode: u32) -> i32 {
21055 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FCHMODAT, AT_FDCWD as i64, path as i64, mode as i64, 0x100)) as i32
21056}
21057
21058#[no_mangle]
21059pub unsafe extern "C" fn lutimes(filename: *const core::ffi::c_char, times: *const core::ffi::c_void) -> i32 {
21060 utimensat(AT_FDCWD, filename, times as *const timespec, 0x100)
21061}
21062
21063#[no_mangle]
21064pub unsafe extern "C" fn mknod(pathname: *const core::ffi::c_char, mode: u32, dev: u64) -> i32 {
21065 #[cfg(target_arch = "x86_64")]
21066 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_MKNOD, pathname as i64, mode as i64, dev as i64)) as i32 }
21067 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
21068 {
21069 syscall_ret(<Arch as Syscalls>::syscall4(SYS_MKNODAT, AT_FDCWD as i64, pathname as i64, mode as i64, dev as i64)) as i32
21070 }
21071}
21072
21073#[no_mangle]
21074pub unsafe extern "C" fn memfd_create(name: *const core::ffi::c_char, flags: u32) -> i32 {
21075 syscall_ret(<Arch as Syscalls>::syscall2(sysno(319, 279), name as i64, flags as i64)) as i32
21076}
21077
21078#[no_mangle]
21079pub unsafe extern "C" fn mlock2(addr: *const core::ffi::c_void, len: usize, flags: u32) -> i32 {
21080 syscall_ret(<Arch as Syscalls>::syscall3(sysno(325, 284), addr as i64, len as i64, flags as i64)) as i32
21081}
21082
21083
21084
21085#[no_mangle]
21086pub unsafe extern "C" fn remap_file_pages(addr: *mut core::ffi::c_void, size: usize, prot: i32, pgoff: usize, flags: u32) -> i32 {
21087 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
21088}
21089
21090#[no_mangle]
21095pub unsafe extern "C" fn nan(_tagp: *const core::ffi::c_char) -> f64 {
21096 f64::NAN
21097}
21098
21099#[no_mangle]
21100pub unsafe extern "C" fn nanf(_tagp: *const core::ffi::c_char) -> f32 {
21101 f32::NAN
21102}
21103
21104#[no_mangle]
21109pub unsafe extern "C" fn __lgammal_r(x: f64, signgamp: *mut i32) -> f64 {
21110 *signgamp = 1;
21111 lgamma(x)
21112}
21113
21114#[no_mangle]
21115pub unsafe extern "C" fn __libc_current_sigrtmax() -> i32 {
21116 64
21117}
21118
21119#[no_mangle]
21120pub unsafe extern "C" fn _longjmp(env: *mut core::ffi::c_void, val: i32) {
21121 crate::longjmp(env as *mut u64, val)
21122}
21123
21124#[no_mangle]
21125pub unsafe extern "C" fn __newlocale(_mask: i32, _name: *const core::ffi::c_char, base: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
21126 base
21127}
21128
21129#[no_mangle]
21130pub unsafe extern "C" fn __nl_langinfo(_item: i32) -> *mut core::ffi::c_char {
21131 b"\0".as_ptr() as *mut core::ffi::c_char
21132}
21133
21134#[no_mangle]
21135pub unsafe extern "C" fn __nl_langinfo_l(_item: i32, _loc: *mut core::ffi::c_void) -> *mut core::ffi::c_char {
21136 b"\0".as_ptr() as *mut core::ffi::c_char
21137}
21138
21139#[no_mangle]
21140pub unsafe extern "C" fn ns_get16(cp: *const u8) -> u16 {
21141 ((*cp.add(0) as u16) << 8) | *cp.add(1) as u16
21142}
21143
21144#[no_mangle]
21145pub unsafe extern "C" fn ns_get32(cp: *const u8) -> u32 {
21146 ((*cp.add(0) as u32) << 24) | ((*cp.add(1) as u32) << 16) | ((*cp.add(2) as u32) << 8) | *cp.add(3) as u32
21147}
21148
21149#[no_mangle]
21150pub unsafe extern "C" fn ns_put16(s: u16, dst: *mut u8) {
21151 *dst.add(0) = (s >> 8) as u8;
21152 *dst.add(1) = (s & 0xff) as u8;
21153}
21154
21155#[no_mangle]
21156pub unsafe extern "C" fn ns_put32(l: u32, dst: *mut u8) {
21157 *dst.add(0) = (l >> 24) as u8;
21158 *dst.add(1) = ((l >> 16) & 0xff) as u8;
21159 *dst.add(2) = ((l >> 8) & 0xff) as u8;
21160 *dst.add(3) = (l & 0xff) as u8;
21161}
21162
21163#[no_mangle]
21164pub unsafe extern "C" fn posix_close(fd: i32) -> i32 {
21165 crate::close(fd)
21166}
21167
21168#[no_mangle]
21169pub unsafe extern "C" fn posix_openpt(flags: i32) -> i32 {
21170 crate::open(b"/dev/ptmx\0".as_ptr() as *const core::ffi::c_char, flags, 0)
21171}
21172
21173#[no_mangle]
21174pub unsafe extern "C" fn putw(w: i32, f: *mut core::ffi::c_void) {
21175 putc((w & 0xff) as i32, f as *mut FILE);
21176 putc(((w >> 8) & 0xff) as i32, f as *mut FILE);
21177 putc(((w >> 16) & 0xff) as i32, f as *mut FILE);
21178 putc(((w >> 24) & 0xff) as i32, f as *mut FILE);
21179}
21180
21181
21182
21183#[no_mangle]
21184pub unsafe extern "C" fn rand_r(seedp: *mut u32) -> i32 {
21185 let seed = (*seedp).wrapping_mul(1103515245).wrapping_add(12345);
21186 *seedp = seed;
21187 ((seed >> 16) & 0x7fff) as i32
21188}
21189
21190#[no_mangle]
21191pub unsafe extern "C" fn reallocarray(ptr: *mut core::ffi::c_void, nmemb: usize, size: usize) -> *mut core::ffi::c_void {
21192 let total = match nmemb.checked_mul(size) {
21193 Some(v) => v,
21194 None => { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
21195 };
21196 crate::realloc(ptr, total)
21197}
21198
21199#[no_mangle]
21200pub unsafe extern "C" fn __res_state() -> *mut core::ffi::c_void {
21201 static mut STATE: [u8; 512] = [0; 512];
21202 STATE.as_mut_ptr() as *mut core::ffi::c_void
21203}
21204
21205#[no_mangle]
21206pub unsafe extern "C" fn sbrk(increment: isize) -> *mut u8 {
21207 if increment != 0 {
21210 ERRNO!() = ENOMEM;
21211 return -1isize as usize as *mut u8;
21212 }
21213 <Arch as Syscalls>::syscall1(sysno(12, 214), 0) as *mut u8
21214}
21215
21216#[no_mangle]
21217pub unsafe extern "C" fn scalb(x: f64, exp: f64) -> f64 {
21218 if x.is_nan() || exp.is_nan() { return x * exp; }
21219 if !exp.is_finite() {
21220 let r = if exp > 0.0 { x * exp } else { x / (-exp) };
21221 if r.is_nan() && !x.is_nan() {
21222 feraiseexcept(FE_INVALID);
21223 }
21224 return r;
21225 }
21226 if libm::rint(exp) != exp {
21227 return __math_invalid(exp);
21228 }
21229 if exp > 65000.0 { return libm::scalbn(x, 65000); }
21230 if -exp > 65000.0 { return libm::scalbn(x, -65000); }
21231 libm::scalbn(x, exp as i32)
21232}
21233
21234#[no_mangle]
21235pub unsafe extern "C" fn scalbf(x: f32, exp: f32) -> f32 {
21236 if x.is_nan() || exp.is_nan() { return x * exp; }
21237 if !exp.is_finite() {
21238 let r = if exp > 0.0 { x * exp } else { x / (-exp) };
21239 if r.is_nan() && !x.is_nan() {
21240 feraiseexcept(FE_INVALID);
21241 }
21242 return r;
21243 }
21244 if libm::rintf(exp) != exp {
21245 return __math_invalidf(exp);
21246 }
21247 if exp > 65000.0 { return libm::scalbnf(x, 65000); }
21248 if -exp > 65000.0 { return libm::scalbnf(x, -65000); }
21249 libm::scalbnf(x, exp as i32)
21250}
21251
21252#[no_mangle]
21253pub unsafe extern "C" fn __sched_cpucount(setsize: usize, setp: *const u8) -> i32 {
21254 let mut count = 0;
21255 let mut i = 0;
21256 while i < setsize * 8 {
21257 if (*setp.add(i / 8) >> (i % 8)) & 1 != 0 { count += 1; }
21258 i += 1;
21259 }
21260 count
21261}
21262
21263
21264
21265#[no_mangle]
21266pub unsafe extern "C" fn select(nfds: i32, readfds: *mut u8, writefds: *mut u8, exceptfds: *mut u8, timeout: *mut core::ffi::c_void) -> i32 {
21267 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
21268}
21269
21270
21271
21272#[no_mangle]
21273pub unsafe extern "C" fn sendfile(out_fd: i32, in_fd: i32, offset: *mut i64, count: usize) -> isize {
21274 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
21275}
21276
21277
21278
21279
21280
21281#[no_mangle]
21282pub unsafe extern "C" fn __setjmp(env: *mut core::ffi::c_void) -> i32 {
21283 crate::setjmp(env as *mut u64)
21284}
21285
21286#[no_mangle]
21287pub unsafe extern "C" fn _setjmp(env: *mut core::ffi::c_void) -> i32 {
21288 crate::setjmp(env as *mut u64)
21289}
21290
21291#[no_mangle]
21292pub unsafe extern "C" fn setlinebuf(stream: *mut core::ffi::c_void) {
21293 setvbuf(stream as *mut FILE, core::ptr::null_mut(), 1, 0);
21294}
21295
21296
21297
21298
21299
21300
21301
21302
21303
21304
21305
21306
21307
21308
21309
21310#[no_mangle]
21311pub unsafe extern "C" fn significand(x: f64) -> f64 {
21312 let bits = x.to_bits();
21313 let exp = ((bits >> 52) & 0x7ff) as i32;
21314 if exp == 0 || exp == 0x7ff { return x; }
21315 f64::from_bits((bits & 0x000fffffffffffff) | (1023u64 << 52))
21316}
21317
21318#[no_mangle]
21319pub unsafe extern "C" fn significandf(x: f32) -> f32 {
21320 let bits = x.to_bits();
21321 let exp = ((bits >> 23) & 0xff) as i32;
21322 if exp == 0 || exp == 0xff { return x; }
21323 f32::from_bits((bits & 0x007fffff) | (127u32 << 23))
21324}
21325
21326
21327
21328
21329
21330#[no_mangle]
21331pub unsafe extern "C" fn sigset(sig: i32, handler: usize) -> usize {
21332 signal(sig, handler)
21334}
21335
21336#[no_mangle]
21337pub unsafe extern "C" fn sincos(x: f64, sin: *mut f64, cos: *mut f64) {
21338 *sin = libm::sin(x);
21339 *cos = libm::cos(x);
21340}
21341
21342#[no_mangle]
21343pub unsafe extern "C" fn sincosf(x: f32, sin: *mut f32, cos: *mut f32) {
21344 *sin = libm::sinf(x);
21345 *cos = libm::cosf(x);
21346}
21347
21348
21349
21350
21351
21352
21353
21354
21355
21356unsafe fn nd_ascii_lower(c: c_char) -> c_int {
21357 let b = c as u8;
21358 if b >= b'A' && b <= b'Z' { (b + 32) as c_int } else { b as c_int }
21359}
21360
21361unsafe fn nd_strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
21362 let mut i = 0usize;
21363 while i < n {
21364 let c1 = nd_ascii_lower(*s1.add(i));
21365 let c2 = nd_ascii_lower(*s2.add(i));
21366 if c1 != c2 || c1 == 0 { return c1 - c2; }
21367 i += 1;
21368 }
21369 0
21370}
21371
21372#[no_mangle]
21373pub unsafe extern "C" fn strcasecmp(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char) -> i32 {
21374 nd_strncasecmp(s1, s2, usize::MAX)
21375}
21376
21377#[no_mangle]
21378pub 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 {
21379 nd_strncasecmp(s1, s2, usize::MAX)
21380}
21381
21382#[no_mangle]
21383pub unsafe extern "C" fn strcasestr(haystack: *const core::ffi::c_char, needle: *const core::ffi::c_char) -> *mut core::ffi::c_char {
21384 let nlen = crate::strlen(needle);
21385 if nlen == 0 { return haystack as *mut core::ffi::c_char; }
21386 let mut i = 0;
21387 loop {
21388 let h = haystack.add(i);
21389 if *h == 0 { return core::ptr::null_mut(); }
21390 if crate::strncasecmp(h, needle, nlen) == 0 { return h as *mut core::ffi::c_char; }
21391 i += 1;
21392 }
21393}
21394
21395#[no_mangle]
21396pub 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 {
21397 crate::strcmp(s1 as *const u8, s2 as *const u8)
21398}
21399
21400#[no_mangle]
21401pub unsafe extern "C" fn strncasecmp(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char, n: usize) -> i32 {
21402 nd_strncasecmp(s1, s2, n)
21403}
21404
21405#[no_mangle]
21406pub 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 {
21407 nd_strncasecmp(s1, s2, n)
21408}
21409
21410#[no_mangle]
21411pub unsafe extern "C" fn strsep(stringp: *mut *mut core::ffi::c_char, delim: *const core::ffi::c_char) -> *mut core::ffi::c_char {
21412 let s = *stringp;
21413 if s.is_null() { return core::ptr::null_mut(); }
21414 let mut p = s;
21415 while *p != 0 {
21416 let mut d = delim;
21417 while *d != 0 {
21418 if *p == *d { *p = 0; *stringp = p.add(1); return s; }
21419 d = d.add(1);
21420 }
21421 p = p.add(1);
21422 }
21423 *stringp = core::ptr::null_mut();
21424 s
21425}
21426
21427#[no_mangle]
21428pub unsafe extern "C" fn strtoimax(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, base: i32) -> i64 {
21429 crate::strtol(nptr, endptr, base)
21430}
21431
21432#[no_mangle]
21433pub 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 {
21434 let mut s = if s.is_null() { *saveptr } else { s };
21435 if s.is_null() { return core::ptr::null_mut(); }
21436 while *s != 0 {
21438 let mut d = delim;
21439 let mut found = false;
21440 while *d != 0 {
21441 if *s == *d { found = true; break; }
21442 d = d.add(1);
21443 }
21444 if !found { break; }
21445 s = s.add(1);
21446 }
21447 if *s == 0 { *saveptr = s; return core::ptr::null_mut(); }
21448 let start = s;
21449 while *s != 0 {
21451 let mut d = delim;
21452 while *d != 0 {
21453 if *s == *d { *s = 0; *saveptr = s.add(1); return start; }
21454 d = d.add(1);
21455 }
21456 s = s.add(1);
21457 }
21458 *saveptr = s;
21459 start
21460}
21461
21462#[no_mangle]
21463pub unsafe extern "C" fn strtoumax(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, base: i32) -> u64 {
21464 crate::strtoul(nptr, endptr, base) as u64
21465}
21466
21467#[no_mangle]
21468pub 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 {
21469 crate::strlcpy(dest as *mut u8, src as *const u8, n)
21470}
21471
21472#[no_mangle]
21473pub unsafe extern "C" fn swab(src: *const u8, dest: *mut u8, nbytes: isize) {
21474 let mut i = 0;
21475 while i + 1 < nbytes {
21476 let a = *src.add(i as usize);
21477 let b = *src.add(i as usize + 1);
21478 *dest.add(i as usize) = b;
21479 *dest.add(i as usize + 1) = a;
21480 i += 2;
21481 }
21482}
21483
21484
21485
21486
21487
21488
21489
21490
21491
21492
21493
21494#[no_mangle]
21495pub unsafe extern "C" fn __tolower_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
21496 if c >= 'A' as i32 && c <= 'Z' as i32 { c + 32 } else { c }
21497}
21498
21499#[no_mangle]
21500pub unsafe extern "C" fn __toupper_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
21501 if c >= 'a' as i32 && c <= 'z' as i32 { c - 32 } else { c }
21502}
21503
21504#[no_mangle]
21505pub unsafe extern "C" fn ulimit(cmd: c_int, mut args: ...) -> c_long {
21506 let mut rl: Rlimit = core::mem::zeroed();
21507 if getrlimit(RLIMIT_FSIZE, &mut rl) != 0 { return -1; }
21508 if cmd == 2 {
21509 let val = args.next_arg::<c_long>();
21510 rl.rlim_cur = 512u64.wrapping_mul(val as u64);
21511 if setrlimit(RLIMIT_FSIZE, &rl) != 0 { return -1; }
21512 }
21513 (rl.rlim_cur / 512) as c_long
21514}
21515
21516#[repr(C)]
21517struct UtsName {
21518 sysname: [u8; 65],
21519 nodename: [u8; 65],
21520 release: [u8; 65],
21521 version: [u8; 65],
21522 machine: [u8; 65],
21523 domainname: [u8; 65],
21524}
21525
21526#[no_mangle]
21527pub unsafe extern "C" fn uname(buf: *mut c_void) -> c_int {
21528 let r = <Arch as Syscalls>::syscall1(SYS_UNAME, buf as i64);
21531 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
21532 0
21533}
21534
21535#[no_mangle]
21536pub unsafe extern "C" fn unshare(flags: i32) -> i32 {
21537 let r = <Arch as Syscalls>::syscall1(SYS_UNSHARE, flags as i64);
21538 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21539}
21540
21541#[no_mangle]
21542pub unsafe extern "C" fn updwtmpx(wtmpx_file: *const core::ffi::c_char, utx: *const core::ffi::c_void) {
21543 updwtmp(wtmpx_file, utx)
21544}
21545
21546#[no_mangle]
21547pub unsafe extern "C" fn __uselocale(loc: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
21548 loc
21549}
21550
21551#[repr(C)]
21552pub struct Utimbuf { actime: i64, modtime: i64 }
21553
21554#[no_mangle]
21555pub unsafe extern "C" fn utime(filename: *const c_char, times: *const Utimbuf) -> c_int {
21556 if times.is_null() {
21557 return utimensat(AT_FDCWD, filename, core::ptr::null(), 0);
21558 }
21559 let ts = [
21560 timespec { tv_sec: (*times).actime, tv_nsec: 0 },
21561 timespec { tv_sec: (*times).modtime, tv_nsec: 0 },
21562 ];
21563 utimensat(AT_FDCWD, filename, ts.as_ptr(), 0)
21564}
21565
21566#[no_mangle]
21567pub unsafe extern "C" fn vhangup() -> c_int {
21568 let r = <Arch as Syscalls>::syscall0(SYS_VHANGUP);
21569 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21570}
21571
21572#[no_mangle]
21573pub unsafe extern "C" fn vmsplice(fd: i32, iov: *const c_void, nr_segs: usize, flags: u32) -> isize {
21574 let r = <Arch as Syscalls>::syscall4(SYS_VMSPLICE, fd as i64, iov as i64, nr_segs as i64, flags as i64);
21575 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
21576}
21577
21578
21579
21580#[no_mangle]
21581pub unsafe extern "C" fn wait4(pid: i32, wstatus: *mut i32, options: i32, rusage: *mut core::ffi::c_void) -> i32 {
21582 syscall_ret(<Arch as Syscalls>::syscall4(SYS_WAIT4, pid as i64, wstatus as i64, options as i64, rusage as i64)) as i32
21583}
21584
21585#[no_mangle]
21586pub unsafe extern "C" fn waitid(idtype: i32, id: u32, infop: *mut core::ffi::c_void, options: i32) -> i32 {
21587 syscall_ret(<Arch as Syscalls>::syscall5(
21590 sysno(247, 95),
21591 idtype as i64,
21592 id as i64,
21593 infop as i64,
21594 options as i64,
21595 0,
21596 )) as i32
21597}
21598
21599#[no_mangle]
21600pub unsafe extern "C" fn __wcscoll_l(s1: *const u32, s2: *const u32, _loc: *mut core::ffi::c_void) -> i32 {
21601 crate::wcscmp(s1 as *const i32, s2 as *const i32)
21602}
21603
21604#[no_mangle]
21605pub unsafe extern "C" fn __wcsxfrm_l(dest: *mut u32, src: *const u32, n: usize, _loc: *mut core::ffi::c_void) -> usize {
21606 crate::wcscpy(dest as *mut i32, src as *const i32);
21607 n
21608}
21609
21610#[no_mangle]
21611pub unsafe extern "C" fn wcwidth(c: u32) -> i32 {
21612 if c == 0 { return 0; }
21613 if c < 32 || (c >= 0x7f && c < 0xa0) { return -1; }
21614 1
21615}
21616
21617
21618
21619
21620
21621#[no_mangle]
21628pub 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 {
21629 crate::strtod(nptr, endptr)
21630}
21631
21632#[no_mangle]
21633pub 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 {
21634 crate::strtof(nptr, endptr)
21635}
21636
21637#[no_mangle]
21638pub 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 {
21639 crate::strtod(nptr, endptr)
21640}
21641
21642#[repr(C)]
21647struct linux_dirent64 {
21648 d_ino: u64,
21649 d_off: i64,
21650 d_reclen: u16,
21651 d_type: u8,
21652 d_name: [u8; 0], }
21654
21655const DIR_BUF_SIZE: usize = 4096;
21659
21660#[repr(C)]
21661struct DirStream {
21662 fd: i32,
21663 pos: usize,
21664 len: usize,
21665 last_off: i64,
21666 buf: [u8; DIR_BUF_SIZE],
21667}
21668
21669unsafe fn dir_stream_new(fd: i32) -> *mut core::ffi::c_void {
21670 let ds = malloc(core::mem::size_of::<DirStream>()) as *mut DirStream;
21671 if ds.is_null() {
21672 crate::close(fd);
21673 ERRNO!() = ENOMEM;
21674 return core::ptr::null_mut();
21675 }
21676 core::ptr::write_bytes(ds, 0, 1);
21677 (*ds).fd = fd;
21678 ds as *mut core::ffi::c_void
21679}
21680
21681#[no_mangle]
21682pub unsafe extern "C" fn opendir(dirname: *const core::ffi::c_char) -> *mut core::ffi::c_void {
21683 let fd = openat(AT_FDCWD, dirname, O_DIRECTORY, 0); if fd < 0 { return core::ptr::null_mut(); }
21685 dir_stream_new(fd)
21686}
21687
21688#[no_mangle]
21689pub unsafe extern "C" fn closedir(dirp: *mut core::ffi::c_void) -> i32 {
21690 if dirp.is_null() { ERRNO!() = 22; return -1; }
21691 let ds = dirp as *mut DirStream;
21692 let r = crate::close((*ds).fd);
21693 free(dirp);
21694 r
21695}
21696
21697#[no_mangle]
21698pub unsafe extern "C" fn readdir(dirp: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
21699 if dirp.is_null() { ERRNO!() = 22; return core::ptr::null_mut(); }
21700 let ds = &mut *(dirp as *mut DirStream);
21701
21702 loop {
21703 if ds.pos >= ds.len {
21704 let nread = syscall_ret(<Arch as Syscalls>::syscall3(
21705 SYS_GETDENTS64,
21706 ds.fd as i64,
21707 ds.buf.as_mut_ptr() as i64,
21708 DIR_BUF_SIZE as i64,
21709 )) as isize;
21710 if nread <= 0 { return core::ptr::null_mut(); }
21711 ds.len = nread as usize;
21712 ds.pos = 0;
21713 }
21714
21715 let ent = ds.buf.as_ptr().add(ds.pos) as *const linux_dirent64;
21716 let ent_ref = &*ent;
21717 if ent_ref.d_reclen as usize == 0 {
21718 ds.len = 0;
21719 return core::ptr::null_mut();
21720 }
21721 ds.pos += ent_ref.d_reclen as usize;
21722 ds.last_off = ent_ref.d_off;
21723
21724 return ent as *mut core::ffi::c_void;
21726 }
21727}
21728
21729#[no_mangle]
21730pub 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 {
21731 let ent = readdir(dirp);
21732 if ent.is_null() {
21733 *result = core::ptr::null_mut();
21734 } else {
21735 *result = ent;
21736 }
21737 0
21738}
21739
21740#[no_mangle]
21741pub unsafe extern "C" fn seekdir(dirp: *mut core::ffi::c_void, loc: i64) {
21742 if dirp.is_null() { return; }
21743 let ds = &mut *(dirp as *mut DirStream);
21744 <Arch as Syscalls>::syscall3(SYS_LSEEK, ds.fd as i64, loc, 0);
21745 ds.pos = 0;
21746 ds.len = 0;
21747}
21748
21749#[no_mangle]
21750pub unsafe extern "C" fn telldir(dirp: *mut core::ffi::c_void) -> i64 {
21751 if dirp.is_null() { return -1; }
21752 (*(dirp as *mut DirStream)).last_off
21753}
21754
21755#[no_mangle]
21756pub unsafe extern "C" fn rewinddir(dirp: *mut core::ffi::c_void) {
21757 if dirp.is_null() { return; }
21758 let ds = &mut *(dirp as *mut DirStream);
21759 <Arch as Syscalls>::syscall3(SYS_LSEEK, ds.fd as i64, 0, 0);
21760 ds.pos = 0;
21761 ds.len = 0;
21762 ds.last_off = 0;
21763}
21764
21765#[no_mangle]
21766pub unsafe extern "C" fn dirfd(dirp: *mut core::ffi::c_void) -> i32 {
21767 if dirp.is_null() { ERRNO!() = 22; return -1; }
21768 (*(dirp as *mut DirStream)).fd
21769}
21770
21771#[no_mangle]
21776pub unsafe extern "C" fn mprotect(addr: *mut u8, len: usize, prot: i32) -> i32 {
21777 syscall_ret(<Arch as Syscalls>::syscall3(SYS_MPROTECT, addr as i64, len as i64, prot as i64)) as i32
21778}
21779
21780#[no_mangle]
21781pub unsafe extern "C" fn msync(addr: *mut u8, len: usize, flags: i32) -> i32 {
21782 syscall_ret(<Arch as Syscalls>::syscall3(sysno(26, 227), addr as i64, len as i64, flags as i64)) as i32
21783}
21784
21785#[no_mangle]
21786pub unsafe extern "C" fn mlock(addr: *const u8, len: usize) -> i32 {
21787 syscall_ret(<Arch as Syscalls>::syscall2(sysno(149, 228), addr as i64, len as i64)) as i32
21788}
21789
21790#[no_mangle]
21791pub unsafe extern "C" fn munlock(addr: *const u8, len: usize) -> i32 {
21792 syscall_ret(<Arch as Syscalls>::syscall2(sysno(150, 229), addr as i64, len as i64)) as i32
21793}
21794
21795#[no_mangle]
21796pub unsafe extern "C" fn mlockall(flags: i32) -> i32 {
21797 syscall_ret(<Arch as Syscalls>::syscall1(sysno(151, 230), flags as i64)) as i32
21798}
21799
21800#[no_mangle]
21801pub unsafe extern "C" fn munlockall() -> i32 {
21802 syscall_ret(<Arch as Syscalls>::syscall0(sysno(152, 231))) as i32
21803}
21804
21805#[no_mangle]
21806pub unsafe extern "C" fn madvise(addr: *mut u8, len: usize, advice: i32) -> i32 {
21807 syscall_ret(<Arch as Syscalls>::syscall3(sysno(28, 233), addr as i64, len as i64, advice as i64)) as i32
21808}
21809
21810#[no_mangle]
21811pub unsafe extern "C" fn mincore(addr: *mut u8, len: usize, vec: *mut u8) -> i32 {
21812 syscall_ret(<Arch as Syscalls>::syscall3(sysno(27, 232), addr as i64, len as i64, vec as i64)) as i32
21813}
21814
21815#[no_mangle]
21822pub unsafe extern "C" fn drem(x: f64, y: f64) -> f64 {
21823 remainder(x, y)
21824}
21825
21826#[no_mangle]
21827pub unsafe extern "C" fn dremf(x: f32, y: f32) -> f32 {
21828 remainderf(x, y)
21829}
21830
21831#[no_mangle]
21832pub unsafe extern "C" fn pow10(x: f64) -> f64 {
21833 libm::pow(10.0, x)
21834}
21835
21836#[no_mangle]
21837pub unsafe extern "C" fn pow10f(x: f32) -> f32 {
21838 libm::powf(10.0, x)
21839}
21840
21841#[no_mangle]
21842pub unsafe extern "C" fn pow10l(x: f64) -> f64 {
21843 libm::pow(10.0, x)
21844}
21845
21846#[no_mangle]
21847pub unsafe extern "C" fn isless(x: f64, y: f64) -> i32 {
21848 if x.is_nan() || y.is_nan() { 0 } else { (x < y) as i32 }
21849}
21850
21851#[no_mangle]
21852pub unsafe extern "C" fn islessf(x: f32, y: f32) -> i32 {
21853 if x.is_nan() || y.is_nan() { 0 } else { (x < y) as i32 }
21854}
21855
21856#[no_mangle]
21857pub unsafe extern "C" fn lgamma_r(x: f64, signgamp: *mut i32) -> f64 {
21858 lgamma_r_impl(x, signgamp)
21859}
21860
21861#[no_mangle]
21862pub unsafe extern "C" fn lgammaf_r(x: f32, signgamp: *mut i32) -> f32 {
21863 if x.is_nan() {
21864 if !signgamp.is_null() { *signgamp = 1; }
21865 return x;
21866 }
21867 if x == 0.0 {
21868 if !signgamp.is_null() { *signgamp = if x.is_sign_negative() { -1 } else { 1 }; }
21869 feraiseexcept(FE_DIVBYZERO);
21870 return f32::INFINITY;
21871 }
21872 let (r, sign) = libm::lgammaf_r(x);
21873 if !signgamp.is_null() { *signgamp = sign; }
21874 r
21875}
21876
21877#[no_mangle]
21878pub unsafe extern "C" fn lgammal_r(x: f64, signgamp: *mut i32) -> f64 {
21879 lgamma_r(x, signgamp)
21880}
21881
21882#[no_mangle]
21887pub unsafe extern "C" fn islessequal(x: f64, y: f64) -> i32 {
21888 if x.is_nan() || y.is_nan() { 0 } else { (x <= y) as i32 }
21889}
21890
21891#[no_mangle]
21892pub unsafe extern "C" fn islessequalf(x: f32, y: f32) -> i32 {
21893 if x.is_nan() || y.is_nan() { 0 } else { (x <= y) as i32 }
21894}
21895
21896#[no_mangle]
21897pub unsafe extern "C" fn islessgreater(x: f64, y: f64) -> i32 {
21898 if x.is_nan() || y.is_nan() { 0 } else { (x < y || x > y) as i32 }
21899}
21900
21901#[no_mangle]
21902pub unsafe extern "C" fn islessgreaterf(x: f32, y: f32) -> i32 {
21903 if x.is_nan() || y.is_nan() { 0 } else { (x < y || x > y) as i32 }
21904}
21905
21906#[no_mangle]
21907pub unsafe extern "C" fn isgreater(x: f64, y: f64) -> i32 {
21908 if x.is_nan() || y.is_nan() { 0 } else { (x > y) as i32 }
21909}
21910
21911#[no_mangle]
21912pub unsafe extern "C" fn isgreaterf(x: f32, y: f32) -> i32 {
21913 if x.is_nan() || y.is_nan() { 0 } else { (x > y) as i32 }
21914}
21915
21916#[no_mangle]
21917pub unsafe extern "C" fn isgreaterequal(x: f64, y: f64) -> i32 {
21918 if x.is_nan() || y.is_nan() { 0 } else { (x >= y) as i32 }
21919}
21920
21921#[no_mangle]
21922pub unsafe extern "C" fn isgreaterequalf(x: f32, y: f32) -> i32 {
21923 if x.is_nan() || y.is_nan() { 0 } else { (x >= y) as i32 }
21924}
21925
21926#[no_mangle]
21931pub unsafe extern "C" fn stpcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char {
21932 let mut d = dest;
21933 let mut s = src;
21934 while *s != 0 {
21935 *d = *s;
21936 d = d.add(1);
21937 s = s.add(1);
21938 }
21939 *d = 0;
21940 d
21941}
21942
21943#[no_mangle]
21944pub unsafe extern "C" fn stpncpy(dest: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
21945 let mut i = 0;
21946 while i < n && *src.add(i) != 0 {
21947 *dest.add(i) = *src.add(i);
21948 i += 1;
21949 }
21950 let end = dest.add(i);
21951 while i < n {
21952 *dest.add(i) = 0;
21953 i += 1;
21954 }
21955 end
21956}
21957
21958#[no_mangle]
21959pub unsafe extern "C" fn strchrnul(s: *const c_char, c: c_int) -> *mut c_char {
21960 let mut p = s;
21961 while *p != 0 && *p as c_int != c {
21962 p = p.add(1);
21963 }
21964 p as *mut c_char
21965}
21966
21967#[no_mangle]
21968pub unsafe extern "C" fn fstatat(dirfd: c_int, path: *const c_char, buf: *mut Stat, flags: c_int) -> c_int {
21969 let r = sys_newfstatat(dirfd, path, buf as *mut u8, flags);
21970 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21971}
21972
21973#[no_mangle]
21974pub unsafe extern "C" fn execvpe(
21975 file: *const c_char,
21976 argv: *const *const c_char,
21977 envp: *const *const c_char,
21978) -> c_int {
21979 ERRNO!() = ENOENT_VAL;
21980 if file.is_null() || *file == 0 {
21981 return -1;
21982 }
21983 let mut p = file;
21984 while *p != 0 {
21985 if *p == b'/' as c_char {
21986 return execve(file, argv, envp);
21987 }
21988 p = p.add(1);
21989 }
21990 let file_len = crate::strlen(file);
21991 let path = crate::getenv(b"PATH\0".as_ptr() as *const c_char);
21992 let default_path = b"/usr/local/bin:/bin:/usr/bin\0";
21993 let path = if path.is_null() { default_path.as_ptr() as *const c_char } else { path };
21994
21995 let mut seen_eacces = false;
21996 let mut buf = [0 as c_char; 4096];
21997 let mut dir = path;
21998 loop {
21999 let mut end = dir;
22000 while *end != 0 && *end != b':' as c_char { end = end.add(1); }
22001 let dlen = end.offset_from(dir) as usize;
22002 let need_slash = dlen > 0;
22004 let total = dlen + need_slash as usize + file_len;
22005 if total < buf.len() {
22006 let mut i = 0;
22007 while i < dlen { buf[i] = *dir.add(i); i += 1; }
22008 if need_slash { buf[i] = b'/' as c_char; i += 1; }
22009 let mut j = 0;
22010 while j < file_len { buf[i + j] = *file.add(j); j += 1; }
22011 buf[i + j] = 0;
22012 execve(buf.as_ptr(), argv, envp);
22013 match ERRNO!() {
22014 13 => seen_eacces = true, 2 | 20 => {} _ => return -1,
22017 }
22018 }
22019 if *end == 0 { break; }
22020 dir = end.add(1);
22021 }
22022 ERRNO!() = if seen_eacces { 13 } else { 2 };
22023 -1
22024}
22025
22026#[no_mangle]
22029pub unsafe extern "C" fn strcoll_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int {
22030 strcoll(s1, s2)
22031}
22032
22033#[no_mangle]
22034pub unsafe extern "C" fn strxfrm_l(dest: *mut c_char, src: *const c_char, n: usize, _loc: locale_t) -> usize {
22035 strxfrm(dest, src, n)
22036}
22037
22038#[no_mangle]
22039pub unsafe extern "C" fn strerror_l(errnum: c_int, _loc: locale_t) -> *mut c_char {
22040 strerror(errnum)
22041}
22042
22043#[no_mangle]
22044pub unsafe extern "C" fn strcasecmp_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int {
22045 strcasecmp(s1, s2)
22046}
22047
22048#[no_mangle]
22049pub unsafe extern "C" fn strncasecmp_l(s1: *const c_char, s2: *const c_char, n: usize, _loc: locale_t) -> c_int {
22050 strncasecmp(s1, s2, n)
22051}
22052
22053#[no_mangle]
22054pub unsafe extern "C" fn strftime_l(s: *mut c_char, max: usize, fmt: *const c_char, tm: *const tm, _loc: locale_t) -> usize {
22055 strftime(s, max, fmt, tm)
22056}
22057
22058#[no_mangle]
22059pub unsafe extern "C" fn nl_langinfo_l(item: c_int, _loc: locale_t) -> *mut c_char {
22060 nl_langinfo(item)
22061}
22062
22063#[no_mangle]
22064pub unsafe extern "C" fn wcscoll_l(s1: *const u32, s2: *const u32, _loc: locale_t) -> c_int {
22065 wcscoll(s1, s2)
22066}
22067
22068#[no_mangle]
22069pub unsafe extern "C" fn wcsxfrm_l(dst: *mut wchar_t, src: *const wchar_t, n: usize, _loc: locale_t) -> usize {
22070 wcsxfrm(dst, src, n)
22071}
22072
22073#[no_mangle]
22074pub unsafe extern "C" fn wcsftime_l(s: *mut u32, max: usize, fmt: *const u32, tm: *const c_void, _loc: locale_t) -> usize {
22075 wcsftime(s, max, fmt, tm)
22076}
22077
22078#[no_mangle]
22079pub unsafe extern "C" fn wctype_l(name: *const c_char, _loc: locale_t) -> wctype_t {
22080 wctype(name)
22081}
22082
22083#[no_mangle]
22084pub unsafe extern "C" fn wctrans_l(name: *const c_char, _loc: locale_t) -> wctrans_t {
22085 wctrans(name)
22086}
22087
22088#[no_mangle]
22089pub unsafe extern "C" fn towlower_l(c: wint_t, _loc: locale_t) -> wint_t {
22090 towlower(c)
22091}
22092
22093#[no_mangle]
22094pub unsafe extern "C" fn towupper_l(c: wint_t, _loc: locale_t) -> wint_t {
22095 towupper(c)
22096}
22097
22098#[no_mangle]
22099pub unsafe extern "C" fn towctrans_l(c: wint_t, desc: wctrans_t, _loc: locale_t) -> wint_t {
22100 towctrans(c, desc)
22101}
22102
22103#[no_mangle] pub unsafe extern "C" fn iswalnum_l(c: wint_t, _l: locale_t) -> c_int { iswalnum(c) }
22104#[no_mangle] pub unsafe extern "C" fn iswalpha_l(c: wint_t, _l: locale_t) -> c_int { iswalpha(c) }
22105#[no_mangle] pub unsafe extern "C" fn iswblank_l(c: wint_t, _l: locale_t) -> c_int { iswblank(c) }
22106#[no_mangle] pub unsafe extern "C" fn iswcntrl_l(c: wint_t, _l: locale_t) -> c_int { iswcntrl(c) }
22107#[no_mangle] pub unsafe extern "C" fn iswdigit_l(c: wint_t, _l: locale_t) -> c_int { iswdigit(c) }
22108#[no_mangle] pub unsafe extern "C" fn iswgraph_l(c: wint_t, _l: locale_t) -> c_int { iswgraph(c) }
22109#[no_mangle] pub unsafe extern "C" fn iswlower_l(c: wint_t, _l: locale_t) -> c_int { iswlower(c) }
22110#[no_mangle] pub unsafe extern "C" fn iswprint_l(c: wint_t, _l: locale_t) -> c_int { iswprint(c) }
22111#[no_mangle] pub unsafe extern "C" fn iswpunct_l(c: wint_t, _l: locale_t) -> c_int { iswpunct(c) }
22112#[no_mangle] pub unsafe extern "C" fn iswspace_l(c: wint_t, _l: locale_t) -> c_int { iswspace(c) }
22113#[no_mangle] pub unsafe extern "C" fn iswupper_l(c: wint_t, _l: locale_t) -> c_int { iswupper(c) }
22114#[no_mangle] pub unsafe extern "C" fn iswxdigit_l(c: wint_t, _l: locale_t) -> c_int { iswxdigit(c) }
22115#[no_mangle] pub unsafe extern "C" fn iswctype_l(c: wint_t, desc: wctype_t, _l: locale_t) -> c_int { iswctype(c, desc) }
22116
22117#[no_mangle] pub unsafe extern "C" fn __isoc99_scanf(fmt: *const c_char, args: ...) -> c_int { vfscanf(stdin, fmt, args) }
22119#[no_mangle] pub unsafe extern "C" fn __isoc99_fscanf(f: *mut FILE, fmt: *const c_char, args: ...) -> c_int { vfscanf(f, fmt, args) }
22120#[no_mangle] pub unsafe extern "C" fn __isoc99_sscanf(s: *const c_char, fmt: *const c_char, args: ...) -> c_int { vsscanf(s, fmt, args) }
22121#[no_mangle] pub unsafe extern "C" fn __isoc99_vscanf(fmt: *const c_char, args: VaList) -> c_int { vfscanf(stdin, fmt, args) }
22122#[no_mangle] pub unsafe extern "C" fn __isoc99_vfscanf(f: *mut FILE, fmt: *const c_char, args: VaList) -> c_int { vfscanf(f, fmt, args) }
22123#[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) }
22124#[no_mangle] pub unsafe extern "C" fn __isoc99_wscanf(fmt: *const wchar_t, args: ...) -> c_int { vfwscanf(stdin, fmt, args) }
22125#[no_mangle] pub unsafe extern "C" fn __isoc99_fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int { vfwscanf(f, fmt, args) }
22126#[no_mangle] pub unsafe extern "C" fn __isoc99_swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int { vswscanf(s, fmt, args) }
22127#[no_mangle] pub unsafe extern "C" fn __isoc99_vwscanf(fmt: *const wchar_t, args: VaList) -> c_int { vfwscanf(stdin, fmt, args) }
22128#[no_mangle] pub unsafe extern "C" fn __isoc99_vfwscanf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int { vfwscanf(f, fmt, args) }
22129#[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) }
22130
22131#[no_mangle] pub unsafe extern "C" fn clearerr_unlocked(f: *mut FILE) { clearerr(f) }
22134#[no_mangle] pub unsafe extern "C" fn feof_unlocked(f: *mut FILE) -> c_int { feof(f) }
22135#[no_mangle] pub unsafe extern "C" fn ferror_unlocked(f: *mut FILE) -> c_int { ferror(f) }
22136#[no_mangle] pub unsafe extern "C" fn fileno_unlocked(f: *mut FILE) -> c_int { fileno(f) }
22137#[no_mangle] pub unsafe extern "C" fn fflush_unlocked(f: *mut FILE) -> c_int { fflush(f) }
22138#[no_mangle] pub unsafe extern "C" fn fgetc_unlocked(f: *mut FILE) -> c_int { fgetc(f) }
22139#[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) }
22140#[no_mangle] pub unsafe extern "C" fn fputc_unlocked(c: c_int, f: *mut FILE) -> c_int { fputc(c, f) }
22141#[no_mangle] pub unsafe extern "C" fn fputs_unlocked(s: *const c_char, f: *mut FILE) -> c_int { fputs(s, f) }
22142#[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) }
22143#[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) }
22144#[no_mangle] pub unsafe extern "C" fn fgetwc_unlocked(f: *mut FILE) -> wint_t { fgetwc(f) }
22145#[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) }
22146#[no_mangle] pub unsafe extern "C" fn fputwc_unlocked(c: wchar_t, f: *mut FILE) -> wint_t { fputwc(c, f) }
22147#[no_mangle] pub unsafe extern "C" fn fputws_unlocked(s: *const wchar_t, f: *mut FILE) -> c_int { fputws(s, f) }
22148#[no_mangle] pub unsafe extern "C" fn getwc_unlocked(f: *mut c_void) -> wint_t { getwc(f) }
22149#[no_mangle] pub unsafe extern "C" fn putwc_unlocked(c: u32, f: *mut c_void) -> wint_t { putwc(c, f) }
22150#[no_mangle] pub unsafe extern "C" fn getwchar_unlocked() -> wint_t { getwchar() }
22151#[no_mangle] pub unsafe extern "C" fn putwchar_unlocked(c: wchar_t) -> wint_t { putwchar(c) }
22152#[no_mangle] pub unsafe extern "C" fn fpurge(f: *mut FILE) { clearerr(f) }
22153#[no_mangle] pub unsafe extern "C" fn _IO_getc(f: *mut FILE) -> c_int { getc(f) }
22154#[no_mangle] pub unsafe extern "C" fn _IO_putc(c: c_int, f: *mut FILE) -> c_int { putc(c, f) }
22155#[no_mangle] pub unsafe extern "C" fn _IO_getc_unlocked(f: *mut FILE) -> c_int { getc(f) }
22156#[no_mangle] pub unsafe extern "C" fn _IO_putc_unlocked(c: c_int, f: *mut FILE) -> c_int { putc(c, f) }
22157#[no_mangle] pub unsafe extern "C" fn _IO_feof_unlocked(f: *mut FILE) -> c_int { feof(f) }
22158#[no_mangle] pub unsafe extern "C" fn _IO_ferror_unlocked(f: *mut FILE) -> c_int { ferror(f) }
22159
22160#[no_mangle] pub unsafe extern "C" fn __getauxval(t: c_ulong) -> c_ulong { getauxval(t) }
22162#[no_mangle] pub unsafe extern "C" fn __longjmp(env: *const c_ulong, val: c_int) -> ! { longjmp(env, val) }
22163#[no_mangle] pub unsafe extern "C" fn bsd_signal(sig: c_int, handler: usize) -> usize { signal(sig, handler) }
22164#[no_mangle] pub unsafe extern "C" fn __sysv_signal(sig: c_int, handler: usize) -> usize { signal(sig, handler) }
22165#[no_mangle] pub unsafe extern "C" fn eaccess(path: *const c_char, mode: c_int) -> c_int { access(path, mode) }
22166#[no_mangle] pub unsafe extern "C" fn __xpg_basename(path: *mut c_char) -> *mut c_char { basename(path) }
22167#[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) }
22168#[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) }
22169
22170#[no_mangle]
22175pub unsafe extern "C" fn cfsetspeed(termios_p: *mut c_void, speed: u32) -> c_int {
22176 let r = cfsetispeed(termios_p, speed);
22177 if r != 0 { return r; }
22178 cfsetospeed(termios_p, speed)
22179}
22180
22181#[no_mangle]
22182pub unsafe extern "C" fn futimesat(dirfd: c_int, path: *const c_char, times: *const timeval) -> c_int {
22183 if times.is_null() {
22184 return utimensat(dirfd, path, core::ptr::null(), 0);
22185 }
22186 let tv = times as *const [timeval; 2];
22187 let mut ts: [timespec; 2] = [
22188 timespec { tv_sec: (*tv)[0].tv_sec, tv_nsec: (*tv)[0].tv_usec * 1000 },
22189 timespec { tv_sec: (*tv)[1].tv_sec, tv_nsec: (*tv)[1].tv_usec * 1000 },
22190 ];
22191 for t in &mut ts {
22192 if t.tv_nsec < 0 || t.tv_nsec >= 1_000_000_000 {
22193 ERRNO!() = EINVAL;
22194 return -1;
22195 }
22196 }
22197 utimensat(dirfd, path, ts.as_ptr(), 0)
22198}
22199
22200#[no_mangle]
22201pub unsafe extern "C" fn membarrier(cmd: c_int, flags: c_int, cpu_id: c_int) -> c_int {
22202 <Arch as Syscalls>::syscall3(SYS_MEMBARRIER, cmd as i64, flags as i64, cpu_id as i64) as c_int
22203}
22204
22205#[no_mangle]
22206pub unsafe extern "C" fn mremap(
22207 old_address: *mut c_void,
22208 old_size: usize,
22209 new_size: usize,
22210 flags: c_int,
22211 mut args: ...
22212) -> *mut c_void {
22213 let new_address = if flags & 2 != 0 { args.next_arg::<*mut c_void>() } else { core::ptr::null_mut() };
22214 let r = <Arch as Syscalls>::syscall5(
22215 SYS_MREMAP,
22216 old_address as i64,
22217 old_size as i64,
22218 new_size as i64,
22219 flags as i64,
22220 new_address as i64,
22221 );
22222 if r < 0 {
22223 ERRNO!() = (-r) as c_int;
22224 return (-1isize) as *mut c_void;
22225 }
22226 r as *mut c_void
22227}
22228
22229#[no_mangle]
22230pub unsafe extern "C" fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: usize) -> c_int {
22231 let name = ptsname(fd);
22232 if name.is_null() { return -1; }
22233 let n = crate::strlen(name);
22234 if n + 1 > buflen {
22235 ERRNO!() = ERANGE_VAL;
22236 return ERANGE_VAL;
22237 }
22238 core::ptr::copy_nonoverlapping(name, buf, n + 1);
22239 0
22240}
22241
22242#[no_mangle]
22243pub unsafe extern "C" fn posix_getdents(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize {
22244 if flags != 0 {
22245 ERRNO!() = EINVAL;
22246 return -1;
22247 }
22248 let r = <Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, buf as i64, len as i64);
22249 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22250}
22251
22252#[no_mangle]
22253pub unsafe extern "C" fn riscv_flush_icache(start: *mut c_void, end: *mut c_void, flags: c_ulong) -> c_int {
22254 #[cfg(target_arch = "riscv64")]
22255 {
22256 let r = <Arch as Syscalls>::syscall3(259, start as i64, end as i64, flags as i64);
22257 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22258 }
22259 #[cfg(not(target_arch = "riscv64"))]
22260 {
22261 let _ = (start, end, flags);
22262 0
22263 }
22264}
22265
22266#[no_mangle]
22267pub unsafe extern "C" fn __riscv_flush_icache(start: *mut c_void, end: *mut c_void, flags: c_ulong) -> c_int {
22268 riscv_flush_icache(start, end, flags)
22269}
22270
22271#[no_mangle]
22272pub unsafe extern "C" fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int {
22273 let fd = mkstemps(template, suffixlen);
22274 if fd >= 0 && flags & O_CLOEXEC != 0 {
22275 sys_fcntl(fd, F_SETFD, FD_CLOEXEC as i64);
22276 }
22277 fd
22278}
22279
22280#[no_mangle]
22281pub unsafe extern "C" fn statfs(path: *const c_char, buf: *mut c_void) -> c_int {
22282 let r = <Arch as Syscalls>::syscall2(SYS_STATFS, path as i64, buf as i64);
22283 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22284}
22285
22286#[no_mangle]
22287pub unsafe extern "C" fn fstatfs(fd: c_int, buf: *mut c_void) -> c_int {
22288 let r = <Arch as Syscalls>::syscall2(SYS_FSTATFS, fd as i64, buf as i64);
22289 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22290}
22291
22292#[no_mangle]
22293pub unsafe extern "C" fn sysinfo(info: *mut c_void) -> c_int {
22294 let r = <Arch as Syscalls>::syscall1(SYS_SYSINFO, info as i64);
22295 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22296}
22297
22298#[no_mangle]
22299pub unsafe extern "C" fn pthread_tryjoin_np(thread: PthreadT, retval: *mut *mut c_void) -> c_int {
22300 let slot = thread as *mut Thread;
22301 if slot.is_null() { return EINVAL; }
22302 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
22303 let tid = core::ptr::read_volatile(&raw const (*slot).tid);
22304 if tid > 0 { return EBUSY; }
22305 if tid < 0 { return EINVAL; }
22306 pthread_join(thread, retval)
22307}
22308
22309#[no_mangle]
22310pub unsafe extern "C" fn pthread_timedjoin_np(thread: PthreadT, retval: *mut *mut c_void, abstime: *const timespec) -> c_int {
22311 let slot = thread as *mut Thread;
22312 if slot.is_null() { return EINVAL; }
22313 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
22314 loop {
22315 let r = pthread_tryjoin_np(thread, retval);
22316 if r != EBUSY { return r; }
22317 let tid = core::ptr::read_volatile(&raw const (*slot).tid);
22318 if tid <= 0 { continue; }
22319 let e = futex_timedwait(&raw mut (*slot).tid, tid, abstime);
22320 if e == ETIMEDOUT { return ETIMEDOUT; }
22321 }
22322}
22323
22324
22325#[repr(C)]
22328pub struct UtmpExit {
22329 pub e_termination: i16,
22330 pub e_exit: i16,
22331}
22332
22333#[repr(C)]
22334pub struct Utmpx {
22335 pub ut_type: i16,
22336 pub __ut_pad1: i16,
22337 pub ut_pid: i32,
22338 pub ut_line: [c_char; 32],
22339 pub ut_id: [c_char; 4],
22340 pub ut_user: [c_char; 32],
22341 pub ut_host: [c_char; 256],
22342 pub ut_exit: UtmpExit,
22343 pub ut_session: i32,
22344 pub __ut_pad2: i32,
22345 pub ut_tv: timeval,
22346 pub ut_addr_v6: [u32; 4],
22347 pub __unused: [u8; 20],
22348}
22349
22350const UTMP_SIZE: usize = 400;
22351const _: [(); UTMP_SIZE] = [(); core::mem::size_of::<Utmpx>()];
22352
22353static mut UTMP_FD: c_int = -1;
22354static mut UTMP_PATH: [u8; 256] = [0; 256];
22355static mut UTMP_PATH_SET: bool = false;
22356#[repr(align(8))]
22357struct UtmpBuf([u8; UTMP_SIZE]);
22358static mut UTMP_BUF: UtmpBuf = UtmpBuf([0; UTMP_SIZE]);
22359
22360unsafe fn utmp_path_ptr() -> *const c_char {
22361 if !UTMP_PATH_SET {
22362 let default = b"/var/run/utmp\0";
22363 let mut i = 0;
22364 while i < default.len() && i < UTMP_PATH.len() {
22365 UTMP_PATH[i] = default[i];
22366 i += 1;
22367 }
22368 UTMP_PATH_SET = true;
22369 }
22370 UTMP_PATH.as_ptr() as *const c_char
22371}
22372
22373unsafe fn utmp_open_read() -> c_int {
22374 if UTMP_FD >= 0 {
22375 crate::close(UTMP_FD);
22376 }
22377 UTMP_FD = crate::open(utmp_path_ptr(), 0, 0);
22378 UTMP_FD
22379}
22380
22381unsafe fn utmp_open_append() -> c_int {
22382 crate::open(utmp_path_ptr(), 1 | 64 | 1024, 0o644)
22383}
22384
22385#[no_mangle]
22386pub unsafe extern "C" fn setutent() {
22387 let _ = utmp_open_read();
22388}
22389
22390#[no_mangle]
22391pub unsafe extern "C" fn endutent() {
22392 if UTMP_FD >= 0 {
22393 crate::close(UTMP_FD);
22394 UTMP_FD = -1;
22395 }
22396}
22397
22398#[no_mangle]
22399pub unsafe extern "C" fn getutent() -> *mut c_void {
22400 if UTMP_FD < 0 && utmp_open_read() < 0 {
22401 return core::ptr::null_mut();
22402 }
22403 let n = crate::read(UTMP_FD, UTMP_BUF.0.as_mut_ptr() as *mut c_void, UTMP_SIZE);
22404 if n == UTMP_SIZE as isize {
22405 UTMP_BUF.0.as_mut_ptr() as *mut c_void
22406 } else {
22407 core::ptr::null_mut()
22408 }
22409}
22410
22411unsafe fn utmp_id_eq(a: &[c_char; 4], b: &[c_char; 4]) -> bool {
22412 a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]
22413}
22414
22415unsafe fn utmp_line_eq(a: &[c_char; 32], b: &[c_char; 32]) -> bool {
22416 let mut i = 0;
22417 while i < 32 {
22418 if a[i] != b[i] { return false; }
22419 if a[i] == 0 { return true; }
22420 i += 1;
22421 }
22422 true
22423}
22424
22425#[no_mangle]
22426pub unsafe extern "C" fn getutid(ut: *const c_void) -> *mut c_void {
22427 if ut.is_null() { return core::ptr::null_mut(); }
22428 let want = &*(ut as *const Utmpx);
22429 loop {
22430 let p = getutent();
22431 if p.is_null() { return p; }
22432 let cur = &*(p as *const Utmpx);
22433 let matched = match want.ut_type {
22434 1 | 2 | 3 | 4 => cur.ut_type == want.ut_type,
22435 _ => utmp_id_eq(&cur.ut_id, &want.ut_id)
22436 && (want.ut_type == 0 || cur.ut_type == want.ut_type),
22437 };
22438 if matched { return p; }
22439 }
22440}
22441
22442#[no_mangle]
22443pub unsafe extern "C" fn getutline(ut: *const c_void) -> *mut c_void {
22444 if ut.is_null() { return core::ptr::null_mut(); }
22445 let want = &*(ut as *const Utmpx);
22446 loop {
22447 let p = getutent();
22448 if p.is_null() { return p; }
22449 if utmp_line_eq(&(*(p as *const Utmpx)).ut_line, &want.ut_line) {
22450 return p;
22451 }
22452 }
22453}
22454
22455#[no_mangle]
22456pub unsafe extern "C" fn pututline(ut: *const c_void) -> *mut c_void {
22457 if ut.is_null() { return core::ptr::null_mut(); }
22458 let fd = utmp_open_append();
22459 if fd < 0 { return core::ptr::null_mut(); }
22460 let n = crate::write(fd, ut, UTMP_SIZE);
22461 crate::close(fd);
22462 if n == UTMP_SIZE as isize { ut as *mut c_void } else { core::ptr::null_mut() }
22463}
22464
22465#[no_mangle]
22466pub unsafe extern "C" fn updwtmp(file: *const c_char, ut: *const c_void) {
22467 if file.is_null() || ut.is_null() { return; }
22468 let fd = crate::open(file, 1 | 64 | 1024, 0o644);
22469 if fd >= 0 {
22470 let _ = crate::write(fd, ut, UTMP_SIZE);
22471 crate::close(fd);
22472 }
22473}
22474
22475unsafe fn utmp_set_name(file: *const c_char) -> c_int {
22476 if file.is_null() { return -1; }
22477 let len = crate::strlen(file);
22478 if len + 1 > UTMP_PATH.len() { return -1; }
22479 if UTMP_FD >= 0 {
22480 crate::close(UTMP_FD);
22481 UTMP_FD = -1;
22482 }
22483 core::ptr::copy_nonoverlapping(file, UTMP_PATH.as_mut_ptr() as *mut c_char, len + 1);
22484 UTMP_PATH_SET = true;
22485 0
22486}
22487
22488#[no_mangle]
22489pub unsafe extern "C" fn utmpname(file: *const c_char) -> c_int { utmp_set_name(file) }
22490
22491#[no_mangle]
22492pub unsafe extern "C" fn utmpxname(file: *const c_char) -> c_int { utmp_set_name(file) }
22493
22494
22495#[no_mangle] pub static mut ___environ: *mut *mut c_char = core::ptr::null_mut();
22497#[no_mangle] pub static mut _environ: *mut *mut c_char = core::ptr::null_mut();
22498#[no_mangle] pub unsafe extern "C" fn __freelocale(loc: locale_t) { freelocale(loc) }
22499#[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) }
22500#[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) }
22501#[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) }
22502#[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) }
22503
22504#[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) }
22505#[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) }
22506#[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) }
22507#[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) }
22508#[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) }
22509#[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) }
22510
22511const MAX_NS: usize = 3;
22516const MAX_SEARCH: usize = 6;
22517const HOST_NOT_FOUND: c_int = 1;
22518const TRY_AGAIN: c_int = 2;
22519const NO_RECOVERY: c_int = 3;
22520const NO_DATA: c_int = 4;
22521
22522static mut NS_COUNT: usize = 0;
22523static mut NS_ADDRS: [u32; MAX_NS] = [0; MAX_NS];
22524static mut SEARCH_COUNT: usize = 0;
22525static mut SEARCH_DOMAINS: [[u8; 256]; MAX_SEARCH] = [[0; 256]; MAX_SEARCH];
22526static mut RESOLV_INITIALIZED: bool = false;
22527
22528#[repr(C)]
22529struct SockAddrIn {
22530 sin_family: u16,
22531 sin_port: u16,
22532 sin_addr: u32,
22533 sin_zero: [u8; 8],
22534}
22535
22536#[repr(C)]
22537struct PollFd {
22538 fd: c_int,
22539 events: i16,
22540 revents: i16,
22541}
22542
22543unsafe fn resolv_skip_ws(line: &[u8], mut i: usize) -> usize {
22544 while i < line.len() && (line[i] == b' ' || line[i] == b'\t') { i += 1; }
22545 i
22546}
22547
22548unsafe fn resolv_token<'a>(line: &'a [u8], mut i: usize) -> (&'a [u8], usize) {
22549 let start = i;
22550 while i < line.len() && line[i] != b' ' && line[i] != b'\t' && line[i] != b'#' { i += 1; }
22551 (&line[start..i], i)
22552}
22553
22554unsafe fn resolv_parse_config() -> c_int {
22555 RESOLV_INITIALIZED = true;
22556 NS_COUNT = 0;
22557 SEARCH_COUNT = 0;
22558 let path = b"/etc/resolv.conf\0";
22559 let fd = crate::open(path.as_ptr() as *const c_char, 0, 0);
22560 if fd < 0 { return -1; }
22561 let mut buf = [0u8; 4096];
22562 let n = crate::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len());
22563 crate::close(fd);
22564 if n <= 0 { return -1; }
22565 let len = n as usize;
22566 let mut i = 0;
22567 while i < len {
22568 let start = i;
22569 while i < len && buf[i] != b'\n' { i += 1; }
22570 let line = &buf[start..i];
22571 i += 1;
22572 let mut j = resolv_skip_ws(line, 0);
22573 if j >= line.len() || line[j] == b'#' { continue; }
22574 let (key, next) = resolv_token(line, j);
22575 j = next;
22576 if key == b"nameserver" {
22577 j = resolv_skip_ws(line, j);
22578 let (tok, _) = resolv_token(line, j);
22579 if !tok.is_empty() && NS_COUNT < MAX_NS {
22580 let mut name = [0u8; 64];
22581 let l = core::cmp::min(tok.len(), 63);
22582 name[..l].copy_from_slice(&tok[..l]);
22583 let addr = crate::inet_addr(name.as_ptr() as *const c_char);
22584 if addr != u32::MAX {
22585 NS_ADDRS[NS_COUNT] = addr;
22586 NS_COUNT += 1;
22587 }
22588 }
22589 } else if key == b"search" || key == b"domain" {
22590 loop {
22591 j = resolv_skip_ws(line, j);
22592 if j >= line.len() || line[j] == b'#' { break; }
22593 let (tok, next) = resolv_token(line, j);
22594 j = next;
22595 if tok.is_empty() { break; }
22596 if SEARCH_COUNT < MAX_SEARCH {
22597 let l = core::cmp::min(tok.len(), 255);
22598 SEARCH_DOMAINS[SEARCH_COUNT][..l].copy_from_slice(&tok[..l]);
22599 SEARCH_DOMAINS[SEARCH_COUNT][l] = 0;
22600 SEARCH_COUNT += 1;
22601 }
22602 if key == b"domain" { break; }
22603 }
22604 }
22605 }
22606 0
22607}
22608
22609#[no_mangle]
22610pub unsafe extern "C" fn res_init() -> c_int {
22611 let _ = resolv_parse_config();
22612 0
22613}
22614
22615#[no_mangle]
22616pub unsafe extern "C" fn res_mkquery(
22617 op: c_int,
22618 dname: *const c_char,
22619 class: c_int,
22620 type_: c_int,
22621 _data: *const u8,
22622 _datalen: c_int,
22623 _newrr: *const u8,
22624 buf: *mut u8,
22625 buflen: c_int,
22626) -> c_int {
22627 if dname.is_null() || buf.is_null() { return -1; }
22628 let mut l = crate::strnlen(dname as *const u8, 255);
22629 if l > 0 && *dname.add(l - 1) == b'.' as c_char { l -= 1; }
22630 if l > 0 && *dname.add(l - 1) == b'.' as c_char { return -1; }
22631 let n = 17 + l + if l != 0 { 1 } else { 0 };
22632 if l > 253 || buflen < n as c_int || op < 0 || op > 15 || class < 0 || class > 255 || type_ < 0 || type_ > 255 {
22633 return -1;
22634 }
22635 let mut q = [0u8; 280];
22636 crate::memset(q.as_mut_ptr() as *mut c_void, 0, n);
22637 q[2] = (op * 8 + 1) as u8;
22638 q[3] = 32;
22639 q[5] = 1;
22640 core::ptr::copy_nonoverlapping(dname as *const u8, q.as_mut_ptr().add(13), l);
22641 let mut i = 13;
22642 while q[i] != 0 {
22643 let mut j = i;
22644 while q[j] != 0 && q[j] != b'.' { j += 1; }
22645 if j - i - 1 > 62 { return -1; }
22646 q[i - 1] = (j - i) as u8;
22647 i = j + 1;
22648 }
22649 q[i + 1] = type_ as u8;
22650 q[i + 3] = class as u8;
22651 let mut ts = timespec { tv_sec: 0, tv_nsec: 0 };
22652 let _ = clock_gettime(CLOCK_REALTIME, &mut ts);
22653 let id = (((ts.tv_nsec as u64) + (ts.tv_nsec as u64) / 65536) & 0xffff) as u16;
22654 q[0] = (id >> 8) as u8;
22655 q[1] = id as u8;
22656 core::ptr::copy_nonoverlapping(q.as_ptr(), buf, n);
22657 n as c_int
22658}
22659
22660unsafe fn res_send_inner(msg: *const u8, msglen: c_int, answer: *mut u8, anslen: c_int) -> c_int {
22661 if msg.is_null() || answer.is_null() || msglen < 12 || anslen < 12 { return -1; }
22662 if !RESOLV_INITIALIZED { let _ = resolv_parse_config(); }
22663 if NS_COUNT == 0 {
22664 h_errno = TRY_AGAIN;
22665 return -1;
22666 }
22667 for n in 0..NS_COUNT {
22668 let fd = crate::socket(AF_INET, SOCK_DGRAM, 0);
22669 if fd < 0 { continue; }
22670 let sa = SockAddrIn {
22671 sin_family: AF_INET as u16,
22672 sin_port: 53u16.to_be(),
22673 sin_addr: NS_ADDRS[n],
22674 sin_zero: [0; 8],
22675 };
22676 let sent = crate::sendto(fd, msg as *const c_void, msglen as usize, 0, &sa as *const SockAddrIn as *const crate::sockaddr, 16);
22677 if sent != msglen as isize {
22678 crate::close(fd);
22679 continue;
22680 }
22681 let mut pfd = PollFd { fd, events: 1, revents: 0 };
22682 let pr = crate::poll(&mut pfd as *mut PollFd as *mut c_void, 1, 5000);
22683 if pr <= 0 {
22684 crate::close(fd);
22685 continue;
22686 }
22687 let r = crate::recvfrom(fd, answer as *mut c_void, anslen as usize, 0, core::ptr::null_mut(), core::ptr::null_mut());
22688 crate::close(fd);
22689 if r >= 12 {
22690 let id_ok = *answer == *msg && *answer.add(1) == *msg.add(1);
22691 let qr = (*answer.add(2) & 0x80) != 0;
22692 if id_ok && qr {
22693 return r as c_int;
22694 }
22695 }
22696 }
22697 h_errno = TRY_AGAIN;
22698 -1
22699}
22700
22701#[no_mangle]
22702pub unsafe extern "C" fn res_send(msg: *const u8, msglen: c_int, answer: *mut u8, anslen: c_int) -> c_int {
22703 if anslen < 512 {
22704 let mut buf = [0u8; 512];
22705 let r = res_send_inner(msg, msglen, buf.as_mut_ptr(), 512);
22706 if r >= 0 {
22707 let copy = core::cmp::min(r, anslen) as usize;
22708 if copy > 0 { core::ptr::copy_nonoverlapping(buf.as_ptr(), answer, copy); }
22709 }
22710 return r;
22711 }
22712 res_send_inner(msg, msglen, answer, anslen)
22713}
22714
22715#[no_mangle]
22716pub unsafe extern "C" fn res_query(
22717 dname: *const c_char,
22718 class: c_int,
22719 type_: c_int,
22720 answer: *mut u8,
22721 anslen: c_int,
22722) -> c_int {
22723 let mut q = [0u8; 280];
22724 let ql = res_mkquery(0, dname, class, type_, core::ptr::null(), 0, core::ptr::null(), q.as_mut_ptr(), q.len() as c_int);
22725 if ql < 0 { return ql; }
22726 let r = res_send(q.as_ptr(), ql, answer, anslen);
22727 if r < 12 {
22728 h_errno = TRY_AGAIN;
22729 return -1;
22730 }
22731 let rcode = answer.add(3).read() & 0x0f;
22732 if rcode == 3 {
22733 h_errno = HOST_NOT_FOUND;
22734 return -1;
22735 }
22736 if rcode == 0 && *answer.add(6) == 0 && *answer.add(7) == 0 {
22737 h_errno = NO_DATA;
22738 return -1;
22739 }
22740 if rcode != 0 {
22741 h_errno = NO_RECOVERY;
22742 return -1;
22743 }
22744 r
22745}
22746
22747#[no_mangle]
22748pub unsafe extern "C" fn res_querydomain(
22749 name: *const c_char,
22750 domain: *const c_char,
22751 class: c_int,
22752 type_: c_int,
22753 answer: *mut u8,
22754 anslen: c_int,
22755) -> c_int {
22756 if domain.is_null() || *domain == 0 { return res_query(name, class, type_, answer, anslen); }
22757 let mut buf = [0u8; 512];
22758 let nl = crate::strlen(name);
22759 let dl = crate::strlen(domain);
22760 if nl + 1 + dl >= buf.len() { return -1; }
22761 core::ptr::copy_nonoverlapping(name, buf.as_mut_ptr() as *mut c_char, nl);
22762 buf[nl] = b'.';
22763 core::ptr::copy_nonoverlapping(domain, buf.as_mut_ptr().add(nl + 1) as *mut c_char, dl);
22764 buf[nl + 1 + dl] = 0;
22765 res_query(buf.as_ptr() as *const c_char, class, type_, answer, anslen)
22766}
22767
22768#[no_mangle]
22769pub unsafe extern "C" fn res_search(
22770 name: *const c_char,
22771 class: c_int,
22772 type_: c_int,
22773 answer: *mut u8,
22774 anslen: c_int,
22775) -> c_int {
22776 if name.is_null() { return -1; }
22777 if !RESOLV_INITIALIZED { let _ = resolv_parse_config(); }
22778 let len = crate::strlen(name);
22779 let mut dots = 0;
22780 for i in 0..len {
22781 if *name.add(i) == b'.' as c_char { dots += 1; }
22782 }
22783 let trailing_dot = len > 0 && *name.add(len - 1) == b'.' as c_char;
22784 if trailing_dot || dots >= 1 {
22785 let r = res_query(name, class, type_, answer, anslen);
22786 if r >= 0 { return r; }
22787 if trailing_dot { return -1; }
22788 }
22789 for i in 0..SEARCH_COUNT {
22790 let dom = SEARCH_DOMAINS[i].as_ptr() as *const c_char;
22791 let r = res_querydomain(name, dom, class, type_, answer, anslen);
22792 if r >= 0 { return r; }
22793 if h_errno != HOST_NOT_FOUND && h_errno != NO_DATA { return -1; }
22794 }
22795 if dots == 0 {
22796 return res_query(name, class, type_, answer, anslen);
22797 }
22798 -1
22799}
22800
22801#[repr(C)]
22806pub struct HostEnt {
22807 pub h_name: *mut c_char,
22808 pub h_aliases: *mut *mut c_char,
22809 pub h_addrtype: c_int,
22810 pub h_length: c_int,
22811 pub h_addr_list: *mut *mut c_char,
22812}
22813
22814#[repr(C)]
22815pub struct AddrInfo {
22816 pub ai_flags: c_int,
22817 pub ai_family: c_int,
22818 pub ai_socktype: c_int,
22819 pub ai_protocol: c_int,
22820 pub ai_addrlen: u32,
22821 pub ai_addr: *mut c_void,
22822 pub ai_canonname: *mut c_char,
22823 pub ai_next: *mut AddrInfo,
22824}
22825
22826static mut HOST_ENT: HostEnt = HostEnt {
22827 h_name: core::ptr::null_mut(),
22828 h_aliases: core::ptr::null_mut(),
22829 h_addrtype: 0,
22830 h_length: 0,
22831 h_addr_list: core::ptr::null_mut(),
22832};
22833static mut HOST_NAME: [c_char; 256] = [0; 256];
22834static mut HOST_ALIASES: [*mut c_char; 1] = [core::ptr::null_mut()];
22835static mut HOST_ADDR: [u8; 16] = [0; 16];
22836static mut HOST_ADDR_PTRS: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
22837
22838unsafe fn dns_skip_name(p: *const u8, end: *const u8) -> *const u8 {
22839 let mut q = p;
22840 while q < end {
22841 let c = *q;
22842 if c == 0 { return q.add(1); }
22843 if c & 0xc0 == 0xc0 { return q.add(2); }
22844 q = q.add(1 + c as usize);
22845 }
22846 end
22847}
22848
22849unsafe fn dns_read_u16(p: *const u8) -> u16 {
22850 ((*p as u16) << 8) | *p.add(1) as u16
22851}
22852
22853unsafe fn dns_expand_name(p: *const u8, msg: *const u8, out: *mut c_char, outlen: usize) -> bool {
22854 let mut q = p;
22855 let mut o = 0usize;
22856 let mut jumps = 0;
22857 loop {
22858 let c = *q;
22859 if c == 0 {
22860 if o < outlen { *out.add(o) = 0; }
22861 return true;
22862 }
22863 if c & 0xc0 == 0xc0 {
22864 let off = (((c & 0x3f) as usize) << 8) | *q.add(1) as usize;
22865 q = msg.add(off);
22866 jumps += 1;
22867 if jumps > 16 { return false; }
22868 continue;
22869 }
22870 let l = c as usize;
22871 if l > 63 { return false; }
22872 if o + l + 1 >= outlen { return false; }
22873 core::ptr::copy_nonoverlapping(q.add(1), out.add(o) as *mut u8, l);
22874 o += l;
22875 *out.add(o) = b'.' as c_char;
22876 o += 1;
22877 q = q.add(1 + l);
22878 }
22879}
22880
22881unsafe fn host_from_answer(answer: *const u8, len: c_int, af: c_int) -> *mut HostEnt {
22882 if len < 12 { return core::ptr::null_mut(); }
22883 let end = answer.add(len as usize);
22884 let qd = dns_read_u16(answer.add(4)) as usize;
22885 let an = dns_read_u16(answer.add(6)) as usize;
22886 let mut p = answer.add(12);
22887 for _ in 0..qd {
22888 p = dns_skip_name(p, end);
22889 p = p.add(4);
22890 }
22891 let want_type: u16 = if af == AF_INET6 { 28 } else { 1 };
22892 let want_len = if af == AF_INET6 { 16 } else { 4 };
22893 for _ in 0..an {
22894 p = dns_skip_name(p, end);
22895 if p.add(10) > end { break; }
22896 let typ = dns_read_u16(p);
22897 let class = dns_read_u16(p.add(2));
22898 let rdlen = dns_read_u16(p.add(8)) as usize;
22899 let rdata = p.add(10);
22900 if rdata.add(rdlen) > end { break; }
22901 if typ == want_type && class == 1 && rdlen == want_len {
22902 core::ptr::copy_nonoverlapping(rdata, HOST_ADDR.as_mut_ptr(), want_len);
22903 HOST_ENT.h_addrtype = af;
22904 HOST_ENT.h_length = want_len as c_int;
22905 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
22906 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
22907 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
22908 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
22909 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22910 h_errno = 0;
22911 return &raw mut HOST_ENT;
22912 }
22913 p = rdata.add(rdlen);
22914 }
22915 core::ptr::null_mut()
22916}
22917
22918#[no_mangle]
22919pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut HostEnt {
22920 gethostbyname2(name, AF_INET)
22921}
22922
22923#[no_mangle]
22924pub unsafe extern "C" fn gethostbyname2(name: *const c_char, af: c_int) -> *mut HostEnt {
22925 if name.is_null() { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22926 let mut addr = [0u8; 16];
22927 let addrlen = if af == AF_INET6 { 16 } else { 4 };
22928 if inet_pton(af, name, addr.as_mut_ptr() as *mut c_void) == 1 {
22929 core::ptr::copy_nonoverlapping(addr.as_ptr(), HOST_ADDR.as_mut_ptr(), addrlen);
22930 let n = crate::strlen(name);
22931 let l = core::cmp::min(n, 255);
22932 core::ptr::copy_nonoverlapping(name, HOST_NAME.as_mut_ptr(), l);
22933 HOST_NAME[l] = 0;
22934 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22935 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
22936 HOST_ENT.h_addrtype = af;
22937 HOST_ENT.h_length = addrlen as c_int;
22938 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
22939 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
22940 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
22941 h_errno = 0;
22942 return &raw mut HOST_ENT;
22943 }
22944 let mut answer = [0u8; 512];
22945 let qtype = if af == AF_INET6 { 28 } else { 1 };
22946 let r = res_query(name, 1, qtype, answer.as_mut_ptr(), answer.len() as c_int);
22947 if r < 0 {
22948 if h_errno == 0 { h_errno = TRY_AGAIN; }
22949 return core::ptr::null_mut();
22950 }
22951 let ent = host_from_answer(answer.as_ptr(), r, af);
22952 if !ent.is_null() {
22953 let n = crate::strlen(name);
22954 let l = core::cmp::min(n, 255);
22955 core::ptr::copy_nonoverlapping(name, HOST_NAME.as_mut_ptr(), l);
22956 HOST_NAME[l] = 0;
22957 } else {
22958 h_errno = HOST_NOT_FOUND;
22959 }
22960 ent
22961}
22962
22963#[no_mangle]
22964pub unsafe extern "C" fn gethostbyaddr(addr: *const c_void, len: u32, type_: c_int) -> *mut HostEnt {
22965 if addr.is_null() || type_ != AF_INET || len != 4 { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22966 let a = addr as *const u8;
22967 let mut name = [0u8; 128];
22968 let mut pos = 0;
22969 for i in 0..4 {
22970 let v = *a.add(3 - i) as u32;
22971 if v >= 100 { name[pos] = b'0' + (v / 100) as u8; pos += 1; }
22972 if v >= 10 { name[pos] = b'0' + ((v / 10) % 10) as u8; pos += 1; }
22973 name[pos] = b'0' + (v % 10) as u8; pos += 1;
22974 name[pos] = b'.'; pos += 1;
22975 }
22976 let suffix = b"in-addr.arpa";
22977 for &c in suffix { name[pos] = c; pos += 1; }
22978 name[pos] = 0;
22979 let mut answer = [0u8; 512];
22980 let r = res_query(name.as_ptr() as *const c_char, 1, 12, answer.as_mut_ptr(), answer.len() as c_int);
22981 if r < 12 { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22982 let end = answer.as_ptr().add(r as usize);
22983 let qd = dns_read_u16(answer.as_ptr().add(4)) as usize;
22984 let an = dns_read_u16(answer.as_ptr().add(6)) as usize;
22985 let mut p = answer.as_ptr().add(12);
22986 for _ in 0..qd { p = dns_skip_name(p, end); p = p.add(4); }
22987 for _ in 0..an {
22988 p = dns_skip_name(p, end);
22989 if p.add(10) > end { break; }
22990 let typ = dns_read_u16(p);
22991 let rdlen = dns_read_u16(p.add(8)) as usize;
22992 let rdata = p.add(10);
22993 if typ == 12 && dns_expand_name(rdata, answer.as_ptr(), HOST_NAME.as_mut_ptr(), HOST_NAME.len()) {
22994 let mut o = crate::strlen(HOST_NAME.as_ptr());
22995 if o > 0 && HOST_NAME[o - 1] == b'.' as c_char { o -= 1; }
22996 HOST_NAME[o] = 0;
22997 core::ptr::copy_nonoverlapping(a, HOST_ADDR.as_mut_ptr(), 4);
22998 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22999 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
23000 HOST_ENT.h_addrtype = AF_INET;
23001 HOST_ENT.h_length = 4;
23002 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
23003 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
23004 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
23005 h_errno = 0;
23006 return &raw mut HOST_ENT;
23007 }
23008 p = rdata.add(rdlen);
23009 }
23010 h_errno = HOST_NOT_FOUND;
23011 core::ptr::null_mut()
23012}
23013
23014#[inline]
23019fn sysno(x86_64: i64, generic: i64) -> i64 {
23020 if cfg!(target_arch = "x86_64") { x86_64 } else { generic }
23021}
23022
23023#[no_mangle]
23024pub unsafe extern "C" fn settimeofday(tv: *const c_void, tz: *const c_void) -> c_int {
23025 let r = <Arch as Syscalls>::syscall2(sysno(164, 170), tv as i64, tz as i64);
23026 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
23027}
23028
23029#[no_mangle]
23030pub unsafe extern "C" fn stime(t: *const i64) -> c_int {
23031 if t.is_null() { ERRNO!() = EINVAL; return -1; }
23032 let tv = timeval { tv_sec: *t, tv_usec: 0 };
23033 settimeofday(&tv as *const timeval as *const c_void, core::ptr::null())
23034}
23035
23036#[no_mangle]
23037pub unsafe extern "C" fn times(buf: *mut c_void) -> c_long {
23038 let r = <Arch as Syscalls>::syscall1(sysno(100, 153), buf as i64);
23039 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_long }
23040}
23041
23042#[no_mangle]
23043pub 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 {
23044 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);
23045 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
23046}
23047
23048#[no_mangle]
23049pub unsafe extern "C" fn tee(fd_in: c_int, fd_out: c_int, len: usize, flags: u32) -> isize {
23050 let r = <Arch as Syscalls>::syscall4(sysno(276, 77), fd_in as i64, fd_out as i64, len as i64, flags as i64);
23051 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
23052}
23053
23054#[no_mangle]
23055pub unsafe extern "C" fn statx(dirfd: c_int, path: *const c_char, flags: c_int, mask: u32, buf: *mut c_void) -> c_int {
23056 let r = <Arch as Syscalls>::syscall5(sysno(332, 291), dirfd as i64, path as i64, flags as i64, mask as i64, buf as i64);
23057 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
23058}
23059
23060#[no_mangle]
23061pub unsafe extern "C" fn setns(fd: c_int, nstype: c_int) -> c_int {
23062 let r = <Arch as Syscalls>::syscall2(SYS_SETNS, fd as i64, nstype as i64);
23063 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
23064}
23065
23066#[no_mangle]
23067pub unsafe extern "C" fn setfsuid(uid: u32) -> c_int {
23068 <Arch as Syscalls>::syscall1(sysno(122, 151), uid as i64) as c_int
23069}
23070
23071#[no_mangle]
23072pub unsafe extern "C" fn setfsgid(gid: u32) -> c_int {
23073 <Arch as Syscalls>::syscall1(sysno(123, 152), gid as i64) as c_int
23074}
23075
23076#[no_mangle]
23077pub unsafe extern "C" fn setregid(rgid: u32, egid: u32) -> c_int {
23078 let r = <Arch as Syscalls>::syscall2(sysno(114, 143), rgid as i64, egid as i64);
23079 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
23080}
23081
23082#[no_mangle]
23083pub 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 {
23084 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);
23085 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
23086}
23087
23088#[no_mangle]
23089pub 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 {
23090 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);
23091 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
23092}
23093
23094#[no_mangle]
23095pub unsafe extern "C" fn tcgetwinsize(fd: c_int, ws: *mut c_void) -> c_int {
23096 if fd < 0 || ws.is_null() { ERRNO!() = EINVAL; return -1; }
23097 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5413, ws as i64);
23098 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
23099}
23100
23101#[no_mangle]
23102pub unsafe extern "C" fn tcsetwinsize(fd: c_int, ws: *const c_void) -> c_int {
23103 if fd < 0 || ws.is_null() { ERRNO!() = EINVAL; return -1; }
23104 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5414, ws as i64);
23105 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
23106}
23107
23108#[no_mangle]
23109pub unsafe extern "C" fn sockatmark(fd: c_int) -> c_int {
23110 let mut at: c_int = 0;
23111 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x8905, &mut at as *mut c_int as i64);
23112 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { at }
23113}
23114
23115#[no_mangle]
23116pub unsafe extern "C" fn isastream(fd: c_int) -> c_int {
23117 let mut buf = [0u8; 64];
23118 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5401, buf.as_mut_ptr() as i64);
23119 if r < 0 { ERRNO!() = (-r) as c_int; 0 } else { 1 }
23120}
23121
23122#[no_mangle]
23123pub unsafe extern "C" fn posix_madvise(addr: *mut c_void, len: usize, advice: c_int) -> c_int {
23124 madvise(addr as *mut u8, len, advice)
23125}
23126
23127#[no_mangle]
23128pub unsafe extern "C" fn secure_getenv(name: *const c_char) -> *mut c_char {
23129 if getauxval(23) != 0 { return core::ptr::null_mut(); }
23130 getenv(name)
23131}
23132
23133#[no_mangle]
23134pub unsafe extern "C" fn sigandset(dest: *mut c_ulong, left: *const c_ulong, right: *const c_ulong) -> c_int {
23135 if dest.is_null() || left.is_null() || right.is_null() { return -1; }
23136 *dest = *left & *right;
23137 0
23138}
23139
23140#[no_mangle]
23141pub unsafe extern "C" fn sigorset(dest: *mut c_ulong, left: *const c_ulong, right: *const c_ulong) -> c_int {
23142 if dest.is_null() || left.is_null() || right.is_null() { return -1; }
23143 *dest = *left | *right;
23144 0
23145}
23146
23147#[no_mangle]
23148pub unsafe extern "C" fn sigisemptyset(set: *const c_ulong) -> c_int {
23149 if set.is_null() { return 1; }
23150 (*set == 0) as c_int
23151}
23152
23153#[no_mangle]
23154pub unsafe extern "C" fn sighold(sig: c_int) -> c_int {
23155 let set: c_ulong = 1u64 << (sig - 1) as u32;
23156 sigprocmask(0, &set, core::ptr::null_mut());
23157 0
23158}
23159
23160#[no_mangle]
23161pub unsafe extern "C" fn sigignore(sig: c_int) -> c_int {
23162 let _ = signal(sig, 1);
23163 0
23164}
23165
23166#[no_mangle]
23167pub unsafe extern "C" fn sigrelse(sig: c_int) -> c_int {
23168 let set: c_ulong = 1u64 << (sig - 1) as u32;
23169 sigprocmask(1, &set, core::ptr::null_mut());
23170 0
23171}
23172
23173#[no_mangle]
23174pub unsafe extern "C" fn siginterrupt(sig: c_int, flag: c_int) -> c_int {
23175 let mut sa: sigaction = core::mem::zeroed();
23176 if sigaction(sig, core::ptr::null(), &mut sa) != 0 { return -1; }
23177 if flag != 0 { sa.sa_flags &= !(SA_RESTART as c_int); } else { sa.sa_flags |= SA_RESTART as c_int; }
23178 sigaction(sig, &sa, core::ptr::null_mut())
23179}
23180
23181#[no_mangle]
23182pub unsafe extern "C" fn sigpause(sig: c_int) -> c_int {
23183 let set: c_ulong = 1u64 << (sig - 1) as u32;
23184 sigsuspend(&set)
23185}
23186
23187#[no_mangle]
23188pub unsafe extern "C" fn semtimedop(semid: c_int, sops: *mut c_void, nsops: usize, timeout: *const timespec) -> c_int {
23189 let r = <Arch as Syscalls>::syscall4(sysno(220, 192), semid as i64, sops as i64, nsops as i64, timeout as i64);
23190 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
23191}
23192
23193#[no_mangle]
23194pub unsafe extern "C" fn wait3(status: *mut c_int, options: c_int, rusage: *mut c_void) -> i32 {
23195 wait4(-1, status, options, rusage) as i32
23196}
23197
23198#[no_mangle]
23199pub unsafe extern "C" fn tempnam(dir: *const c_char, pfx: *const c_char) -> *mut c_char {
23200 let mut path = [0 as c_char; 256];
23201 let mut i = 0;
23202 if !dir.is_null() {
23203 while *dir.add(i) != 0 && i < 200 { path[i] = *dir.add(i); i += 1; }
23204 if i > 0 && path[i-1] != b'/' as c_char { path[i] = b'/' as c_char; i += 1; }
23205 } else {
23206 for &c in b"/tmp/" { path[i] = c as c_char; i += 1; }
23207 }
23208 if !pfx.is_null() {
23209 let mut j = 0;
23210 while *pfx.add(j) != 0 && i < 220 { path[i] = *pfx.add(j); i += 1; j += 1; }
23211 }
23212 for &c in b"XXXXXX" { path[i] = c as c_char; i += 1; }
23213 path[i] = 0;
23214 let fd = mkstemp(path.as_mut_ptr());
23215 if fd < 0 { return core::ptr::null_mut(); }
23216 close(fd);
23217 unlink(path.as_ptr());
23218 let n = strlen(path.as_ptr());
23219 let out = malloc(n + 1) as *mut c_char;
23220 if out.is_null() { return core::ptr::null_mut(); }
23221 core::ptr::copy_nonoverlapping(path.as_ptr(), out, n + 1);
23222 out
23223}
23224
23225#[no_mangle]
23226pub unsafe extern "C" fn putwc(c: u32, f: *mut c_void) -> u32 {
23227 fputwc(c as c_int, f as *mut FILE) as u32
23228}
23229
23230#[no_mangle]
23231pub unsafe extern "C" fn __uflow(f: *mut c_void) -> c_int {
23232 fgetc(f as *mut FILE)
23233}
23234
23235#[no_mangle]
23236pub unsafe extern "C" fn __xmknod(_ver: c_int, path: *const c_char, mode: c_uint, dev: u64) -> c_int {
23237 mknod(path, mode, dev)
23238}
23239
23240#[no_mangle]
23241pub unsafe extern "C" fn __xmknodat(_ver: c_int, dirfd: c_int, path: *const c_char, mode: c_uint, dev: u64) -> c_int {
23242 mknodat(dirfd, path, mode, dev)
23243}
23244
23245#[no_mangle]
23246pub 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 {
23247 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);
23248 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
23249}
23250
23251#[no_mangle]
23252pub unsafe extern "C" fn open_by_handle_at(mount_fd: c_int, handle: *mut c_void, flags: c_int) -> c_int {
23253 let r = <Arch as Syscalls>::syscall3(sysno(304, 265), mount_fd as i64, handle as i64, flags as i64);
23254 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
23255}
23256
23257#[no_mangle]
23258pub unsafe extern "C" fn dn_skipname(comp: *const u8, eom: *const u8) -> c_int {
23259 let p = dns_skip_name(comp, eom);
23260 if p <= eom { (p as isize - comp as isize) as c_int } else { -1 }
23261}
23262
23263#[no_mangle]
23264pub 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 {
23265 if exp.is_null() || dst.is_null() || dstsiz <= 0 { return -1; }
23266 let mut o = 0usize;
23267 let mut p = exp;
23268 loop {
23269 let start = p;
23270 while *p != 0 && *p != b'.' as c_char { p = p.add(1); }
23271 let l = p as usize - start as usize;
23272 if l > 63 || o + l + 2 > dstsiz as usize { return -1; }
23273 *dst.add(o) = l as u8; o += 1;
23274 core::ptr::copy_nonoverlapping(start as *const u8, dst.add(o), l);
23275 o += l;
23276 if *p == 0 { break; }
23277 p = p.add(1);
23278 }
23279 if o + 1 > dstsiz as usize { return -1; }
23280 *dst.add(o) = 0;
23281 (o + 1) as c_int
23282}
23283
23284#[repr(C)]
23289#[derive(Copy, Clone)]
23290pub struct Spwd {
23291 pub sp_namp: *mut c_char,
23292 pub sp_pwdp: *mut c_char,
23293 pub sp_lstchg: c_long,
23294 pub sp_min: c_long,
23295 pub sp_max: c_long,
23296 pub sp_warn: c_long,
23297 pub sp_inact: c_long,
23298 pub sp_expire: c_long,
23299 pub sp_flag: c_ulong,
23300}
23301
23302static mut SPWD_ENT: Spwd = Spwd {
23303 sp_namp: core::ptr::null_mut(), sp_pwdp: core::ptr::null_mut(),
23304 sp_lstchg: 0, sp_min: 0, sp_max: 0, sp_warn: 0, sp_inact: 0,
23305 sp_expire: 0, sp_flag: 0,
23306};
23307static mut SPWD_BUF: [c_char; 1024] = [0; 1024];
23308static mut SPWD_FILE: *mut FILE = core::ptr::null_mut();
23309
23310unsafe fn parse_spwd(line: *const c_char, ent: *mut Spwd, buf: *mut c_char, buflen: usize) -> bool {
23311 let mut src = line;
23312 let mut o = 0usize;
23313 let mut fields: [*mut c_char; 9] = [core::ptr::null_mut(); 9];
23314 let mut n = 0usize;
23315 while n < 9 {
23316 let start = o;
23317 while *src != 0 && *src != b':' as c_char {
23318 if o + 1 >= buflen { return false; }
23319 *buf.add(o) = *src;
23320 o += 1;
23321 src = src.add(1);
23322 }
23323 *buf.add(o) = 0;
23324 o += 1;
23325 fields[n] = buf.add(start);
23326 n += 1;
23327 if *src == 0 { break; }
23328 src = src.add(1);
23329 }
23330 if n < 9 { return false; }
23331 (*ent).sp_namp = fields[0];
23332 (*ent).sp_pwdp = fields[1];
23333 (*ent).sp_lstchg = crate::strtol(fields[2], core::ptr::null_mut(), 10) as c_long;
23334 (*ent).sp_min = crate::strtol(fields[3], core::ptr::null_mut(), 10) as c_long;
23335 (*ent).sp_max = crate::strtol(fields[4], core::ptr::null_mut(), 10) as c_long;
23336 (*ent).sp_warn = crate::strtol(fields[5], core::ptr::null_mut(), 10) as c_long;
23337 (*ent).sp_inact = crate::strtol(fields[6], core::ptr::null_mut(), 10) as c_long;
23338 (*ent).sp_expire = crate::strtol(fields[7], core::ptr::null_mut(), 10) as c_long;
23339 (*ent).sp_flag = crate::strtoul(fields[8], core::ptr::null_mut(), 10) as c_ulong;
23340 true
23341}
23342
23343#[no_mangle]
23344pub unsafe extern "C" fn setspent() {
23345 endspent();
23346 SPWD_FILE = crate::fopen(b"/etc/shadow\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
23347}
23348
23349#[no_mangle]
23350pub unsafe extern "C" fn endspent() {
23351 if !SPWD_FILE.is_null() { crate::fclose(SPWD_FILE); SPWD_FILE = core::ptr::null_mut(); }
23352}
23353
23354#[no_mangle]
23355pub unsafe extern "C" fn getspent() -> *mut Spwd {
23356 if SPWD_FILE.is_null() { setspent(); if SPWD_FILE.is_null() { return core::ptr::null_mut(); } }
23357 let mut line = [0 as c_char; 1024];
23358 loop {
23359 if crate::fgets(line.as_mut_ptr(), 1024, SPWD_FILE).is_null() { return core::ptr::null_mut(); }
23360 if parse_spwd(line.as_ptr(), &raw mut SPWD_ENT, SPWD_BUF.as_mut_ptr(), SPWD_BUF.len()) {
23361 return &raw mut SPWD_ENT;
23362 }
23363 }
23364}
23365
23366#[no_mangle]
23367pub unsafe extern "C" fn fgetspent(f: *mut FILE) -> *mut Spwd {
23368 if f.is_null() { return core::ptr::null_mut(); }
23369 let mut line = [0 as c_char; 1024];
23370 loop {
23371 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
23372 if parse_spwd(line.as_ptr(), &raw mut SPWD_ENT, SPWD_BUF.as_mut_ptr(), SPWD_BUF.len()) {
23373 return &raw mut SPWD_ENT;
23374 }
23375 }
23376}
23377
23378#[no_mangle]
23379pub unsafe extern "C" fn getspnam(name: *const c_char) -> *mut Spwd {
23380 if name.is_null() { return core::ptr::null_mut(); }
23381 setspent();
23382 loop {
23383 let sp = getspent();
23384 if sp.is_null() { break; }
23385 if crate::strcmp((*sp).sp_namp as *const u8, name as *const u8) == 0 { endspent(); return sp; }
23386 }
23387 endspent();
23388 core::ptr::null_mut()
23389}
23390
23391#[no_mangle]
23392pub 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 {
23393 if result.is_null() { return EINVAL; }
23394 let p = getspnam(name);
23395 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *sp = *p; *result = sp; 0 }
23396}
23397
23398#[no_mangle]
23399pub unsafe extern "C" fn putspent(sp: *const Spwd, f: *mut FILE) -> c_int {
23400 if sp.is_null() || f.is_null() { return -1; }
23401 crate::fprintf(f, b"%s:%s:%ld:%ld:%ld:%ld:%ld:%ld:%lu\\n\0".as_ptr() as *const c_char,
23402 (*sp).sp_namp, (*sp).sp_pwdp, (*sp).sp_lstchg, (*sp).sp_min, (*sp).sp_max,
23403 (*sp).sp_warn, (*sp).sp_inact, (*sp).sp_expire, (*sp).sp_flag)
23404}
23405
23406#[no_mangle]
23407pub unsafe extern "C" fn getgrouplist(user: *const c_char, group: u32, groups: *mut u32, ngroups: *mut i32) -> c_int {
23408 if user.is_null() || groups.is_null() || ngroups.is_null() { return -1; }
23409 let max = *ngroups as usize;
23410 let mut n = 0usize;
23411 if n < max { *groups.add(n) = group; }
23412 n += 1;
23413 setgrent();
23414 loop {
23415 let g = getgrent();
23416 if g.is_null() { break; }
23417 if (*g).gr_gid == group { continue; }
23418 let mut found = false;
23419 let mut i = 0;
23420 while !(*(*g).gr_mem.add(i)).is_null() {
23421 if crate::strcmp(*(*g).gr_mem.add(i) as *const u8, user as *const u8) == 0 {
23422 found = true;
23423 break;
23424 }
23425 i += 1;
23426 }
23427 if found {
23428 if n < max { *groups.add(n) = (*g).gr_gid; }
23429 n += 1;
23430 }
23431 }
23432 endgrent();
23433 if n > max { *ngroups = n as i32; return -1; }
23434 *ngroups = n as i32;
23435 n as c_int
23436}