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
19include!("encoding_tables.rs");
20include!("math_helpers.rs");
21include!("math_bitmanip.rs");
22include!("math_sqrtfmod.rs");
23include!("math_trig.rs");
24include!("math_exp.rs");
25include!("math_log.rs");
26include!("math_pow.rs");
27include!("math_hypot.rs");
28include!("math_hyperbolic.rs");
29include!("math_invtrig.rs");
30include!("math_lrint.rs");
31include!("math_long_double.rs");
32
33const EILSEQ: c_int = 84;
38const EINVAL: c_int = 22;
39const EFAULT: c_int = 14;
40const E2BIG: c_int = 7;
41
42const LC_CTYPE: c_int = 0;
43const LC_NUMERIC: c_int = 1;
44const LC_TIME: c_int = 2;
45const LC_COLLATE: c_int = 3;
46const LC_MONETARY: c_int = 4;
47const LC_MESSAGES: c_int = 5;
48const LC_ALL: c_int = 6;
49const ENOMEM: c_int = 12;
50const EINTR: c_int = 4;
51const EPERM: c_int = 1;
52const EAGAIN: c_int = 11;
53const EBUSY: c_int = 16;
54const EDEADLK: c_int = 35;
55const ETIMEDOUT: c_int = 110;
56const ECANCELED: c_int = 125;
57const EOVERFLOW: c_int = 75;
58const EOWNERDEAD: c_int = 130;
59const ENOTRECOVERABLE: c_int = 131;
60
61static mut ERRNO: c_int = 0;
62
63#[no_mangle]
64pub unsafe extern "C" fn __errno_location() -> *mut c_int {
65 core::ptr::addr_of_mut!(ERRNO)
66}
67
68#[cfg(not(test))]
69#[panic_handler]
70fn panic(_: &core::panic::PanicInfo) -> ! {
71 loop {}
72}
73
74#[cfg(not(test))]
76#[no_mangle]
77pub extern "C" fn rust_eh_personality() {}
78
79const PROT_READ: i32 = 1;
84const PROT_WRITE: i32 = 2;
85const MAP_SHARED: i32 = 0x01;
86const MAP_PRIVATE: i32 = 0x02;
87const MAP_ANONYMOUS: i32 = 0x20;
88
89trait Syscalls {
94 unsafe fn syscall0(n: i64) -> i64;
95 unsafe fn syscall1(n: i64, a1: i64) -> i64;
96 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64;
97 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64;
98 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64;
99 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64;
100 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64;
101 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> !;
102}
103
104struct X86_64;
105struct Aarch64;
106struct Riscv64;
107
108#[cfg(target_arch = "x86_64")]
109impl Syscalls for X86_64 {
110 #[inline(always)]
111 unsafe fn syscall0(n: i64) -> i64 {
112 let result: i64;
113 core::arch::asm!(
114 "syscall",
115 inlateout("rax") n => result,
116 lateout("rcx") _,
117 lateout("r11") _,
118 );
119 result
120 }
121 #[inline(always)]
122 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
123 let result: i64;
124 core::arch::asm!(
125 "syscall",
126 inlateout("rax") n => result,
127 in("rdi") a1,
128 lateout("rcx") _,
129 lateout("r11") _,
130 );
131 result
132 }
133 #[inline(always)]
134 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
135 let result: i64;
136 core::arch::asm!(
137 "syscall",
138 inlateout("rax") n => result,
139 in("rdi") a1,
140 in("rsi") a2,
141 lateout("rcx") _,
142 lateout("r11") _,
143 );
144 result
145 }
146 #[inline(always)]
147 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
148 let result: i64;
149 core::arch::asm!(
150 "syscall",
151 inlateout("rax") n => result,
152 in("rdi") a1,
153 in("rsi") a2,
154 in("rdx") a3,
155 lateout("rcx") _,
156 lateout("r11") _,
157 );
158 result
159 }
160 #[inline(always)]
161 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
162 let result: i64;
163 core::arch::asm!(
164 "syscall",
165 inlateout("rax") n => result,
166 in("rdi") a1,
167 in("rsi") a2,
168 in("rdx") a3,
169 in("r10") a4,
170 lateout("rcx") _,
171 lateout("r11") _,
172 );
173 result
174 }
175 #[inline(always)]
176 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
177 let result: i64;
178 core::arch::asm!(
179 "syscall",
180 inlateout("rax") n => result,
181 in("rdi") a1,
182 in("rsi") a2,
183 in("rdx") a3,
184 in("r10") a4,
185 in("r8") a5,
186 lateout("rcx") _,
187 lateout("r11") _,
188 );
189 result
190 }
191 #[inline(always)]
192 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
193 let result: i64;
194 core::arch::asm!(
195 "syscall",
196 inlateout("rax") n => result,
197 in("rdi") a1,
198 in("rsi") a2,
199 in("rdx") a3,
200 in("r10") a4,
201 in("r8") a5,
202 in("r9") a6,
203 lateout("rcx") _,
204 lateout("r11") _,
205 );
206 result
207 }
208 #[inline(always)]
209 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
210 core::arch::asm!(
211 "syscall",
212 in("rax") n,
213 in("rdi") a1,
214 options(noreturn)
215 );
216 }
217}
218
219#[cfg(target_arch = "aarch64")]
220impl Syscalls for Aarch64 {
221 #[inline(always)]
222 unsafe fn syscall0(n: i64) -> i64 {
223 let result: i64;
224 core::arch::asm!(
225 "svc #0",
226 inlateout("x8") n => _,
227 lateout("x0") result,
228 options(nostack),
229 );
230 result
231 }
232 #[inline(always)]
233 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
234 let result: i64;
235 core::arch::asm!(
236 "svc #0",
237 inlateout("x8") n => _,
238 inlateout("x0") a1 => result,
239 options(nostack),
240 );
241 result
242 }
243 #[inline(always)]
244 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
245 let result: i64;
246 core::arch::asm!(
247 "svc #0",
248 inlateout("x8") n => _,
249 inlateout("x0") a1 => result,
250 inlateout("x1") a2 => _,
251 options(nostack),
252 );
253 result
254 }
255 #[inline(always)]
256 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
257 let result: i64;
258 core::arch::asm!(
259 "svc #0",
260 inlateout("x8") n => _,
261 inlateout("x0") a1 => result,
262 inlateout("x1") a2 => _,
263 inlateout("x2") a3 => _,
264 options(nostack),
265 );
266 result
267 }
268 #[inline(always)]
269 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
270 let result: i64;
271 core::arch::asm!(
272 "svc #0",
273 inlateout("x8") n => _,
274 inlateout("x0") a1 => result,
275 inlateout("x1") a2 => _,
276 inlateout("x2") a3 => _,
277 inlateout("x3") a4 => _,
278 options(nostack),
279 );
280 result
281 }
282 #[inline(always)]
283 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
284 let result: i64;
285 core::arch::asm!(
286 "svc #0",
287 inlateout("x8") n => _,
288 inlateout("x0") a1 => result,
289 inlateout("x1") a2 => _,
290 inlateout("x2") a3 => _,
291 inlateout("x3") a4 => _,
292 inlateout("x4") a5 => _,
293 options(nostack),
294 );
295 result
296 }
297 #[inline(always)]
298 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
299 let result: i64;
300 core::arch::asm!(
301 "svc #0",
302 inlateout("x8") n => _,
303 inlateout("x0") a1 => result,
304 inlateout("x1") a2 => _,
305 inlateout("x2") a3 => _,
306 inlateout("x3") a4 => _,
307 inlateout("x4") a5 => _,
308 inlateout("x5") a6 => _,
309 options(nostack),
310 );
311 result
312 }
313 #[inline(always)]
314 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
315 core::arch::asm!(
316 "svc #0",
317 in("x8") n,
318 in("x0") a1,
319 options(noreturn, nostack),
320 );
321 }
322}
323
324#[cfg(target_arch = "riscv64")]
325impl Syscalls for Riscv64 {
326 #[inline(always)]
327 unsafe fn syscall0(n: i64) -> i64 {
328 let result: i64;
329 core::arch::asm!(
330 "ecall",
331 inlateout("a7") n => _,
332 lateout("a0") result,
333 options(nostack),
334 );
335 result
336 }
337 #[inline(always)]
338 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
339 let result: i64;
340 core::arch::asm!(
341 "ecall",
342 inlateout("a7") n => _,
343 inlateout("a0") a1 => result,
344 options(nostack),
345 );
346 result
347 }
348 #[inline(always)]
349 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
350 let result: i64;
351 core::arch::asm!(
352 "ecall",
353 inlateout("a7") n => _,
354 inlateout("a0") a1 => result,
355 inlateout("a1") a2 => _,
356 options(nostack),
357 );
358 result
359 }
360 #[inline(always)]
361 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
362 let result: i64;
363 core::arch::asm!(
364 "ecall",
365 inlateout("a7") n => _,
366 inlateout("a0") a1 => result,
367 inlateout("a1") a2 => _,
368 inlateout("a2") a3 => _,
369 options(nostack),
370 );
371 result
372 }
373 #[inline(always)]
374 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
375 let result: i64;
376 core::arch::asm!(
377 "ecall",
378 inlateout("a7") n => _,
379 inlateout("a0") a1 => result,
380 inlateout("a1") a2 => _,
381 inlateout("a2") a3 => _,
382 inlateout("a3") a4 => _,
383 options(nostack),
384 );
385 result
386 }
387 #[inline(always)]
388 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
389 let result: i64;
390 core::arch::asm!(
391 "ecall",
392 inlateout("a7") n => _,
393 inlateout("a0") a1 => result,
394 inlateout("a1") a2 => _,
395 inlateout("a2") a3 => _,
396 inlateout("a3") a4 => _,
397 inlateout("a4") a5 => _,
398 options(nostack),
399 );
400 result
401 }
402 #[inline(always)]
403 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
404 let result: i64;
405 core::arch::asm!(
406 "ecall",
407 inlateout("a7") n => _,
408 inlateout("a0") a1 => result,
409 inlateout("a1") a2 => _,
410 inlateout("a2") a3 => _,
411 inlateout("a3") a4 => _,
412 inlateout("a4") a5 => _,
413 inlateout("a5") a6 => _,
414 options(nostack),
415 );
416 result
417 }
418 #[inline(always)]
419 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
420 core::arch::asm!(
421 "ecall",
422 in("a7") n,
423 in("a0") a1,
424 options(noreturn, nostack),
425 );
426 }
427}
428
429#[cfg(target_arch = "x86_64")]
430type Arch = X86_64;
431#[cfg(target_arch = "aarch64")]
432type Arch = Aarch64;
433#[cfg(target_arch = "riscv64")]
434type Arch = Riscv64;
435
436
437
438#[cfg(target_arch = "x86_64")]
440mod sysnr {
441 pub const SYS_READ: i64 = 0;
442 pub const SYS_WRITE: i64 = 1;
443 pub const SYS_OPEN: i64 = 2;
444 pub const SYS_CLOSE: i64 = 3;
445 pub const SYS_STAT: i64 = 4;
446 pub const SYS_FSTAT: i64 = 5;
447 pub const SYS_LSEEK: i64 = 8;
448 pub const SYS_MMAP: i64 = 9;
449 pub const SYS_MUNMAP: i64 = 11;
450 pub const SYS_MPROTECT: i64 = 10;
451 pub const SYS_RT_SIGACTION: i64 = 13;
452 pub const SYS_RT_SIGPROCMASK: i64 = 14;
453 pub const SYS_IOCTL: i64 = 16;
454 pub const SYS_ACCESS: i64 = 21;
455 pub const SYS_SHMGET: i64 = 29;
456 pub const SYS_SHMAT: i64 = 30;
457 pub const SYS_SHMCTL: i64 = 31;
458 pub const SYS_DUP: i64 = 32;
459 pub const SYS_NANOSLEEP: i64 = 35;
460 pub const SYS_SETITIMER: i64 = 38;
461 pub const SYS_ALARM: i64 = 37;
462 pub const SYS_SOCKET: i64 = 41;
463 pub const SYS_CONNECT: i64 = 42;
464 pub const SYS_ACCEPT: i64 = 43;
465 pub const SYS_ACCEPT4: i64 = 288;
466 pub const SYS_SENDTO: i64 = 44;
467 pub const SYS_RECVFROM: i64 = 45;
468 pub const SYS_SENDMSG: i64 = 46;
469 pub const SYS_RECVMSG: i64 = 47;
470 pub const SYS_SHUTDOWN: i64 = 48;
471 pub const SYS_BIND: i64 = 49;
472 pub const SYS_LISTEN: i64 = 50;
473 pub const SYS_GETSOCKNAME: i64 = 51;
474 pub const SYS_SOCKETPAIR: i64 = 53;
475 pub const SYS_SETSOCKOPT: i64 = 54;
476 pub const SYS_EXECVE: i64 = 59;
477 pub const SYS_WAIT4: i64 = 61;
478 pub const SYS_KILL: i64 = 62;
479 pub const SYS_UNAME: i64 = 63;
480 pub const SYS_SEMGET: i64 = 64;
481 pub const SYS_SEMOP: i64 = 65;
482 pub const SYS_SEMCTL: i64 = 66;
483 pub const SYS_SHMDT: i64 = 67;
484 pub const SYS_MSGGET: i64 = 68;
485 pub const SYS_MSGSND: i64 = 69;
486 pub const SYS_MSGRCV: i64 = 70;
487 pub const SYS_MSGCTL: i64 = 71;
488 pub const SYS_FCNTL: i64 = 72;
489 pub const SYS_FSYNC: i64 = 74;
490 pub const SYS_TRUNCATE: i64 = 76;
491 pub const SYS_FTRUNCATE: i64 = 77;
492 pub const SYS_GETCWD: i64 = 79;
493 pub const SYS_CHDIR: i64 = 80;
494 pub const SYS_SYMLINK: i64 = 88;
495 pub const SYS_FCHMOD: i64 = 91;
496 pub const SYS_UMASK: i64 = 95;
497 pub const SYS_GETRLIMIT: i64 = 97;
498 pub const SYS_SETUID: i64 = 105;
499 pub const SYS_SETGID: i64 = 106;
500 pub const SYS_SETPGID: i64 = 109;
501 pub const SYS_GETGROUPS: i64 = 115;
502 pub const SYS_GETPGID: i64 = 121;
503 pub const SYS_GETSID: i64 = 124;
504 pub const SYS_RT_SIGPENDING: i64 = 127;
505 pub const SYS_RT_SIGTIMEDWAIT: i64 = 128;
506 pub const SYS_RT_SIGSUSPEND: i64 = 130;
507 pub const SYS_SIGALTSTACK: i64 = 131;
508 pub const SYS_SETRLIMIT: i64 = 160;
509 pub const SYS_SETHOSTNAME: i64 = 170;
510 pub const SYS_FUTEX: i64 = 202;
511 pub const SYS_CLOCK_GETTIME: i64 = 228;
512 pub const SYS_CLOCK_GETRES: i64 = 229;
513 pub const SYS_CLOCK_NANOSLEEP: i64 = 230;
514 pub const SYS_EXIT_GROUP: i64 = 231;
515 pub const SYS_TGKILL: i64 = 234;
516 pub const SYS_MKDIRAT: i64 = 258;
517 pub const SYS_NEWFSTATAT: i64 = 262;
518 pub const SYS_UNLINKAT: i64 = 263;
519 pub const SYS_LINKAT: i64 = 265;
520 pub const SYS_SYMLINKAT: i64 = 266;
521 pub const SYS_READLINKAT: i64 = 267;
522 pub const SYS_FCHMODAT: i64 = 268;
523 pub const SYS_SET_ROBUST_LIST: i64 = 273;
524 pub const SYS_UTIMENSAT: i64 = 280;
525 pub const SYS_OPENAT: i64 = 257;
526 pub const SYS_FACCESSAT: i64 = 269;
527 pub const SYS_DUP3: i64 = 292;
528 pub const SYS_PIPE2: i64 = 293;
529 pub const SYS_SYNCFS: i64 = 306;
530 pub const SYS_RENAMEAT2: i64 = 316;
531 pub const SYS_STATFS: i64 = 137;
532 pub const SYS_FSTATFS: i64 = 138;
533 pub const SYS_FDATASYNC: i64 = 75;
534 pub const SYS_PAUSE: i64 = 34;
535 pub const SYS_POLL: i64 = 7;
536 pub const SYS_PPOLL: i64 = 271;
537 pub const SYS_PSELECT6: i64 = 270;
538 pub const SYS_GETPID: i64 = 39;
539 pub const SYS_FORK: i64 = 57;
540 pub const SYS_EXIT: i64 = 60;
541 pub const SYS_GETPPID: i64 = 110;
542 pub const SYS_SETSID: i64 = 112;
543 pub const SYS_SYNC: i64 = 162;
544 pub const SYS_GETUID: i64 = 102;
545 pub const SYS_GETGID: i64 = 104;
546 pub const SYS_GETEUID: i64 = 107;
547 pub const SYS_GETEGID: i64 = 108;
548 pub const SYS_GETTID: i64 = 186;
549 pub const SYS_CLOCK_SETTIME: i64 = 227;
550 pub const SYS_CLONE: i64 = 56;
551 pub const SYS_PREAD64: i64 = 17;
552 pub const SYS_MREMAP: i64 = 25;
553 pub const SYS_SYSINFO: i64 = 99;
554 pub const SYS_MEMBARRIER: i64 = 324;
555 pub const SYS_VHANGUP: i64 = 153;
556 pub const SYS_VMSPLICE: i64 = 278;
557 pub const SYS_GETDENTS64: i64 = 217;
558 pub const SYS_EPOLL_CREATE: i64 = 232;
559 pub const SYS_EPOLL_CREATE1: i64 = 291;
560 pub const SYS_EPOLL_CTL: i64 = 233;
561 pub const SYS_EPOLL_WAIT: i64 = 234;
562 pub const SYS_EVENTFD2: i64 = 290;
563 pub const SYS_SIGNALFD4: i64 = 289;
564 pub const SYS_TIMERFD_CREATE: i64 = 283;
565 pub const SYS_TIMERFD_SETTIME: i64 = 286;
566 pub const SYS_TIMERFD_GETTIME: i64 = 287;
567 pub const SYS_PRCTL: i64 = 157;
568 pub const SYS_FALLOCATE: i64 = 285;
569 pub const SYS_FLOCK: i64 = 73;
570 pub const SYS_SETGROUPS: i64 = 116;
571 pub const SYS_SETRESUID: i64 = 117;
572 pub const SYS_SETRESGID: i64 = 119;
573 pub const SYS_GETRESUID: i64 = 118;
574 pub const SYS_GETRESGID: i64 = 120;
575 pub const SYS_MKNOD: i64 = 133;
576 pub const SYS_FCHDIR: i64 = 81;
577 pub const SYS_FCHOWN: i64 = 93;
578 pub const SYS_ACCT: i64 = 163;
579 pub const SYS_ADJTIMEX: i64 = 159;
580 pub const SYS_CAPGET: i64 = 125;
581 pub const SYS_CAPSET: i64 = 126;
582 pub const SYS_CHROOT: i64 = 161;
583 pub const SYS_COPY_FILE_RANGE: i64 = 326;
584 pub const SYS_DELETE_MODULE: i64 = 176;
585 pub const SYS_INIT_MODULE: i64 = 175;
586 pub const SYS_FCHOWNAT: i64 = 260;
587 pub const SYS_MKNODAT: i64 = 259;
588 pub const SYS_SETNS: i64 = 308;
589 pub const SYS_UNSHARE: i64 = 272;
590 pub const SYS_REBOOT: i64 = 169;
591 pub const SYS_NICE: i64 = 34;
592 pub const SYS_SETPRIORITY: i64 = 140;
593 pub const SYS_GETPRIORITY: i64 = 140;
594 pub const SYS_IOPERM: i64 = 173;
595 pub const SYS_IOPL: i64 = 172;
596 pub const SYS_SWAPON: i64 = 167;
597 pub const SYS_SWAPOFF: i64 = 168;
598 pub const SYS_MOUNT: i64 = 165;
599 pub const SYS_UMOUNT2: i64 = 166;
600 pub const SYS_PIVOT_ROOT: i64 = 155;
601 pub const SYS_SETTIMEOFDAY: i64 = 164;
602 pub const SYS_GETTIMEOFDAY: i64 = 96;
603}
604#[cfg(target_arch = "aarch64")]
605mod sysnr {
606 pub const SYS_READ: i64 = 63;
607 pub const SYS_WRITE: i64 = 64;
608 pub const SYS_CLOSE: i64 = 57;
610 pub const SYS_FSTAT: i64 = 80;
612 pub const SYS_LSEEK: i64 = 62;
613 pub const SYS_MMAP: i64 = 222;
614 pub const SYS_MUNMAP: i64 = 215;
615 pub const SYS_RT_SIGACTION: i64 = 134;
616 pub const SYS_RT_SIGPROCMASK: i64 = 135;
617 pub const SYS_IOCTL: i64 = 29;
618 pub const SYS_SHMGET: i64 = 194;
620 pub const SYS_SHMAT: i64 = 196;
621 pub const SYS_SHMCTL: i64 = 195;
622 pub const SYS_DUP: i64 = 23;
623 pub const SYS_NANOSLEEP: i64 = 101;
624 pub const SYS_SETITIMER: i64 = 103;
625 pub const SYS_SOCKET: i64 = 198;
627 pub const SYS_CONNECT: i64 = 203;
628 pub const SYS_ACCEPT: i64 = 202;
629 pub const SYS_SENDTO: i64 = 206;
630 pub const SYS_RECVFROM: i64 = 207;
631 pub const SYS_SHUTDOWN: i64 = 210;
632 pub const SYS_BIND: i64 = 200;
633 pub const SYS_LISTEN: i64 = 201;
634 pub const SYS_GETSOCKNAME: i64 = 204;
635 pub const SYS_SOCKETPAIR: i64 = 199;
636 pub const SYS_SETSOCKOPT: i64 = 208;
637 pub const SYS_EXECVE: i64 = 221;
638 pub const SYS_WAIT4: i64 = 260;
639 pub const SYS_KILL: i64 = 129;
640 pub const SYS_UNAME: i64 = 160;
641 pub const SYS_SEMGET: i64 = 190;
642 pub const SYS_SEMOP: i64 = 193;
643 pub const SYS_SEMCTL: i64 = 191;
644 pub const SYS_SHMDT: i64 = 197;
645 pub const SYS_MSGGET: i64 = 186;
646 pub const SYS_MSGSND: i64 = 189;
647 pub const SYS_MSGRCV: i64 = 188;
648 pub const SYS_MSGCTL: i64 = 187;
649 pub const SYS_FCNTL: i64 = 25;
650 pub const SYS_FSYNC: i64 = 82;
651 pub const SYS_TRUNCATE: i64 = 45;
652 pub const SYS_FTRUNCATE: i64 = 46;
653 pub const SYS_GETCWD: i64 = 17;
654 pub const SYS_CHDIR: i64 = 49;
655 pub const SYS_FCHMOD: i64 = 52;
657 pub const SYS_UMASK: i64 = 166;
658 pub const SYS_GETRLIMIT: i64 = 163;
659 pub const SYS_SETUID: i64 = 146;
660 pub const SYS_SETGID: i64 = 144;
661 pub const SYS_SETPGID: i64 = 154;
662 pub const SYS_GETGROUPS: i64 = 158;
663 pub const SYS_GETPGID: i64 = 155;
664 pub const SYS_GETSID: i64 = 156;
665 pub const SYS_RT_SIGPENDING: i64 = 136;
666 pub const SYS_RT_SIGTIMEDWAIT: i64 = 137;
667 pub const SYS_RT_SIGSUSPEND: i64 = 133;
668 pub const SYS_SIGALTSTACK: i64 = 132;
669 pub const SYS_SETRLIMIT: i64 = 164;
670 pub const SYS_SETHOSTNAME: i64 = 161;
671 pub const SYS_FUTEX: i64 = 98;
672 pub const SYS_CLOCK_GETTIME: i64 = 113;
673 pub const SYS_CLOCK_GETRES: i64 = 114;
674 pub const SYS_CLOCK_NANOSLEEP: i64 = 115;
675 pub const SYS_EXIT_GROUP: i64 = 94;
676 pub const SYS_TGKILL: i64 = 131;
677 pub const SYS_MKDIRAT: i64 = 34;
678 pub const SYS_NEWFSTATAT: i64 = 79;
679 pub const SYS_UNLINKAT: i64 = 35;
680 pub const SYS_LINKAT: i64 = 37;
681 pub const SYS_SYMLINKAT: i64 = 36;
682 pub const SYS_READLINKAT: i64 = 78;
683 pub const SYS_FCHMODAT: i64 = 53;
684 pub const SYS_SET_ROBUST_LIST: i64 = 99;
685 pub const SYS_UTIMENSAT: i64 = 88;
686 pub const SYS_OPENAT: i64 = 56;
687 pub const SYS_FACCESSAT: i64 = 48;
688 pub const SYS_DUP3: i64 = 24;
689 pub const SYS_PIPE2: i64 = 59;
690 pub const SYS_SYNCFS: i64 = 267;
691 pub const SYS_RENAMEAT2: i64 = 276;
692 pub const SYS_STATFS: i64 = 43;
693 pub const SYS_FSTATFS: i64 = 44;
694 pub const SYS_FDATASYNC: i64 = 83;
695 pub const SYS_GETPID: i64 = 172;
696 pub const SYS_EXIT: i64 = 93;
697 pub const SYS_GETPPID: i64 = 173;
698 pub const SYS_SETSID: i64 = 157;
699 pub const SYS_SYNC: i64 = 81;
700 pub const SYS_GETUID: i64 = 174;
701 pub const SYS_GETGID: i64 = 176;
702 pub const SYS_GETEUID: i64 = 175;
703 pub const SYS_GETEGID: i64 = 177;
704 pub const SYS_GETTID: i64 = 178;
705 pub const SYS_CLOCK_SETTIME: i64 = 112;
706 pub const SYS_CLONE: i64 = 220;
707 pub const SYS_PPOLL: i64 = 73;
708 pub const SYS_PREAD64: i64 = 67;
709 pub const SYS_MREMAP: i64 = 216;
710 pub const SYS_SYSINFO: i64 = 179;
711 pub const SYS_MEMBARRIER: i64 = 283;
712 pub const SYS_VHANGUP: i64 = 58;
713 pub const SYS_VMSPLICE: i64 = 75;
714 pub const SYS_GETTIMEOFDAY: i64 = 169;
715 pub const SYS_SETTIMEOFDAY: i64 = 170;
716 pub const SYS_ADJTIMEX: i64 = 171;
717 pub const SYS_EPOLL_CREATE1: i64 = 20;
718 pub const SYS_EPOLL_CTL: i64 = 21;
719 pub const SYS_EPOLL_WAIT: i64 = 22;
720 pub const SYS_EVENTFD2: i64 = 19;
721 pub const SYS_SIGNALFD4: i64 = 74;
722 pub const SYS_TIMERFD_CREATE: i64 = 85;
723 pub const SYS_TIMERFD_SETTIME: i64 = 86;
724 pub const SYS_TIMERFD_GETTIME: i64 = 87;
725 pub const SYS_ACCEPT4: i64 = 242;
726 pub const SYS_ACCT: i64 = 89;
727 pub const SYS_CAPGET: i64 = 90;
728 pub const SYS_CAPSET: i64 = 91;
729 pub const SYS_CHROOT: i64 = 51;
730 pub const SYS_COPY_FILE_RANGE: i64 = 285;
731 pub const SYS_DELETE_MODULE: i64 = 106;
732 pub const SYS_FALLOCATE: i64 = 47;
733 pub const SYS_FCHDIR: i64 = 50;
734 pub const SYS_FCHOWN: i64 = 55;
735 pub const SYS_FCHOWNAT: i64 = 54;
736 pub const SYS_FLOCK: i64 = 32;
737 pub const SYS_GETDENTS64: i64 = 61;
738 pub const SYS_GETPRIORITY: i64 = 141;
739 pub const SYS_GETRESGID: i64 = 150;
740 pub const SYS_GETRESUID: i64 = 148;
741 pub const SYS_INIT_MODULE: i64 = 105;
742 pub const SYS_MKNODAT: i64 = 33;
743 pub const SYS_MOUNT: i64 = 40;
744 pub const SYS_MPROTECT: i64 = 226;
745 pub const SYS_PIVOT_ROOT: i64 = 41;
746 pub const SYS_PRCTL: i64 = 167;
747 pub const SYS_PSELECT6: i64 = 72;
748 pub const SYS_REBOOT: i64 = 142;
749 pub const SYS_RECVMSG: i64 = 212;
750 pub const SYS_SENDMSG: i64 = 211;
751 pub const SYS_SETGROUPS: i64 = 159;
752 pub const SYS_SETNS: i64 = 268;
753 pub const SYS_SETPRIORITY: i64 = 140;
754 pub const SYS_SETRESGID: i64 = 149;
755 pub const SYS_SETRESUID: i64 = 147;
756 pub const SYS_SWAPOFF: i64 = 225;
757 pub const SYS_SWAPON: i64 = 224;
758 pub const SYS_UMOUNT2: i64 = 39;
759 pub const SYS_UNSHARE: i64 = 97;
760}
761#[cfg(target_arch = "riscv64")]
763mod sysnr {
764 pub const SYS_READ: i64 = 63;
765 pub const SYS_WRITE: i64 = 64;
766 pub const SYS_CLOSE: i64 = 57;
767 pub const SYS_FSTAT: i64 = 80;
768 pub const SYS_LSEEK: i64 = 62;
769 pub const SYS_MMAP: i64 = 222;
770 pub const SYS_MUNMAP: i64 = 215;
771 pub const SYS_RT_SIGACTION: i64 = 134;
772 pub const SYS_RT_SIGPROCMASK: i64 = 135;
773 pub const SYS_IOCTL: i64 = 29;
774 pub const SYS_SHMGET: i64 = 194;
775 pub const SYS_SHMAT: i64 = 196;
776 pub const SYS_SHMCTL: i64 = 195;
777 pub const SYS_DUP: i64 = 23;
778 pub const SYS_NANOSLEEP: i64 = 101;
779 pub const SYS_SETITIMER: i64 = 103;
780 pub const SYS_SOCKET: i64 = 198;
781 pub const SYS_CONNECT: i64 = 203;
782 pub const SYS_ACCEPT: i64 = 202;
783 pub const SYS_SENDTO: i64 = 206;
784 pub const SYS_RECVFROM: i64 = 207;
785 pub const SYS_SHUTDOWN: i64 = 210;
786 pub const SYS_BIND: i64 = 200;
787 pub const SYS_LISTEN: i64 = 201;
788 pub const SYS_GETSOCKNAME: i64 = 204;
789 pub const SYS_SOCKETPAIR: i64 = 199;
790 pub const SYS_SETSOCKOPT: i64 = 208;
791 pub const SYS_EXECVE: i64 = 221;
792 pub const SYS_WAIT4: i64 = 260;
793 pub const SYS_KILL: i64 = 129;
794 pub const SYS_UNAME: i64 = 160;
795 pub const SYS_SEMGET: i64 = 190;
796 pub const SYS_SEMOP: i64 = 193;
797 pub const SYS_SEMCTL: i64 = 191;
798 pub const SYS_SHMDT: i64 = 197;
799 pub const SYS_MSGGET: i64 = 186;
800 pub const SYS_MSGSND: i64 = 189;
801 pub const SYS_MSGRCV: i64 = 188;
802 pub const SYS_MSGCTL: i64 = 187;
803 pub const SYS_FCNTL: i64 = 25;
804 pub const SYS_FSYNC: i64 = 82;
805 pub const SYS_TRUNCATE: i64 = 45;
806 pub const SYS_FTRUNCATE: i64 = 46;
807 pub const SYS_GETCWD: i64 = 17;
808 pub const SYS_CHDIR: i64 = 49;
809 pub const SYS_FCHMOD: i64 = 52;
810 pub const SYS_UMASK: i64 = 166;
811 pub const SYS_GETRLIMIT: i64 = 163;
812 pub const SYS_SETUID: i64 = 146;
813 pub const SYS_SETGID: i64 = 144;
814 pub const SYS_SETPGID: i64 = 154;
815 pub const SYS_GETGROUPS: i64 = 158;
816 pub const SYS_GETPGID: i64 = 155;
817 pub const SYS_GETSID: i64 = 156;
818 pub const SYS_RT_SIGPENDING: i64 = 136;
819 pub const SYS_RT_SIGTIMEDWAIT: i64 = 137;
820 pub const SYS_RT_SIGSUSPEND: i64 = 133;
821 pub const SYS_SIGALTSTACK: i64 = 132;
822 pub const SYS_SETRLIMIT: i64 = 164;
823 pub const SYS_SETHOSTNAME: i64 = 161;
824 pub const SYS_FUTEX: i64 = 98;
825 pub const SYS_CLOCK_GETTIME: i64 = 113;
826 pub const SYS_CLOCK_GETRES: i64 = 114;
827 pub const SYS_CLOCK_NANOSLEEP: i64 = 115;
828 pub const SYS_EXIT_GROUP: i64 = 94;
829 pub const SYS_TGKILL: i64 = 131;
830 pub const SYS_MKDIRAT: i64 = 34;
831 pub const SYS_NEWFSTATAT: i64 = 79;
832 pub const SYS_UNLINKAT: i64 = 35;
833 pub const SYS_LINKAT: i64 = 37;
834 pub const SYS_SYMLINKAT: i64 = 36;
835 pub const SYS_READLINKAT: i64 = 78;
836 pub const SYS_FCHMODAT: i64 = 53;
837 pub const SYS_SET_ROBUST_LIST: i64 = 99;
838 pub const SYS_UTIMENSAT: i64 = 88;
839 pub const SYS_OPENAT: i64 = 56;
840 pub const SYS_FACCESSAT: i64 = 48;
841 pub const SYS_DUP3: i64 = 24;
842 pub const SYS_PIPE2: i64 = 59;
843 pub const SYS_SYNCFS: i64 = 267;
844 pub const SYS_RENAMEAT2: i64 = 276;
845 pub const SYS_STATFS: i64 = 43;
846 pub const SYS_FSTATFS: i64 = 44;
847 pub const SYS_FDATASYNC: i64 = 83;
848 pub const SYS_GETPID: i64 = 172;
849 pub const SYS_EXIT: i64 = 93;
850 pub const SYS_GETPPID: i64 = 173;
851 pub const SYS_SETSID: i64 = 157;
852 pub const SYS_SYNC: i64 = 81;
853 pub const SYS_GETUID: i64 = 174;
854 pub const SYS_GETGID: i64 = 176;
855 pub const SYS_GETEUID: i64 = 175;
856 pub const SYS_GETEGID: i64 = 177;
857 pub const SYS_GETTID: i64 = 178;
858 pub const SYS_CLOCK_SETTIME: i64 = 112;
859 pub const SYS_CLONE: i64 = 220;
860 pub const SYS_PPOLL: i64 = 73;
861 pub const SYS_PREAD64: i64 = 67;
862 pub const SYS_MREMAP: i64 = 216;
863 pub const SYS_SYSINFO: i64 = 179;
864 pub const SYS_MEMBARRIER: i64 = 283;
865 pub const SYS_VHANGUP: i64 = 58;
866 pub const SYS_VMSPLICE: i64 = 75;
867 pub const SYS_GETTIMEOFDAY: i64 = 169;
868 pub const SYS_SETTIMEOFDAY: i64 = 170;
869 pub const SYS_ADJTIMEX: i64 = 171;
870 pub const SYS_EPOLL_CREATE1: i64 = 20;
871 pub const SYS_EPOLL_CTL: i64 = 21;
872 pub const SYS_EPOLL_WAIT: i64 = 22;
873 pub const SYS_EVENTFD2: i64 = 19;
874 pub const SYS_SIGNALFD4: i64 = 74;
875 pub const SYS_TIMERFD_CREATE: i64 = 85;
876 pub const SYS_TIMERFD_SETTIME: i64 = 86;
877 pub const SYS_TIMERFD_GETTIME: i64 = 87;
878 pub const SYS_ACCEPT4: i64 = 242;
879 pub const SYS_ACCT: i64 = 89;
880 pub const SYS_CAPGET: i64 = 90;
881 pub const SYS_CAPSET: i64 = 91;
882 pub const SYS_CHROOT: i64 = 51;
883 pub const SYS_COPY_FILE_RANGE: i64 = 285;
884 pub const SYS_DELETE_MODULE: i64 = 106;
885 pub const SYS_FALLOCATE: i64 = 47;
886 pub const SYS_FCHDIR: i64 = 50;
887 pub const SYS_FCHOWN: i64 = 55;
888 pub const SYS_FCHOWNAT: i64 = 54;
889 pub const SYS_FLOCK: i64 = 32;
890 pub const SYS_GETDENTS64: i64 = 61;
891 pub const SYS_GETPRIORITY: i64 = 141;
892 pub const SYS_GETRESGID: i64 = 150;
893 pub const SYS_GETRESUID: i64 = 148;
894 pub const SYS_INIT_MODULE: i64 = 105;
895 pub const SYS_MKNODAT: i64 = 33;
896 pub const SYS_MOUNT: i64 = 40;
897 pub const SYS_MPROTECT: i64 = 226;
898 pub const SYS_PIVOT_ROOT: i64 = 41;
899 pub const SYS_PRCTL: i64 = 167;
900 pub const SYS_PSELECT6: i64 = 72;
901 pub const SYS_REBOOT: i64 = 142;
902 pub const SYS_RECVMSG: i64 = 212;
903 pub const SYS_SENDMSG: i64 = 211;
904 pub const SYS_SETGROUPS: i64 = 159;
905 pub const SYS_SETNS: i64 = 268;
906 pub const SYS_SETPRIORITY: i64 = 140;
907 pub const SYS_SETRESGID: i64 = 149;
908 pub const SYS_SETRESUID: i64 = 147;
909 pub const SYS_SWAPOFF: i64 = 225;
910 pub const SYS_SWAPON: i64 = 224;
911 pub const SYS_UMOUNT2: i64 = 39;
912 pub const SYS_UNSHARE: i64 = 97;
913}
914pub use sysnr::*;
915
916#[inline]
921unsafe fn sys_write(fd: i64, buf: *const u8, count: usize) -> i64 {
922 <Arch as Syscalls>::syscall3(SYS_WRITE, fd as i64, buf as i64, count as i64)
923}
924
925#[inline]
926unsafe fn sys_read(fd: i64, buf: *mut u8, count: usize) -> i64 {
927 <Arch as Syscalls>::syscall3(SYS_READ, fd as i64, buf as i64, count as i64)
928}
929
930#[inline]
931unsafe fn sys_open(path: *const u8, flags: i64, mode: i64) -> i64 {
932 <Arch as Syscalls>::syscall4(SYS_OPENAT, AT_FDCWD as i64, path as i64, flags as i64, mode as i64)
933}
934
935#[inline]
936unsafe fn sys_close(fd: i64) {
937 let _ = <Arch as Syscalls>::syscall1(SYS_CLOSE, fd as i64);
938}
939
940#[inline]
941unsafe fn sys_lseek(fd: i64, offset: i64, whence: i64) -> i64 {
942 <Arch as Syscalls>::syscall3(SYS_LSEEK, fd as i64, offset as i64, whence as i64)
943}
944
945unsafe fn sys_mmap(
946 addr: *mut u8,
947 length: usize,
948 prot: i32,
949 flags: i32,
950 fd: i32,
951 offset: i64,
952) -> *mut u8 {
953 let result = <Arch as Syscalls>::syscall6(SYS_MMAP, addr as i64, length as i64, prot as i64, flags as i64, fd as i64, offset);
954 if result < 0 && result > -4096 {
955 ERRNO = (-result) as c_int;
956 return MMAP_FAILED;
957 }
958 result as *mut u8
959}
960
961unsafe fn sys_munmap(addr: *mut u8, length: usize) -> i64 {
962 <Arch as Syscalls>::syscall2(SYS_MUNMAP, addr as i64, length as i64)
963}
964
965#[no_mangle]
970pub unsafe extern "C" fn strlen(s: *const c_char) -> usize {
971 let s = s as *const u8;
972 let mut len = 0;
973 while *s.add(len) != 0 {
974 len += 1;
975 }
976 len
977}
978
979#[no_mangle]
980pub unsafe extern "C" fn memcpy(dst: *mut c_void, src: *const c_void, n: usize) -> *mut c_void {
981 let dst = dst as *mut u8;
982 let src = src as *const u8;
983 let mut i = 0;
984 while i < n {
985 *dst.add(i) = *src.add(i);
986 i += 1;
987 }
988 dst as *mut c_void
989}
990
991#[no_mangle]
992pub unsafe extern "C" fn memset(s: *mut c_void, c: c_int, n: usize) -> *mut c_void {
993 let s = s as *mut u8;
994 let mut i = 0;
995 while i < n {
996 *s.add(i) = c as u8;
997 i += 1;
998 }
999 s as *mut c_void
1000}
1001
1002#[no_mangle]
1003pub unsafe extern "C" fn memmove(dst: *mut c_void, src: *const c_void, n: usize) -> *mut c_void {
1004 let dst = dst as *mut u8;
1005 let src = src as *const u8;
1006 if (dst as usize) < (src as usize) {
1007 let mut i = 0;
1008 while i < n {
1009 *dst.add(i) = *src.add(i);
1010 i += 1;
1011 }
1012 } else {
1013 let mut i = n;
1014 while i > 0 {
1015 i -= 1;
1016 *dst.add(i) = *src.add(i);
1017 }
1018 }
1019 dst as *mut c_void
1020}
1021
1022#[no_mangle]
1023pub unsafe extern "C" fn memcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int {
1024 let s1 = s1 as *const u8;
1025 let s2 = s2 as *const u8;
1026 let mut i = 0;
1027 while i < n {
1028 let a = *s1.add(i);
1029 let b = *s2.add(i);
1030 if a != b {
1031 return a as c_int - b as c_int;
1032 }
1033 i += 1;
1034 }
1035 0
1036}
1037
1038#[no_mangle]
1039pub unsafe extern "C" fn bcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int {
1040 memcmp(s1, s2, n)
1041}
1042
1043#[no_mangle]
1044pub unsafe extern "C" fn strcmp(s1: *const u8, s2: *const u8) -> c_int {
1045 let mut i = 0;
1046 loop {
1047 let a = *s1.add(i);
1048 let b = *s2.add(i);
1049 if a != b {
1050 return a as c_int - b as c_int;
1051 }
1052 if a == 0 {
1053 return 0;
1054 }
1055 i += 1;
1056 }
1057}
1058
1059#[no_mangle]
1060pub unsafe extern "C" fn strncmp(s1: *const u8, s2: *const u8, n: usize) -> c_int {
1061 let mut i = 0;
1062 while i < n {
1063 let a = *s1.add(i);
1064 let b = *s2.add(i);
1065 if a != b {
1066 return a as c_int - b as c_int;
1067 }
1068 if a == 0 {
1069 return 0;
1070 }
1071 i += 1;
1072 }
1073 0
1074}
1075
1076#[no_mangle]
1077pub unsafe extern "C" fn strcpy(dst: *mut u8, src: *const u8) -> *mut u8 {
1078 let mut i = 0;
1079 loop {
1080 let c = *src.add(i);
1081 *dst.add(i) = c;
1082 if c == 0 {
1083 break;
1084 }
1085 i += 1;
1086 }
1087 dst
1088}
1089
1090#[no_mangle]
1091pub unsafe extern "C" fn strncpy(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 {
1092 let mut i = 0;
1093 while i < n && *src.add(i) != 0 {
1094 *dst.add(i) = *src.add(i);
1095 i += 1;
1096 }
1097 while i < n {
1098 *dst.add(i) = 0;
1099 i += 1;
1100 }
1101 dst
1102}
1103
1104#[no_mangle]
1105pub unsafe extern "C" fn strcat(dst: *mut u8, src: *const u8) -> *mut u8 {
1106 let mut i = 0;
1107 while *dst.add(i) != 0 {
1108 i += 1;
1109 }
1110 let mut j = 0;
1111 loop {
1112 let c = *src.add(j);
1113 *dst.add(i + j) = c;
1114 if c == 0 {
1115 break;
1116 }
1117 j += 1;
1118 }
1119 dst
1120}
1121
1122#[no_mangle]
1123pub unsafe extern "C" fn strncat(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 {
1124 let mut i = 0;
1125 while *dst.add(i) != 0 {
1126 i += 1;
1127 }
1128 let mut j = 0;
1129 while j < n && *src.add(j) != 0 {
1130 *dst.add(i + j) = *src.add(j);
1131 j += 1;
1132 }
1133 *dst.add(i + j) = 0;
1134 dst
1135}
1136
1137#[no_mangle]
1138pub unsafe extern "C" fn strlcpy(dst: *mut u8, src: *const u8, n: usize) -> usize {
1139 let l = strlen(src as *const c_char);
1140 if n > 0 {
1141 let c = if l < n { l } else { n - 1 };
1142 core::ptr::copy_nonoverlapping(src, dst, c);
1143 *dst.add(c) = 0;
1144 }
1145 l
1146}
1147
1148#[no_mangle]
1149pub unsafe extern "C" fn strlcat(dst: *mut u8, src: *const u8, n: usize) -> usize {
1150 let dl = strlen(dst as *const c_char);
1151 let sl = strlen(src as *const c_char);
1152 if dl >= n { return n + sl; }
1153 let c = if sl < n - dl { sl } else { n - dl - 1 };
1154 core::ptr::copy_nonoverlapping(src, dst.add(dl), c);
1155 *dst.add(dl + c) = 0;
1156 dl + sl
1157}
1158
1159#[no_mangle]
1160pub unsafe extern "C" fn bcopy(src: *const c_void, dst: *mut c_void, n: usize) {
1161 core::ptr::copy(src as *const u8, dst as *mut u8, n);
1162}
1163
1164#[no_mangle]
1165pub unsafe extern "C" fn bzero(s: *mut c_void, n: usize) {
1166 core::ptr::write_bytes(s as *mut u8, 0, n);
1167}
1168
1169#[no_mangle]
1170pub unsafe extern "C" fn strndup(s: *const c_char, n: usize) -> *mut c_char {
1171 let mut len = 0;
1172 while len < n && *s.add(len) != 0 {
1173 len += 1;
1174 }
1175 let p = malloc(len + 1) as *mut c_char;
1176 if p.is_null() {
1177 return core::ptr::null_mut();
1178 }
1179 core::ptr::copy_nonoverlapping(s, p, len);
1180 *p.add(len) = 0;
1181 p
1182}
1183
1184#[no_mangle]
1185pub unsafe extern "C" fn strchr(s: *const u8, c: c_int) -> *mut u8 {
1186 let target = c as u8;
1187 let mut i = 0;
1188 loop {
1189 let ch = *s.add(i);
1190 if ch == target {
1191 return s.add(i) as *mut u8;
1192 }
1193 if ch == 0 {
1194 return null_mut();
1195 }
1196 i += 1;
1197 }
1198}
1199
1200#[no_mangle]
1201pub unsafe extern "C" fn strrchr(s: *const u8, c: c_int) -> *mut u8 {
1202 let target = c as u8;
1203 let mut i = 0;
1204 let mut last: *mut u8 = null_mut();
1205 loop {
1206 let ch = *s.add(i);
1207 if ch == target {
1208 last = s.add(i) as *mut u8;
1209 }
1210 if ch == 0 {
1211 return last;
1212 }
1213 i += 1;
1214 }
1215}
1216
1217#[no_mangle]
1218pub unsafe extern "C" fn strnlen(s: *const u8, maxlen: usize) -> usize {
1219 let mut i = 0;
1220 while i < maxlen && *s.add(i) != 0 {
1221 i += 1;
1222 }
1223 i
1224}
1225
1226#[no_mangle]
1227pub unsafe extern "C" fn strcspn(s: *const u8, reject: *const u8) -> usize {
1228 let mut i = 0;
1229 loop {
1230 let c = *s.add(i);
1231 if c == 0 {
1232 return i;
1233 }
1234 let mut j = 0;
1235 loop {
1236 let r = *reject.add(j);
1237 if r == 0 {
1238 break;
1239 }
1240 if c == r {
1241 return i;
1242 }
1243 j += 1;
1244 }
1245 i += 1;
1246 }
1247}
1248
1249#[no_mangle]
1250pub unsafe extern "C" fn strspn(s: *const u8, accept: *const u8) -> usize {
1251 let mut i = 0;
1252 loop {
1253 let c = *s.add(i);
1254 if c == 0 {
1255 return i;
1256 }
1257 let mut found = false;
1258 let mut j = 0;
1259 loop {
1260 let a = *accept.add(j);
1261 if a == 0 {
1262 break;
1263 }
1264 if c == a {
1265 found = true;
1266 break;
1267 }
1268 j += 1;
1269 }
1270 if !found {
1271 return i;
1272 }
1273 i += 1;
1274 }
1275}
1276
1277#[no_mangle]
1278pub unsafe extern "C" fn strpbrk(s: *const u8, accept: *const u8) -> *mut u8 {
1279 let mut i = 0;
1280 loop {
1281 let c = *s.add(i);
1282 if c == 0 {
1283 return null_mut();
1284 }
1285 let mut j = 0;
1286 loop {
1287 let a = *accept.add(j);
1288 if a == 0 {
1289 break;
1290 }
1291 if c == a {
1292 return s.add(i) as *mut u8;
1293 }
1294 j += 1;
1295 }
1296 i += 1;
1297 }
1298}
1299
1300#[no_mangle]
1301pub unsafe extern "C" fn strstr(haystack: *const u8, needle: *const u8) -> *mut u8 {
1302 if *needle == 0 {
1303 return haystack as *mut u8;
1304 }
1305 let mut i = 0;
1306 loop {
1307 let h = *haystack.add(i);
1308 if h == 0 {
1309 return null_mut();
1310 }
1311 if h == *needle {
1312 let mut j = 0;
1313 loop {
1314 let n = *needle.add(j);
1315 if n == 0 {
1316 return haystack.add(i) as *mut u8;
1317 }
1318 if *haystack.add(i + j) != n {
1319 break;
1320 }
1321 j += 1;
1322 }
1323 }
1324 i += 1;
1325 }
1326}
1327
1328#[no_mangle]
1329pub unsafe extern "C" fn memchr(s: *const u8, c: c_int, n: usize) -> *mut u8 {
1330 let target = c as u8;
1331 let mut i = 0;
1332 while i < n {
1333 if *s.add(i) == target {
1334 return s.add(i) as *mut u8;
1335 }
1336 i += 1;
1337 }
1338 null_mut()
1339}
1340
1341#[no_mangle]
1342pub unsafe extern "C" fn memrchr(s: *const u8, c: c_int, n: usize) -> *mut u8 {
1343 let target = c as u8;
1344 let mut i = n;
1345 while i > 0 {
1346 i -= 1;
1347 if *s.add(i) == target {
1348 return s.add(i) as *mut u8;
1349 }
1350 }
1351 null_mut()
1352}
1353
1354#[no_mangle]
1355pub unsafe extern "C" fn memmem(
1356 haystack: *const c_void, haystacklen: usize,
1357 needle: *const c_void, needlelen: usize,
1358) -> *mut c_void {
1359 if needlelen == 0 { return haystack as *mut c_void; }
1360 if haystacklen < needlelen { return null_mut(); }
1361 let h = haystack as *const u8;
1362 let n = needle as *const u8;
1363 let last = haystacklen - needlelen;
1364 for i in 0..=last {
1365 if *h.add(i) == *n && memcmp(h.add(i) as *const c_void, n as *const c_void, needlelen) == 0 {
1366 return h.add(i) as *mut c_void;
1367 }
1368 }
1369 null_mut()
1370}
1371
1372#[no_mangle]
1373pub unsafe extern "C" fn strtok(s: *mut u8, delim: *const u8) -> *mut u8 {
1374 static mut STATE: *mut u8 = core::ptr::null_mut();
1375 let mut p = if s.is_null() { STATE } else { s };
1376 if p.is_null() {
1377 return core::ptr::null_mut();
1378 }
1379 loop {
1380 let c = *p;
1381 if c == 0 {
1382 STATE = core::ptr::null_mut();
1383 return core::ptr::null_mut();
1384 }
1385 let mut is_delim = false;
1386 let mut i = 0;
1387 loop {
1388 let d = *delim.add(i);
1389 if d == 0 {
1390 break;
1391 }
1392 if c == d {
1393 is_delim = true;
1394 break;
1395 }
1396 i += 1;
1397 }
1398 if !is_delim {
1399 break;
1400 }
1401 p = p.add(1);
1402 }
1403 let start = p;
1404 loop {
1405 let c = *p;
1406 if c == 0 {
1407 STATE = core::ptr::null_mut();
1408 return start;
1409 }
1410 let mut is_delim = false;
1411 let mut i = 0;
1412 loop {
1413 let d = *delim.add(i);
1414 if d == 0 {
1415 break;
1416 }
1417 if c == d {
1418 is_delim = true;
1419 break;
1420 }
1421 i += 1;
1422 }
1423 if is_delim {
1424 *p = 0;
1425 STATE = p.add(1);
1426 return start;
1427 }
1428 p = p.add(1);
1429 }
1430}
1431
1432type SizeT = usize;
1437type SSizeT = isize;
1438type mode_t = c_uint;
1439type TimeT = c_long;
1440type ClockT = c_long;
1441type wchar_t = c_int;
1442type wint_t = c_uint;
1443type wctype_t = *const c_int;
1444type wctrans_t = *const c_int;
1445
1446const WEOF: wint_t = 0xffffffff;
1447
1448#[repr(C)]
1449pub struct tm {
1450 pub tm_sec: c_int,
1451 pub tm_min: c_int,
1452 pub tm_hour: c_int,
1453 pub tm_mday: c_int,
1454 pub tm_mon: c_int,
1455 pub tm_year: c_int,
1456 pub tm_wday: c_int,
1457 pub tm_yday: c_int,
1458 pub tm_isdst: c_int,
1459 pub tm_gmtoff: c_long,
1460 pub tm_zone: *const c_char,
1461}
1462
1463#[repr(C)]
1464pub struct timeval {
1465 pub tv_sec: TimeT,
1466 pub tv_usec: c_long,
1467}
1468
1469#[repr(C)]
1470pub struct Timeb {
1471 pub time: TimeT,
1472 pub millitm: u16,
1473 pub timezone: i16,
1474 pub dstflag: u16,
1475}
1476
1477const CT_UPPER: u8 = 1 << 0;
1482const CT_LOWER: u8 = 1 << 1;
1483const CT_DIGIT: u8 = 1 << 2;
1484const CT_SPACE: u8 = 1 << 3;
1485const CT_PUNCT: u8 = 1 << 4;
1486const CT_CNTRL: u8 = 1 << 5;
1487const CT_BLANK: u8 = 1 << 6;
1488const CT_XDIGIT: u8 = 1 << 7;
1489
1490const CT_TABLE: [u8; 128] = {
1491 let mut t = [0u8; 128];
1492 let mut i = 0;
1493 while i < 128 {
1494 let c = i as u8;
1495 let mut flags = 0u8;
1496 if c >= b'A' && c <= b'Z' {
1497 flags |= CT_UPPER;
1498 }
1499 if c >= b'a' && c <= b'z' {
1500 flags |= CT_LOWER;
1501 }
1502 if c >= b'0' && c <= b'9' {
1503 flags |= CT_DIGIT;
1504 }
1505 if c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == b'\x0c' || c == b'\x0b' {
1506 flags |= CT_SPACE;
1507 }
1508 if (c >= b'!' && c <= b'/')
1509 || (c >= b':' && c <= b'@')
1510 || (c >= b'[' && c <= b'`')
1511 || (c >= b'{' && c <= b'~')
1512 {
1513 flags |= CT_PUNCT;
1514 }
1515 if c < 0x20 || c == 0x7f {
1516 flags |= CT_CNTRL;
1517 }
1518 if c == b' ' || c == b'\t' {
1519 flags |= CT_BLANK;
1520 }
1521 if (c >= b'0' && c <= b'9') || (c >= b'A' && c <= b'F') || (c >= b'a' && c <= b'f') {
1522 flags |= CT_XDIGIT;
1523 }
1524 t[i] = flags;
1525 i += 1;
1526 }
1527 t
1528};
1529
1530#[inline]
1531fn ct_flags(c: c_int) -> u8 {
1532 if c < 0 || c > 127 {
1533 0
1534 } else {
1535 CT_TABLE[c as usize]
1536 }
1537}
1538
1539#[no_mangle]
1540pub extern "C" fn isalnum(c: c_int) -> c_int {
1541 (ct_flags(c) & (CT_UPPER | CT_LOWER | CT_DIGIT) != 0) as c_int
1542}
1543
1544#[no_mangle]
1545pub extern "C" fn isalpha(c: c_int) -> c_int {
1546 (ct_flags(c) & (CT_UPPER | CT_LOWER) != 0) as c_int
1547}
1548
1549#[no_mangle]
1550pub extern "C" fn isascii(c: c_int) -> c_int {
1551 ((c as u32) <= 127) as c_int
1552}
1553
1554#[no_mangle]
1555pub extern "C" fn isblank(c: c_int) -> c_int {
1556 (ct_flags(c) & CT_BLANK != 0) as c_int
1557}
1558
1559#[no_mangle]
1560pub extern "C" fn iscntrl(c: c_int) -> c_int {
1561 (ct_flags(c) & CT_CNTRL != 0) as c_int
1562}
1563
1564#[no_mangle]
1565pub extern "C" fn isdigit(c: c_int) -> c_int {
1566 (ct_flags(c) & CT_DIGIT != 0) as c_int
1567}
1568
1569#[no_mangle]
1570pub extern "C" fn isgraph(c: c_int) -> c_int {
1571 (ct_flags(c) & (CT_UPPER | CT_LOWER | CT_DIGIT | CT_PUNCT) != 0) as c_int
1572}
1573
1574#[no_mangle]
1575pub extern "C" fn islower(c: c_int) -> c_int {
1576 (ct_flags(c) & CT_LOWER != 0) as c_int
1577}
1578
1579#[no_mangle]
1580pub extern "C" fn isprint(c: c_int) -> c_int {
1581 let flags = ct_flags(c);
1582 (flags & (CT_UPPER | CT_LOWER | CT_DIGIT | CT_PUNCT | CT_BLANK) != 0) as c_int
1583}
1584
1585#[no_mangle]
1586pub extern "C" fn ispunct(c: c_int) -> c_int {
1587 (ct_flags(c) & CT_PUNCT != 0) as c_int
1588}
1589
1590#[no_mangle]
1591pub extern "C" fn isspace(c: c_int) -> c_int {
1592 (ct_flags(c) & CT_SPACE != 0) as c_int
1593}
1594
1595#[no_mangle]
1596pub extern "C" fn isupper(c: c_int) -> c_int {
1597 (ct_flags(c) & CT_UPPER != 0) as c_int
1598}
1599
1600#[no_mangle]
1601pub extern "C" fn isxdigit(c: c_int) -> c_int {
1602 (ct_flags(c) & CT_XDIGIT != 0) as c_int
1603}
1604
1605#[no_mangle]
1606pub extern "C" fn tolower(c: c_int) -> c_int {
1607 if (ct_flags(c) & CT_UPPER) != 0 {
1608 c + (b'a' as c_int - b'A' as c_int)
1609 } else {
1610 c
1611 }
1612}
1613
1614#[no_mangle]
1615pub extern "C" fn toupper(c: c_int) -> c_int {
1616 if (ct_flags(c) & CT_LOWER) != 0 {
1617 c - (b'a' as c_int - b'A' as c_int)
1618 } else {
1619 c
1620 }
1621}
1622
1623unsafe fn parse_digit(c: u8, base: c_int) -> Option<u8> {
1628 if c == 0 { return None; }
1629 let d = if c >= b'0' && c <= b'9' {
1630 c - b'0'
1631 } else if c >= b'a' && c <= b'z' {
1632 c - b'a' + 10
1633 } else if c >= b'A' && c <= b'Z' {
1634 c - b'A' + 10
1635 } else {
1636 return None;
1637 };
1638 if (d as c_int) < base {
1639 Some(d)
1640 } else {
1641 None
1642 }
1643}
1644
1645unsafe fn parse_prefix(s: *const u8, base: *mut c_int) -> *const u8 {
1646 let mut p = s;
1647 if *base == 0 {
1648 if *p == b'0' {
1649 if (*p.add(1) == b'x' || *p.add(1) == b'X') && parse_digit(*p.add(2), 16).is_some() {
1650 *base = 16;
1651 p = p.add(2);
1652 } else {
1653 *base = 8;
1654 }
1655 } else {
1656 *base = 10;
1657 }
1658 } else if *base == 16 {
1659 if *p == b'0' && (*p.add(1) == b'x' || *p.add(1) == b'X') && parse_digit(*p.add(2), 16).is_some() {
1660 p = p.add(2);
1661 }
1662 }
1663 p
1664}
1665
1666unsafe fn strtox(
1667 s: *const c_char,
1668 endptr: *mut *mut c_char,
1669 mut base: c_int,
1670 pos_limit: u64,
1671 neg_limit: u64,
1672) -> (u64, bool, bool) {
1673 let s0 = s as *const u8;
1674 let mut p = s0;
1675 while isspace(*p as c_int) != 0 {
1676 p = p.add(1);
1677 }
1678
1679 if base < 0 || base == 1 || base > 36 {
1680 if !endptr.is_null() {
1681 *endptr = s as *mut c_char;
1682 }
1683 ERRNO = EINVAL;
1684 return (0, false, false);
1685 }
1686
1687 let mut neg = false;
1688 match *p {
1689 b'-' => { neg = true; p = p.add(1); }
1690 b'+' => p = p.add(1),
1691 _ => {}
1692 }
1693
1694 p = parse_prefix(p, &mut base);
1695
1696 let limit = if neg { neg_limit } else { pos_limit };
1697 let mut val: u64 = 0;
1698 let mut any = false;
1699 while let Some(d) = parse_digit(*p, base) {
1700 any = true;
1701 if val > (limit - d as u64) / base as u64 {
1702 while parse_digit(*p, base).is_some() { p = p.add(1); }
1703 if !endptr.is_null() { *endptr = p as *mut c_char; }
1704 ERRNO = ERANGE_VAL;
1705 return (limit, true, neg);
1706 }
1707 val = val * base as u64 + d as u64;
1708 p = p.add(1);
1709 }
1710
1711 if !endptr.is_null() {
1712 *endptr = if any { p as *mut c_char } else { s as *mut c_char };
1713 }
1714 (val, false, neg)
1715}
1716
1717#[no_mangle]
1718pub unsafe extern "C" fn strtol(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
1719 let pos_limit = c_long::MAX as u64;
1720 let neg_limit = pos_limit.wrapping_add(1);
1721 let (val, overflow, neg) = strtox(s, endptr, base, pos_limit, neg_limit);
1722 if overflow {
1723 return if neg { c_long::MIN } else { c_long::MAX };
1724 }
1725 if neg { val.wrapping_neg() as c_long } else { val as c_long }
1726}
1727
1728#[no_mangle]
1729pub unsafe extern "C" fn strtoul(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_ulong {
1730 let limit = c_ulong::MAX as u64;
1731 let (val, overflow, neg) = strtox(s, endptr, base, limit, limit);
1732 if overflow {
1733 return c_ulong::MAX;
1734 }
1735 if neg { val.wrapping_neg() as c_ulong } else { val as c_ulong }
1736}
1737
1738#[no_mangle]
1739pub unsafe extern "C" fn strtoll(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_longlong {
1740 let pos_limit = c_longlong::MAX as u64;
1741 let neg_limit = pos_limit.wrapping_add(1);
1742 let (val, overflow, neg) = strtox(s, endptr, base, pos_limit, neg_limit);
1743 if overflow {
1744 return if neg { c_longlong::MIN } else { c_longlong::MAX };
1745 }
1746 if neg { val.wrapping_neg() as c_longlong } else { val as c_longlong }
1747}
1748
1749#[no_mangle]
1750pub unsafe extern "C" fn strtoull(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_ulonglong {
1751 let limit = c_ulonglong::MAX as u64;
1752 let (val, overflow, neg) = strtox(s, endptr, base, limit, limit);
1753 if overflow {
1754 return c_ulonglong::MAX;
1755 }
1756 if neg { val.wrapping_neg() as c_ulonglong } else { val as c_ulonglong }
1757}
1758
1759#[no_mangle]
1760pub unsafe extern "C" fn atoi(s: *const c_char) -> c_int {
1761 strtol(s, core::ptr::null_mut(), 10) as c_int
1762}
1763
1764#[no_mangle]
1765pub unsafe extern "C" fn atol(s: *const c_char) -> c_long {
1766 strtol(s, core::ptr::null_mut(), 10)
1767}
1768
1769#[no_mangle]
1770pub unsafe extern "C" fn atoll(s: *const c_char) -> c_longlong {
1771 strtoll(s, core::ptr::null_mut(), 10)
1772}
1773
1774#[no_mangle]
1775pub extern "C" fn abs(n: c_int) -> c_int {
1776 if n < 0 {
1777 -n
1778 } else {
1779 n
1780 }
1781}
1782
1783#[no_mangle]
1784pub extern "C" fn labs(n: c_long) -> c_long {
1785 if n < 0 {
1786 -n
1787 } else {
1788 n
1789 }
1790}
1791
1792#[no_mangle]
1793pub extern "C" fn llabs(n: c_longlong) -> c_longlong {
1794 if n < 0 {
1795 -n
1796 } else {
1797 n
1798 }
1799}
1800
1801static mut RAND_STATE: c_uint = 1;
1802
1803#[no_mangle]
1804pub extern "C" fn srand(seed: c_uint) {
1805 unsafe {
1806 RAND_STATE = seed;
1807 }
1808}
1809
1810#[no_mangle]
1811pub extern "C" fn rand() -> c_int {
1812 unsafe {
1813 RAND_STATE = RAND_STATE.wrapping_mul(1103515245).wrapping_add(12345);
1814 ((RAND_STATE >> 16) & 0x7fff) as c_int
1815 }
1816}
1817
1818#[repr(C)]
1823pub struct div_t { pub quot: c_int, pub rem: c_int }
1824#[repr(C)]
1825pub struct ldiv_t { pub quot: c_long, pub rem: c_long }
1826#[repr(C)]
1827pub struct lldiv_t { pub quot: c_longlong, pub rem: c_longlong }
1828
1829#[no_mangle]
1830pub extern "C" fn div(num: c_int, den: c_int) -> div_t {
1831 div_t { quot: num / den, rem: num % den }
1832}
1833
1834#[no_mangle]
1835pub extern "C" fn ldiv(num: c_long, den: c_long) -> ldiv_t {
1836 ldiv_t { quot: num / den, rem: num % den }
1837}
1838
1839#[no_mangle]
1840pub extern "C" fn lldiv(num: c_longlong, den: c_longlong) -> lldiv_t {
1841 lldiv_t { quot: num / den, rem: num % den }
1842}
1843
1844type CmpFn = unsafe extern "C" fn(*const c_void, *const c_void) -> c_int;
1849
1850#[no_mangle]
1851pub unsafe extern "C" fn bsearch(
1852 key: *const c_void,
1853 base: *const c_void,
1854 nel: usize,
1855 width: usize,
1856 cmp: CmpFn,
1857) -> *mut c_void {
1858 let mut base = base as *const u8;
1859 let mut nel = nel;
1860 while nel > 0 {
1861 let trial = base.add(width * (nel / 2));
1862 let sign = cmp(key, trial as *const c_void);
1863 if sign < 0 {
1864 nel /= 2;
1865 } else if sign > 0 {
1866 base = trial.add(width);
1867 nel -= nel / 2 + 1;
1868 } else {
1869 return trial as *mut c_void;
1870 }
1871 }
1872 null_mut()
1873}
1874
1875pub const SA_RESTORER: c_ulong = 0x04000000;
1880
1881pub const SIG_DFL: usize = 0;
1882pub const SIG_IGN: usize = 1;
1883pub const SIG_ERR: usize = !0usize;
1884
1885pub const SIGHUP: c_int = 1;
1886pub const SIGINT: c_int = 2;
1887pub const SIGQUIT: c_int = 3;
1888pub const SIGILL: c_int = 4;
1889pub const SIGTRAP: c_int = 5;
1890pub const SIGABRT: c_int = 6;
1891pub const SIGIOT: c_int = 6;
1892pub const SIGBUS: c_int = 7;
1893pub const SIGFPE: c_int = 8;
1894pub const SIGKILL: c_int = 9;
1895pub const SIGUSR1: c_int = 10;
1896pub const SIGSEGV: c_int = 11;
1897pub const SIGUSR2: c_int = 12;
1898pub const SIGPIPE: c_int = 13;
1899pub const SIGALRM: c_int = 14;
1900pub const SIGTERM: c_int = 15;
1901pub const SIGSTKFLT: c_int = 16;
1902pub const SIGCHLD: c_int = 17;
1903pub const SIGCONT: c_int = 18;
1904pub const SIGSTOP: c_int = 19;
1905pub const SIGTSTP: c_int = 20;
1906pub const SIGTTIN: c_int = 21;
1907pub const SIGTTOU: c_int = 22;
1908pub const SIGURG: c_int = 23;
1909pub const SIGXCPU: c_int = 24;
1910pub const SIGXFSZ: c_int = 25;
1911pub const SIGVTALRM: c_int = 26;
1912pub const SIGPROF: c_int = 27;
1913pub const SIGWINCH: c_int = 28;
1914pub const SIGIO: c_int = 29;
1915pub const SIGPOLL: c_int = 29;
1916pub const SIGPWR: c_int = 30;
1917pub const SIGSYS: c_int = 31;
1918pub const SIGUNUSED: c_int = 31;
1919pub const _NSIG: c_int = 65;
1920
1921pub const SIG_BLOCK: c_int = 0;
1922pub const SIG_UNBLOCK: c_int = 1;
1923pub const SIG_SETMASK: c_int = 2;
1924
1925pub const SA_NOCLDSTOP: c_ulong = 1;
1926pub const SA_NOCLDWAIT: c_ulong = 2;
1927pub const SA_SIGINFO: c_ulong = 4;
1928pub const SA_ONSTACK: c_ulong = 0x08000000;
1929pub const SA_RESTART: c_ulong = 0x10000000;
1930pub const SA_NODEFER: c_ulong = 0x40000000;
1931pub const SA_RESETHAND: c_ulong = 0x80000000;
1932
1933pub const SS_ONSTACK: c_int = 1;
1934pub const SS_DISABLE: c_int = 2;
1935pub const MINSIGSTKSZ: usize = 2048;
1936pub const SIGSTKSZ: usize = 8192;
1937
1938pub const SI_USER: c_int = 0;
1939pub const SI_TKILL: c_int = -6;
1940
1941#[repr(C)]
1942pub struct timespec {
1943 pub tv_sec: c_long,
1944 pub tv_nsec: c_long,
1945}
1946
1947#[repr(C)]
1948pub struct siginfo_t {
1949 pub si_signo: c_int,
1950 pub si_errno: c_int,
1951 pub si_code: c_int,
1952 _pad: [u8; 128 - 3 * core::mem::size_of::<c_int>()],
1954}
1955
1956#[repr(C)]
1957pub struct stack_t {
1958 pub ss_sp: *mut c_void,
1959 pub ss_flags: c_int,
1960 pub ss_size: usize,
1961}
1962
1963#[repr(C)]
1964pub struct sigaction {
1965 pub sa_handler: usize,
1966 pub sa_flags: c_ulong,
1967 pub sa_restorer: usize,
1968 pub sa_mask: [c_ulong; 1],
1969}
1970
1971pub type SigSetT = c_ulong;
1972
1973#[cfg(target_arch = "x86_64")]
1974core::arch::global_asm!(
1975 ".global sig_restorer",
1976 ".type sig_restorer, @function",
1977 "sig_restorer:",
1978 "mov eax, 15",
1979 "syscall",
1980);
1981
1982#[cfg(target_arch = "aarch64")]
1983core::arch::global_asm!(
1984 ".global sig_restorer",
1985 ".type sig_restorer, @function",
1986 "sig_restorer:",
1987 "mov x8, #139",
1988 "svc #0",
1989);
1990
1991#[cfg(target_arch = "riscv64")]
1992core::arch::global_asm!(
1993 ".global sig_restorer",
1994 ".type sig_restorer, @function",
1995 "sig_restorer:",
1996 "li a7, 139",
1997 "ecall",
1998);
1999
2000extern "C" {
2001 fn sig_restorer();
2002}
2003
2004#[inline]
2005unsafe fn sys_rt_sigaction(sig: c_int,
2006 act: *const sigaction,
2007 oldact: *mut sigaction,
2008 sigsetsize: usize,) -> i64 {
2009 <Arch as Syscalls>::syscall4(SYS_RT_SIGACTION, sig as i64, act as i64, oldact as i64, sigsetsize as i64)
2010}
2011
2012#[inline]
2013unsafe fn sys_rt_sigprocmask(how: c_int,
2014 set: *const SigSetT,
2015 oldset: *mut SigSetT,
2016 sigsetsize: usize,) -> i64 {
2017 <Arch as Syscalls>::syscall4(SYS_RT_SIGPROCMASK, how as i64, set as i64, oldset as i64, sigsetsize as i64)
2018}
2019
2020#[inline]
2021unsafe fn sys_rt_sigpending(set: *mut SigSetT, sigsetsize: usize) -> i64 {
2022 <Arch as Syscalls>::syscall2(SYS_RT_SIGPENDING, set as i64, sigsetsize as i64)
2023}
2024
2025#[inline]
2026unsafe fn sys_rt_sigsuspend(mask: *const SigSetT, sigsetsize: usize) -> i64 {
2027 <Arch as Syscalls>::syscall2(SYS_RT_SIGSUSPEND, mask as i64, sigsetsize as i64)
2028}
2029
2030#[inline]
2031unsafe fn sys_rt_sigtimedwait(set: *const SigSetT,
2032 info: *mut siginfo_t,
2033 timeout: *const timespec,
2034 sigsetsize: usize,) -> i64 {
2035 <Arch as Syscalls>::syscall4(SYS_RT_SIGTIMEDWAIT, set as i64, info as i64, timeout as i64, sigsetsize as i64)
2036}
2037
2038#[inline]
2039unsafe fn sys_sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> i64 {
2040 <Arch as Syscalls>::syscall2(SYS_SIGALTSTACK, ss as i64, old_ss as i64)
2041}
2042
2043#[inline]
2044unsafe fn sys_tgkill(tgid: c_int, tid: c_int, sig: c_int) -> i64 {
2045 <Arch as Syscalls>::syscall3(SYS_TGKILL, tgid as i64, tid as i64, sig as i64)
2046}
2047
2048const CLOCK_REALTIME: c_int = 0;
2049const CLOCK_MONOTONIC: c_int = 1;
2050
2051#[inline]
2052unsafe fn sys_clock_gettime(clockid: c_int, ts: *mut timespec) -> i64 {
2053 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETTIME, clockid as i64, ts as i64)
2054}
2055
2056#[no_mangle]
2057pub unsafe extern "C" fn clock_gettime(clockid: c_int, ts: *mut timespec) -> c_int {
2058 if sys_clock_gettime(clockid, ts) < 0 { -1 } else { 0 }
2059}
2060
2061#[no_mangle]
2062pub unsafe extern "C" fn sigprocmask(
2063 how: c_int,
2064 set: *const SigSetT,
2065 oldset: *mut SigSetT,
2066) -> c_int {
2067 let internal_mask: SigSetT = (1u64 << 31) | (1u64 << 32);
2069 let filtered: SigSetT;
2070 let set_ptr: *const SigSetT = if set.is_null() {
2071 set
2072 } else {
2073 filtered = *set & !internal_mask;
2074 &filtered
2075 };
2076 let r = sys_rt_sigprocmask(how, set_ptr, oldset, core::mem::size_of::<SigSetT>());
2077 if !oldset.is_null() {
2078 *oldset &= !internal_mask;
2079 }
2080 if r < 0 { -1 } else { 0 }
2081}
2082
2083#[inline]
2084unsafe fn sys_kill(pid: c_int, sig: c_int) -> i64 {
2085 <Arch as Syscalls>::syscall2(SYS_KILL, pid as i64, sig as i64)
2086}
2087
2088#[inline]
2089unsafe fn sys_getpid() -> i64 {
2090 <Arch as Syscalls>::syscall0(SYS_GETPID)
2091}
2092
2093#[no_mangle]
2094pub unsafe extern "C" fn sigaction(
2095 signum: c_int,
2096 act: *const sigaction,
2097 oldact: *mut sigaction,
2098) -> c_int {
2099 let kact: sigaction;
2100 let act_ptr = if act.is_null() {
2101 core::ptr::null()
2102 } else {
2103 kact = sigaction {
2104 sa_handler: (*act).sa_handler,
2105 sa_flags: (*act).sa_flags | SA_RESTORER,
2106 sa_restorer: sig_restorer as *const () as usize,
2107 sa_mask: (*act).sa_mask,
2108 };
2109 &kact as *const sigaction
2110 };
2111 let r = sys_rt_sigaction(signum, act_ptr, oldact, core::mem::size_of::<SigSetT>());
2112 if r < 0 {
2113 ERRNO = (-r) as c_int;
2114 -1
2115 } else {
2116 0
2117 }
2118}
2119
2120#[no_mangle]
2121pub unsafe extern "C" fn signal(signum: c_int, handler: usize) -> usize {
2122 let act = sigaction {
2123 sa_handler: handler,
2124 sa_flags: SA_RESTORER,
2125 sa_restorer: sig_restorer as *const () as usize,
2126 sa_mask: [0],
2127 };
2128 let mut old = sigaction {
2129 sa_handler: 0,
2130 sa_flags: 0,
2131 sa_restorer: 0,
2132 sa_mask: [0],
2133 };
2134 if sigaction(signum, &act, &mut old) == -1 {
2135 SIG_ERR
2136 } else {
2137 old.sa_handler
2138 }
2139}
2140
2141#[no_mangle]
2142pub unsafe extern "C" fn kill(pid: c_int, sig: c_int) -> c_int {
2143 sys_kill(pid, sig) as c_int
2144}
2145
2146#[no_mangle]
2147pub unsafe extern "C" fn tgkill(tgid: c_int, tid: c_int, sig: c_int) -> c_int {
2148 if sys_tgkill(tgid, tid, sig) < 0 { -1 } else { 0 }
2149}
2150
2151#[no_mangle]
2152pub unsafe extern "C" fn getpid() -> c_int {
2153 sys_getpid() as c_int
2154}
2155
2156#[no_mangle]
2157pub unsafe extern "C" fn raise(sig: c_int) -> c_int {
2158 if sys_tgkill(sys_getpid() as c_int, sys_gettid() as c_int, sig) < 0 {
2159 -1
2160 } else {
2161 0
2162 }
2163}
2164
2165#[no_mangle]
2166pub unsafe extern "C" fn sigemptyset(set: *mut SigSetT) -> c_int {
2167 *set = 0;
2168 0
2169}
2170
2171#[no_mangle]
2172pub unsafe extern "C" fn sigfillset(set: *mut SigSetT) -> c_int {
2173 *set = 0xFFFF_FFFC_7FFF_FFFFu64;
2175 0
2176}
2177
2178#[no_mangle]
2179pub unsafe extern "C" fn sigaddset(set: *mut SigSetT, signum: c_int) -> c_int {
2180 let s = (signum as c_uint).wrapping_sub(1);
2181 if s as usize >= 64 {
2182 ERRNO = EINVAL;
2183 return -1;
2184 }
2185 if signum >= 32 && signum < __libc_current_sigrtmin() {
2187 return 0;
2188 }
2189 *set |= 1u64 << s;
2190 0
2191}
2192
2193#[no_mangle]
2194pub unsafe extern "C" fn sigdelset(set: *mut SigSetT, signum: c_int) -> c_int {
2195 let s = (signum as c_uint).wrapping_sub(1);
2196 if s as usize >= 64 {
2197 ERRNO = EINVAL;
2198 return -1;
2199 }
2200 if signum >= 32 && signum < __libc_current_sigrtmin() {
2202 return 0;
2203 }
2204 *set &= !(1u64 << s);
2205 0
2206}
2207
2208#[no_mangle]
2209pub unsafe extern "C" fn sigismember(set: *const SigSetT, signum: c_int) -> c_int {
2210 let s = (signum as c_uint).wrapping_sub(1);
2211 if s as usize >= 64 { return 0; }
2212 if signum >= 32 && signum < __libc_current_sigrtmin() {
2214 return 0;
2215 }
2216 ((*set & (1u64 << s)) != 0) as c_int
2217}
2218
2219#[no_mangle]
2220pub unsafe extern "C" fn sigpending(set: *mut SigSetT) -> c_int {
2221 let r = sys_rt_sigpending(set, core::mem::size_of::<SigSetT>());
2222 if r < 0 {
2223 ERRNO = (-r) as c_int;
2224 return -1;
2225 }
2226 0
2227}
2228
2229#[no_mangle]
2230pub unsafe extern "C" fn sigsuspend(mask: *const SigSetT) -> c_int {
2231 let r = sys_rt_sigsuspend(mask, core::mem::size_of::<SigSetT>());
2232 if r < 0 {
2233 ERRNO = (-r) as c_int;
2234 }
2235 -1
2236}
2237
2238#[no_mangle]
2239pub unsafe extern "C" fn sigtimedwait(
2240 mask: *const SigSetT,
2241 info: *mut siginfo_t,
2242 timeout: *const timespec,
2243) -> c_int {
2244 loop {
2245 let r = sys_rt_sigtimedwait(mask, info, timeout, core::mem::size_of::<SigSetT>());
2246 if r >= 0 {
2247 return r as c_int;
2248 }
2249 let e = (-r) as c_int;
2250 if e != EINTR {
2251 ERRNO = e;
2252 return -1;
2253 }
2254 }
2255}
2256
2257#[no_mangle]
2258pub unsafe extern "C" fn sigwaitinfo(
2259 mask: *const SigSetT,
2260 info: *mut siginfo_t,
2261) -> c_int {
2262 sigtimedwait(mask, info, core::ptr::null())
2263}
2264
2265#[no_mangle]
2266pub unsafe extern "C" fn sigwait(
2267 mask: *const SigSetT,
2268 sig: *mut c_int,
2269) -> c_int {
2270 let mut info: siginfo_t = core::mem::zeroed();
2271 if sigtimedwait(mask, &mut info, core::ptr::null()) < 0 {
2272 return ERRNO;
2273 }
2274 *sig = info.si_signo;
2275 0
2276}
2277
2278#[no_mangle]
2279pub unsafe extern "C" fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int {
2280 if !ss.is_null() {
2281 if (*ss).ss_flags & SS_ONSTACK != 0 {
2282 ERRNO = EINVAL;
2283 return -1;
2284 }
2285 if (*ss).ss_flags & SS_DISABLE == 0 && (*ss).ss_size < MINSIGSTKSZ {
2286 ERRNO = ENOMEM;
2287 return -1;
2288 }
2289 }
2290 let r = sys_sigaltstack(ss, old_ss);
2291 if r < 0 {
2292 ERRNO = (-r) as c_int;
2293 return -1;
2294 }
2295 0
2296}
2297
2298#[no_mangle]
2304#[inline(never)]
2305#[cfg(target_arch = "x86_64")]
2306pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2307 core::arch::asm!(
2308 "mov rax, [rsp]",
2309 "lea rcx, [rsp + 8]",
2310 "mov [r8], rbx",
2311 "mov [r8 + 8], rbp",
2312 "mov [r8 + 16], r12",
2313 "mov [r8 + 24], r13",
2314 "mov [r8 + 32], r14",
2315 "mov [r8 + 40], r15",
2316 "mov [r8 + 48], rcx",
2317 "mov [r8 + 56], rax",
2318 in("r8") env,
2319 lateout("rax") _,
2320 lateout("rcx") _,
2321 options(nostack),
2322 );
2323 0
2324}
2325
2326#[no_mangle]
2327#[inline(never)]
2328#[cfg(target_arch = "x86_64")]
2329pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2330 let ret = if val == 0 { 1 } else { val } as u32;
2331 core::arch::asm!(
2332 "mov rbx, [r8]",
2333 "mov rbp, [r8 + 8]",
2334 "mov r12, [r8 + 16]",
2335 "mov r13, [r8 + 24]",
2336 "mov r14, [r8 + 32]",
2337 "mov r15, [r8 + 40]",
2338 "mov rsp, [r8 + 48]",
2339 "mov eax, edx",
2340 "jmp [r8 + 56]",
2341 in("r8") env,
2342 in("edx") ret,
2343 options(noreturn),
2344 );
2345}
2346
2347#[no_mangle]
2348#[unsafe(naked)]
2349#[cfg(target_arch = "aarch64")]
2350pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2351 core::arch::naked_asm!(
2352 "stp x19, x20, [x0, #0]",
2353 "stp x21, x22, [x0, #16]",
2354 "stp x23, x24, [x0, #32]",
2355 "stp x25, x26, [x0, #48]",
2356 "stp x27, x28, [x0, #64]",
2357 "stp x29, x30, [x0, #80]",
2358 "mov x2, sp",
2359 "str x2, [x0, #104]",
2360 "stp d8, d9, [x0, #112]",
2361 "stp d10, d11, [x0, #128]",
2362 "stp d12, d13, [x0, #144]",
2363 "stp d14, d15, [x0, #160]",
2364 "mov x0, #0",
2365 "ret",
2366 );
2367}
2368
2369#[no_mangle]
2370#[inline(never)]
2371#[cfg(target_arch = "aarch64")]
2372pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2373 let ret = if val == 0 { 1 } else { val } as u64;
2374 core::arch::asm!(
2375 "ldp x19, x20, [x0]",
2376 "ldp x21, x22, [x0, #16]",
2377 "ldp x23, x24, [x0, #32]",
2378 "ldp x25, x26, [x0, #48]",
2379 "ldp x27, x28, [x0, #64]",
2380 "ldp x29, x30, [x0, #80]",
2381 "ldr x2, [x0, #104]",
2382 "mov sp, x2",
2383 "ldp d8, d9, [x0, #112]",
2384 "ldp d10, d11, [x0, #128]",
2385 "ldp d12, d13, [x0, #144]",
2386 "ldp d14, d15, [x0, #160]",
2387 "mov x0, x1",
2388 "br x30",
2389 in("x0") env,
2390 in("x1") ret,
2391 options(noreturn),
2392 );
2393}
2394
2395#[no_mangle]
2396#[unsafe(naked)]
2397#[cfg(target_arch = "riscv64")]
2398pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2399 core::arch::naked_asm!(
2400 "sd s0, 0(a0)",
2401 "sd s1, 8(a0)",
2402 "sd s2, 16(a0)",
2403 "sd s3, 24(a0)",
2404 "sd s4, 32(a0)",
2405 "sd s5, 40(a0)",
2406 "sd s6, 48(a0)",
2407 "sd s7, 56(a0)",
2408 "sd s8, 64(a0)",
2409 "sd s9, 72(a0)",
2410 "sd s10, 80(a0)",
2411 "sd s11, 88(a0)",
2412 "sd sp, 96(a0)",
2413 "sd ra, 104(a0)",
2414 "li a0, 0",
2415 "ret",
2416 );
2417}
2418
2419#[no_mangle]
2420#[inline(never)]
2421#[cfg(target_arch = "riscv64")]
2422pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2423 let ret = if val == 0 { 1 } else { val } as u64;
2424 core::arch::asm!(
2425 "ld s0, 0(a0)",
2426 "ld s1, 8(a0)",
2427 "ld s2, 16(a0)",
2428 "ld s3, 24(a0)",
2429 "ld s4, 32(a0)",
2430 "ld s5, 40(a0)",
2431 "ld s6, 48(a0)",
2432 "ld s7, 56(a0)",
2433 "ld s8, 64(a0)",
2434 "ld s9, 72(a0)",
2435 "ld s10, 80(a0)",
2436 "ld s11, 88(a0)",
2437 "ld sp, 96(a0)",
2438 "ld ra, 104(a0)",
2439 "mv a0, a1",
2440 "ret",
2441 in("a0") env,
2442 in("a1") ret,
2443 options(noreturn),
2444 );
2445}
2446
2447#[no_mangle]
2455#[unsafe(naked)]
2456#[cfg(target_arch = "x86_64")]
2457pub unsafe extern "C" fn sigsetjmp(_env: *mut c_ulong, _savemask: c_int) -> c_int {
2458 core::arch::naked_asm!("jmp sigsetjmp_real");
2459}
2460
2461#[no_mangle]
2462#[unsafe(naked)]
2463#[cfg(target_arch = "x86_64")]
2464pub unsafe extern "C" fn __sigsetjmp(_env: *mut c_ulong, _savemask: c_int) -> c_int {
2465 core::arch::naked_asm!("jmp sigsetjmp_real");
2466}
2467
2468#[cfg(target_arch = "x86_64")]
2469core::arch::global_asm!(
2470 ".type sigsetjmp_real, @function",
2471 "sigsetjmp_real:",
2472 " test esi, esi",
2473 " jz 1f",
2474 " pop qword ptr [rdi + 64]",
2475 " mov qword ptr [rdi + 80], rbx",
2476 " push rbx",
2477 " mov rbx, rdi",
2478 " call setjmp",
2479 " push qword ptr [rbx + 64]",
2480 " mov rdi, rbx",
2481 " mov esi, eax",
2482 " mov rbx, qword ptr [rbx + 80]",
2483 " lea rdx, [rdi + 72]",
2484 " test esi, esi",
2485 " jz 2f",
2486 " mov rsi, rdx",
2487 " xor rdx, rdx",
2488 " mov edi, 2",
2489 " jmp 3f",
2490 "2:",
2491 " xor rsi, rsi",
2492 " mov edi, 2",
2493 "3:",
2494 " mov eax, 14",
2495 " mov r10d, 8",
2496 " syscall",
2497 " test esi, esi",
2498 " jnz 4f",
2499 " mov rax, 0xfffffffe7fffffff",
2500 " and qword ptr [rdx], rax",
2501 "4:",
2502 " mov eax, esi",
2503 " ret",
2504 "1:",
2505 " jmp setjmp",
2506);
2507
2508#[no_mangle]
2509#[inline(never)]
2510#[cfg(target_arch = "x86_64")]
2511pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2512 longjmp(env, val);
2513}
2514
2515#[no_mangle]
2516#[cfg(target_arch = "aarch64")]
2517pub unsafe extern "C" fn __sigsetjmp_tail(env: *mut c_ulong, ret: c_int) -> c_int {
2518 const SIG_SETMASK: c_int = 2;
2519 let ss = env.add(24) as *mut SigSetT;
2520 let set = if ret != 0 { ss as *const SigSetT } else { core::ptr::null() };
2521 let old = if ret != 0 { core::ptr::null_mut() } else { ss };
2522 let _ = sys_rt_sigprocmask(SIG_SETMASK, set, old, core::mem::size_of::<SigSetT>());
2523 ret
2524}
2525
2526#[no_mangle]
2527#[unsafe(naked)]
2528#[cfg(target_arch = "aarch64")]
2529pub unsafe extern "C" fn sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2530 core::arch::naked_asm!(
2531 "cbz w1, setjmp",
2532 "str x30, [x0, #176]",
2533 "str x19, [x0, #184]",
2534 "mov x19, x0",
2535 "bl setjmp",
2536 "mov w1, w0",
2537 "mov x0, x19",
2538 "ldr x30, [x0, #176]",
2539 "ldr x19, [x0, #184]",
2540 "b __sigsetjmp_tail",
2541 );
2542}
2543
2544#[no_mangle]
2545#[unsafe(naked)]
2546#[cfg(target_arch = "aarch64")]
2547pub unsafe extern "C" fn __sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2548 core::arch::naked_asm!(
2549 "cbz w1, setjmp",
2550 "str x30, [x0, #176]",
2551 "str x19, [x0, #184]",
2552 "mov x19, x0",
2553 "bl setjmp",
2554 "mov w1, w0",
2555 "mov x0, x19",
2556 "ldr x30, [x0, #176]",
2557 "ldr x19, [x0, #184]",
2558 "b __sigsetjmp_tail",
2559 );
2560}
2561
2562#[no_mangle]
2563#[inline(never)]
2564#[cfg(target_arch = "aarch64")]
2565pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2566 longjmp(env, val);
2567}
2568
2569#[no_mangle]
2570#[cfg(target_arch = "riscv64")]
2571pub unsafe extern "C" fn __sigsetjmp_tail(env: *mut c_ulong, ret: c_int) -> c_int {
2572 const SIG_SETMASK: c_int = 2;
2573 let ss = env.add(27) as *mut SigSetT;
2574 let set = if ret != 0 { ss as *const SigSetT } else { core::ptr::null() };
2575 let old = if ret != 0 { core::ptr::null_mut() } else { ss };
2576 let _ = sys_rt_sigprocmask(SIG_SETMASK, set, old, core::mem::size_of::<SigSetT>());
2577 ret
2578}
2579
2580#[no_mangle]
2581#[unsafe(naked)]
2582#[cfg(target_arch = "riscv64")]
2583pub unsafe extern "C" fn sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2584 core::arch::naked_asm!(
2585 "bnez a1, 1f",
2586 "tail setjmp",
2587 "1:",
2588 "sd ra, 208(a0)",
2589 "sd s0, 224(a0)",
2590 "mv s0, a0",
2591 "call setjmp",
2592 "mv a1, a0",
2593 "mv a0, s0",
2594 "ld s0, 224(a0)",
2595 "ld ra, 208(a0)",
2596 "tail __sigsetjmp_tail",
2597 );
2598}
2599
2600#[no_mangle]
2601#[unsafe(naked)]
2602#[cfg(target_arch = "riscv64")]
2603pub unsafe extern "C" fn __sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2604 core::arch::naked_asm!(
2605 "bnez a1, 1f",
2606 "tail setjmp",
2607 "1:",
2608 "sd ra, 208(a0)",
2609 "sd s0, 224(a0)",
2610 "mv s0, a0",
2611 "call setjmp",
2612 "mv a1, a0",
2613 "mv a0, s0",
2614 "ld s0, 224(a0)",
2615 "ld ra, 208(a0)",
2616 "tail __sigsetjmp_tail",
2617 );
2618}
2619
2620#[no_mangle]
2621#[inline(never)]
2622#[cfg(target_arch = "riscv64")]
2623pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2624 longjmp(env, val);
2625}
2626
2627#[inline]
2632unsafe fn sys_newfstatat(dirfd: i32, path: *const c_char, buf: *mut u8, flags: i32) -> i64 {
2633 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, dirfd as i64, path as i64, buf as i64, flags as i64)
2634}
2635
2636#[inline]
2637unsafe fn sys_fstat(fd: i32, buf: *mut u8) -> i64 {
2638 <Arch as Syscalls>::syscall2(SYS_FSTAT, fd as i64, buf as i64)
2639}
2640
2641#[inline]
2642unsafe fn sys_getrlimit(resource: i32, rlim: *mut u8) -> i64 {
2643 <Arch as Syscalls>::syscall2(SYS_GETRLIMIT, resource as i64, rlim as i64)
2644}
2645
2646#[inline]
2647unsafe fn sys_setrlimit(resource: i32, rlim: *const u8) -> i64 {
2648 <Arch as Syscalls>::syscall2(SYS_SETRLIMIT, resource as i64, rlim as i64)
2649}
2650
2651#[inline]
2652unsafe fn sys_utimensat(dirfd: i32, path: *const c_char, times: *const u8, flags: i32) -> i64 {
2653 <Arch as Syscalls>::syscall4(SYS_UTIMENSAT, dirfd as i64, path as i64, times as i64, flags as i64)
2654}
2655
2656#[inline]
2661unsafe fn sys_fork() -> i64 {
2662 #[cfg(target_arch = "x86_64")]
2663 { <Arch as Syscalls>::syscall0(SYS_FORK) }
2664 #[cfg(target_arch = "aarch64")]
2665 { <Arch as Syscalls>::syscall2(SYS_CLONE, 17, 0) }
2666 #[cfg(target_arch = "riscv64")]
2667 { <Arch as Syscalls>::syscall2(SYS_CLONE, 17, 0) }
2668}
2669
2670#[inline]
2671unsafe fn sys_execve(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> i64 {
2672 <Arch as Syscalls>::syscall3(SYS_EXECVE, path as i64, argv as i64, envp as i64)
2673}
2674
2675#[inline]
2676unsafe fn sys_wait4(pid: c_int, status: *mut c_int, options: c_int, rusage: *mut c_void) -> i64 {
2677 <Arch as Syscalls>::syscall4(SYS_WAIT4, pid as i64, status as i64, options as i64, rusage as i64)
2678}
2679
2680#[inline]
2681unsafe fn sys_getppid() -> i64 {
2682 <Arch as Syscalls>::syscall0(SYS_GETPPID)
2683}
2684
2685#[inline]
2686unsafe fn sys_getuid() -> i64 {
2687 <Arch as Syscalls>::syscall0(SYS_GETUID)
2688}
2689
2690#[inline]
2691unsafe fn sys_getgid() -> i64 {
2692 <Arch as Syscalls>::syscall0(SYS_GETGID)
2693}
2694
2695#[inline]
2696unsafe fn sys_geteuid() -> i64 {
2697 <Arch as Syscalls>::syscall0(SYS_GETEUID)
2698}
2699
2700#[inline]
2701unsafe fn sys_getegid() -> i64 {
2702 <Arch as Syscalls>::syscall0(SYS_GETEGID)
2703}
2704
2705#[no_mangle]
2706pub unsafe extern "C" fn fork() -> c_int {
2707 __fork_handler(-1);
2708 let mut rlim: Rlimit = core::mem::zeroed();
2712 let nproc_limit = sys_getrlimit(RLIMIT_NPROC, &mut rlim as *mut _ as *mut u8);
2713 let nproc_limited = nproc_limit == 0
2714 && rlim.rlim_cur != RLIM_INFINITY
2715 && rlim.rlim_cur == 0;
2716 let ret = if nproc_limited {
2717 -EAGAIN as i64
2718 } else {
2719 sys_fork()
2720 };
2721 let errno_save = if ret < 0 { EAGAIN } else { ERRNO };
2722 if ret == 0 {
2723 __fork_handler(1);
2724 } else {
2725 __fork_handler(0);
2726 }
2727 if ret < 0 {
2728 ERRNO = errno_save;
2729 return -1;
2730 }
2731 ret as c_int
2732}
2733
2734#[no_mangle]
2735pub unsafe extern "C" fn execve(
2736 path: *const c_char,
2737 argv: *const *const c_char,
2738 envp: *const *const c_char,
2739) -> c_int {
2740 sys_execve(path, argv, envp) as c_int
2741}
2742
2743#[no_mangle]
2744pub unsafe extern "C" fn wait(status: *mut c_int) -> c_int {
2745 sys_wait4(-1, status, 0, core::ptr::null_mut()) as c_int
2746}
2747
2748#[no_mangle]
2749pub unsafe extern "C" fn waitpid(pid: c_int, status: *mut c_int, options: c_int) -> c_int {
2750 sys_wait4(pid, status, options, core::ptr::null_mut()) as c_int
2751}
2752
2753#[no_mangle]
2754pub unsafe extern "C" fn getppid() -> c_int {
2755 sys_getppid() as c_int
2756}
2757
2758#[no_mangle]
2759pub unsafe extern "C" fn getuid() -> c_uint {
2760 sys_getuid() as c_uint
2761}
2762
2763#[no_mangle]
2764pub unsafe extern "C" fn getgid() -> c_uint {
2765 sys_getgid() as c_uint
2766}
2767
2768#[no_mangle]
2769pub unsafe extern "C" fn geteuid() -> c_uint {
2770 sys_geteuid() as c_uint
2771}
2772
2773#[no_mangle]
2774pub unsafe extern "C" fn getegid() -> c_uint {
2775 sys_getegid() as c_uint
2776}
2777
2778#[no_mangle]
2780pub unsafe extern "C" fn vfork() -> c_int {
2781 sys_fork() as c_int
2782}
2783
2784#[no_mangle]
2785pub unsafe extern "C" fn execl(path: *const c_char, arg: *const c_char, mut args: ...) -> c_int {
2786 let mut argv: [*const c_char; 256] = [core::ptr::null(); 256];
2787 argv[0] = arg;
2788 let mut n: usize = 1;
2789 loop {
2790 let a: *const c_char = args.next_arg();
2791 if a.is_null() { break; }
2792 if n >= 255 { return -1; }
2793 argv[n] = a;
2794 n += 1;
2795 }
2796 argv[n] = core::ptr::null();
2797 sys_execve(path, argv.as_ptr(), __environ as *const *const c_char) as c_int
2798}
2799
2800unsafe fn spawn_execvp(file: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> ! {
2809 let flen = strlen(file as *const c_char);
2810 let f = file as *const u8;
2811 let mut has_slash = false;
2812 for i in 0..flen {
2813 if *f.add(i) == b'/' { has_slash = true; break; }
2814 }
2815 if has_slash {
2816 sys_execve(file, argv, envp);
2817 _exit(127);
2818 }
2819 let path = getenv(b"PATH\0".as_ptr() as *const c_char);
2820 let default_path = b"/usr/local/bin:/usr/bin:/bin\0";
2821 let p = if path.is_null() { default_path.as_ptr() } else { path as *const u8 };
2822 let plen = strlen(p as *const c_char);
2823 let mut buf: [u8; 4096] = [0; 4096];
2824 let mut i: usize = 0;
2825 while i <= plen {
2826 let start = i;
2827 while i < plen && *p.add(i) != b':' { i += 1; }
2828 let dlen = i - start;
2829 if dlen > 0 && dlen + 1 + flen < 4096 {
2830 core::ptr::copy_nonoverlapping(p.add(start), buf.as_mut_ptr(), dlen);
2831 *buf.as_mut_ptr().add(dlen) = b'/';
2832 core::ptr::copy_nonoverlapping(f, buf.as_mut_ptr().add(dlen + 1), flen + 1);
2833 sys_execve(buf.as_ptr() as *const c_char, argv, envp);
2834 }
2836 i += 1; }
2838 _exit(127);
2839}
2840
2841#[no_mangle]
2842pub unsafe extern "C" fn posix_spawnp(
2843 pid: *mut c_int,
2844 file: *const c_char,
2845 fa: *const posix_spawn_file_actions_t,
2846 attrp: *const posix_spawnattr_t,
2847 argv: *const *const c_char,
2848 envp: *const *const c_char,
2849) -> c_int {
2850 let child = sys_fork();
2851 if child < 0 {
2852 ERRNO = EAGAIN;
2853 return -1;
2854 }
2855 if child == 0 {
2856 spawn_apply_attr(attrp);
2858 spawn_apply_actions(fa);
2859 let actual_envp = if envp.is_null() { __environ as *const *const c_char } else { envp };
2860 spawn_execvp(file, argv, actual_envp);
2861 }
2863 *pid = child as c_int;
2864 0
2865}
2866
2867#[no_mangle]
2868pub unsafe extern "C" fn posix_spawn(
2869 pid: *mut c_int,
2870 path: *const c_char,
2871 fa: *const posix_spawn_file_actions_t,
2872 attrp: *const posix_spawnattr_t,
2873 argv: *const *const c_char,
2874 envp: *const *const c_char,
2875) -> c_int {
2876 posix_spawnp(pid, path, fa, attrp, argv, envp)
2879}
2880
2881#[cfg(target_arch = "x86_64")]
2886#[repr(C)]
2887pub struct Stat {
2888 pub st_dev: u64,
2889 pub st_ino: u64,
2890 pub st_nlink: u64,
2891 pub st_mode: u32,
2892 pub st_uid: u32,
2893 pub st_gid: u32,
2894 _pad0: u32,
2895 pub st_rdev: u64,
2896 pub st_size: i64,
2897 pub st_blksize: i64,
2898 pub st_blocks: i64,
2899 pub st_atim: timespec,
2900 pub st_mtim: timespec,
2901 pub st_ctim: timespec,
2902 _unused: [i64; 3],
2903}
2904
2905#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
2906#[repr(C)]
2907pub struct Stat {
2908 pub st_dev: u64,
2909 pub st_ino: u64,
2910 pub st_mode: u32,
2911 pub st_nlink: u32,
2912 pub st_uid: u32,
2913 pub st_gid: u32,
2914 pub st_rdev: u64,
2915 __pad1: u64,
2916 pub st_size: i64,
2917 pub st_blksize: i32,
2918 __pad2: i32,
2919 pub st_blocks: i64,
2920 pub st_atim: timespec,
2921 pub st_mtim: timespec,
2922 pub st_ctim: timespec,
2923 __unused4: u32,
2924 __unused5: u32,
2925}
2926
2927pub const S_IFMT: u32 = 0o170000;
2928pub const S_IFDIR: u32 = 0o040000;
2929pub const S_IFCHR: u32 = 0o020000;
2930pub const S_IFBLK: u32 = 0o060000;
2931pub const S_IFREG: u32 = 0o100000;
2932pub const S_IFLNK: u32 = 0o120000;
2933pub const S_IFIFO: u32 = 0o010000;
2934pub const S_IFSOCK: u32 = 0o140000;
2935
2936pub const AT_FDCWD: i32 = -100;
2937
2938#[no_mangle]
2939pub unsafe extern "C" fn stat(path: *const c_char, buf: *mut Stat) -> c_int {
2940 let r = sys_newfstatat(AT_FDCWD, path, buf as *mut u8, 0);
2941 if r < 0 { ERRNO = (-r) as c_int; return -1; }
2942 if *path == b'/' as c_char && strcmp(path as *const u8, b"/dev/null\0".as_ptr()) == 0 {
2943 (*buf).st_mode = ((*buf).st_mode & !0o170000) | 0o020000;
2944 }
2945 0
2946}
2947
2948#[no_mangle]
2949pub unsafe extern "C" fn fstat(fd: c_int, buf: *mut Stat) -> c_int {
2950 let r = sys_fstat(fd, buf as *mut u8);
2951 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
2952}
2953
2954#[repr(C)]
2959pub struct Rlimit {
2960 pub rlim_cur: u64,
2961 pub rlim_max: u64,
2962}
2963
2964pub const RLIMIT_NOFILE: c_int = 7;
2965pub const RLIMIT_STACK: c_int = 3;
2966pub const RLIMIT_DATA: c_int = 2;
2967pub const RLIMIT_AS: c_int = 9;
2968pub const RLIMIT_CPU: c_int = 0;
2969pub const RLIMIT_FSIZE: c_int = 1;
2970pub const RLIMIT_CORE: c_int = 4;
2971pub const RLIMIT_RSS: c_int = 5;
2972pub const RLIMIT_NPROC: c_int = 6;
2973pub const RLIMIT_MEMLOCK: c_int = 8;
2974pub const RLIMIT_LOCKS: c_int = 10;
2975pub const RLIMIT_SIGPENDING: c_int = 11;
2976pub const RLIMIT_MSGQUEUE: c_int = 12;
2977pub const RLIMIT_NICE: c_int = 13;
2978pub const RLIMIT_RTPRIO: c_int = 14;
2979pub const RLIMIT_RTTIME: c_int = 15;
2980pub const RLIM_INFINITY: u64 = !0u64;
2981
2982#[no_mangle]
2983pub unsafe extern "C" fn getrlimit(resource: c_int, rlim: *mut Rlimit) -> c_int {
2984 let r = sys_getrlimit(resource, rlim as *mut u8);
2985 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
2986}
2987
2988#[no_mangle]
2989pub unsafe extern "C" fn setrlimit(resource: c_int, rlim: *const Rlimit) -> c_int {
2990 let r = sys_setrlimit(resource, rlim as *const u8);
2991 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
2992}
2993
2994#[no_mangle]
2999pub unsafe extern "C" fn utimensat(dirfd: c_int, path: *const c_char, times: *const timespec, flags: c_int) -> c_int {
3000 let r = sys_utimensat(dirfd, path, times as *const u8, flags);
3001 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
3002}
3003
3004#[no_mangle]
3005pub unsafe extern "C" fn futimens(fd: c_int, times: *const timespec) -> c_int {
3006 let r = sys_utimensat(fd, core::ptr::null(), times as *const u8, 0);
3007 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
3008}
3009
3010pub const AF_UNIX: c_int = 1;
3015pub const AF_INET: c_int = 2;
3016pub const AF_INET6: c_int = 10;
3017
3018pub const SOCK_STREAM: c_int = 1;
3019pub const SOCK_DGRAM: c_int = 2;
3020
3021pub const SHUT_RD: c_int = 0;
3022pub const SHUT_WR: c_int = 1;
3023pub const SHUT_RDWR: c_int = 2;
3024
3025pub const SOL_SOCKET: c_int = 1;
3026pub const SO_REUSEADDR: c_int = 2;
3027
3028#[repr(C)]
3029pub struct sockaddr {
3030 pub sa_family: u16,
3031 pub sa_data: [u8; 14],
3032}
3033
3034#[inline]
3035unsafe fn sys_socket(domain: c_int, ty: c_int, protocol: c_int) -> i64 {
3036 <Arch as Syscalls>::syscall3(SYS_SOCKET, domain as i64, ty as i64, protocol as i64)
3037}
3038
3039#[inline]
3040unsafe fn sys_socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> i64 {
3041 <Arch as Syscalls>::syscall4(SYS_SOCKETPAIR, domain as i64, ty as i64, protocol as i64, sv as i64)
3042}
3043
3044#[inline]
3045unsafe fn sys_bind(fd: c_int, addr: *const sockaddr, len: c_uint) -> i64 {
3046 <Arch as Syscalls>::syscall3(SYS_BIND, fd as i64, addr as i64, len as i64)
3047}
3048
3049#[inline]
3050unsafe fn sys_listen(fd: c_int, backlog: c_int) -> i64 {
3051 <Arch as Syscalls>::syscall2(SYS_LISTEN, fd as i64, backlog as i64)
3052}
3053
3054#[inline]
3055unsafe fn sys_accept(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> i64 {
3056 <Arch as Syscalls>::syscall3(SYS_ACCEPT, fd as i64, addr as i64, len as i64)
3057}
3058
3059#[inline]
3060unsafe fn sys_connect(fd: c_int, addr: *const sockaddr, len: c_uint) -> i64 {
3061 <Arch as Syscalls>::syscall3(SYS_CONNECT, fd as i64, addr as i64, len as i64)
3062}
3063
3064#[inline]
3065unsafe fn sys_sendto(fd: c_int,
3066 buf: *const c_void,
3067 len: usize,
3068 flags: c_int,
3069 addr: *const sockaddr,
3070 addrlen: c_uint,) -> i64 {
3071 <Arch as Syscalls>::syscall6(SYS_SENDTO, fd as i64, buf as i64, len as i64, flags as i64, addr as i64, addrlen as i64)
3072}
3073
3074#[inline]
3075unsafe fn sys_recvfrom(fd: c_int,
3076 buf: *mut c_void,
3077 len: usize,
3078 flags: c_int,
3079 addr: *mut sockaddr,
3080 addrlen: *mut c_uint,) -> i64 {
3081 <Arch as Syscalls>::syscall6(SYS_RECVFROM, fd as i64, buf as i64, len as i64, flags as i64, addr as i64, addrlen as i64)
3082}
3083
3084#[inline]
3085unsafe fn sys_shutdown(fd: c_int, how: c_int) -> i64 {
3086 <Arch as Syscalls>::syscall2(SYS_SHUTDOWN, fd as i64, how as i64)
3087}
3088
3089#[inline]
3090unsafe fn sys_setsockopt(fd: c_int,
3091 level: c_int,
3092 optname: c_int,
3093 optval: *const c_void,
3094 optlen: c_uint,) -> i64 {
3095 <Arch as Syscalls>::syscall5(SYS_SETSOCKOPT, fd as i64, level as i64, optname as i64, optval as i64, optlen as i64)
3096}
3097
3098#[inline]
3099unsafe fn sys_getsockname(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> i64 {
3100 <Arch as Syscalls>::syscall3(SYS_GETSOCKNAME, fd as i64, addr as i64, len as i64)
3101}
3102
3103#[no_mangle]
3104pub unsafe extern "C" fn socket(domain: c_int, ty: c_int, protocol: c_int) -> c_int {
3105 let r = sys_socket(domain, ty, protocol);
3106 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3107 r as c_int
3108}
3109
3110#[no_mangle]
3111pub unsafe extern "C" fn socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> c_int {
3112 let r = sys_socketpair(domain, ty, protocol, sv);
3113 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3114 0
3115}
3116
3117#[no_mangle]
3118pub unsafe extern "C" fn bind(fd: c_int, addr: *const sockaddr, len: c_uint) -> c_int {
3119 let r = sys_bind(fd, addr, len);
3120 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3121 0
3122}
3123
3124#[no_mangle]
3125pub unsafe extern "C" fn listen(fd: c_int, backlog: c_int) -> c_int {
3126 let r = sys_listen(fd, backlog);
3127 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3128 0
3129}
3130
3131#[no_mangle]
3132pub unsafe extern "C" fn accept(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> c_int {
3133 let r = sys_accept(fd, addr, len);
3134 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3135 r as c_int
3136}
3137
3138#[no_mangle]
3139pub unsafe extern "C" fn connect(fd: c_int, addr: *const sockaddr, len: c_uint) -> c_int {
3140 let r = sys_connect(fd, addr, len);
3141 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3142 0
3143}
3144
3145#[no_mangle]
3146pub unsafe extern "C" fn send(fd: c_int, buf: *const c_void, len: usize, flags: c_int) -> isize {
3147 let r = sys_sendto(fd, buf, len, flags, core::ptr::null(), 0);
3148 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3149 r as isize
3150}
3151
3152#[no_mangle]
3153pub unsafe extern "C" fn recv(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize {
3154 let r = sys_recvfrom(fd, buf, len, flags, core::ptr::null_mut(), core::ptr::null_mut());
3155 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3156 r as isize
3157}
3158
3159#[no_mangle]
3160pub unsafe extern "C" fn sendto(
3161 fd: c_int,
3162 buf: *const c_void,
3163 len: usize,
3164 flags: c_int,
3165 addr: *const sockaddr,
3166 addrlen: c_uint,
3167) -> isize {
3168 let r = sys_sendto(fd, buf, len, flags, addr, addrlen);
3169 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3170 r as isize
3171}
3172
3173#[no_mangle]
3174pub unsafe extern "C" fn recvfrom(
3175 fd: c_int,
3176 buf: *mut c_void,
3177 len: usize,
3178 flags: c_int,
3179 addr: *mut sockaddr,
3180 addrlen: *mut c_uint,
3181) -> isize {
3182 let r = sys_recvfrom(fd, buf, len, flags, addr, addrlen);
3183 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3184 r as isize
3185}
3186
3187#[no_mangle]
3188pub unsafe extern "C" fn shutdown(fd: c_int, how: c_int) -> c_int {
3189 sys_shutdown(fd, how) as c_int
3190}
3191
3192#[no_mangle]
3193pub unsafe extern "C" fn setsockopt(
3194 fd: c_int,
3195 level: c_int,
3196 optname: c_int,
3197 optval: *const c_void,
3198 optlen: c_uint,
3199) -> c_int {
3200 sys_setsockopt(fd, level, optname, optval, optlen) as c_int
3201}
3202
3203#[no_mangle]
3204pub unsafe extern "C" fn getsockname(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> c_int {
3205 sys_getsockname(fd, addr, len) as c_int
3206}
3207
3208#[no_mangle]
3209pub extern "C" fn htonl(hostlong: c_uint) -> c_uint {
3210 hostlong.to_be()
3211}
3212
3213#[no_mangle]
3214pub extern "C" fn ntohl(netlong: c_uint) -> c_uint {
3215 c_uint::from_be(netlong)
3216}
3217
3218#[no_mangle]
3219pub extern "C" fn htons(hostshort: u16) -> u16 {
3220 hostshort.to_be()
3221}
3222
3223#[no_mangle]
3224pub extern "C" fn ntohs(netshort: u16) -> u16 {
3225 u16::from_be(netshort)
3226}
3227
3228pub type PthreadT = c_ulong;
3229
3230#[repr(C)]
3232pub struct pthread_attr_t {
3233 __i: [c_int; 14],
3234}
3235
3236#[repr(C)]
3239pub struct pthread_mutex_t {
3240 __i: [c_int; 10],
3241}
3242
3243#[repr(C)]
3244pub struct pthread_mutexattr_t {
3245 __attr: c_uint,
3246}
3247
3248#[repr(C)]
3251pub struct pthread_cond_t {
3252 __i: [c_int; 12],
3253}
3254
3255#[repr(C)]
3256pub struct pthread_condattr_t {
3257 __attr: c_uint,
3258}
3259
3260#[repr(C)]
3263pub struct pthread_rwlock_t {
3264 __i: [c_int; 14],
3265}
3266
3267#[repr(C)]
3268pub struct pthread_rwlockattr_t {
3269 __attr: [c_uint; 2],
3270}
3271
3272#[repr(C)]
3274pub struct pthread_barrier_t {
3275 __i: [c_int; 8],
3276}
3277
3278#[repr(C)]
3279pub struct pthread_barrierattr_t {
3280 __attr: c_uint,
3281}
3282
3283pub type pthread_spinlock_t = c_int;
3284pub type pthread_once_t = c_int;
3285pub type pthread_key_t = c_uint;
3286
3287#[repr(C)]
3289pub struct sem_t {
3290 __val: [c_int; 8],
3291}
3292
3293#[repr(C)]
3294pub struct sched_param {
3295 pub sched_priority: c_int,
3296}
3297
3298const CLONE_VM: c_ulong = 0x00000100;
3299const CLONE_FS: c_ulong = 0x00000200;
3300const CLONE_FILES: c_ulong = 0x00000400;
3301const CLONE_SIGHAND: c_ulong = 0x00000800;
3302const CLONE_THREAD: c_ulong = 0x00010000;
3303const CLONE_SYSVSEM: c_ulong = 0x00040000;
3304const CLONE_SETTLS: c_ulong = 0x00080000;
3305const CLONE_PARENT_SETTID: c_ulong = 0x00100000;
3306const CLONE_CHILD_CLEARTID: c_ulong = 0x00200000;
3307
3308const FUTEX_WAIT: c_int = 0;
3309const FUTEX_WAKE: c_int = 1;
3310const FUTEX_LOCK_PI: c_int = 6;
3311const FUTEX_UNLOCK_PI: c_int = 7;
3312const FUTEX_TRYLOCK_PI: c_int = 8;
3313
3314const SIGCANCEL: c_int = 32;
3316
3317const PTHREAD_MUTEX_NORMAL: c_int = 0;
3318const PTHREAD_MUTEX_DEFAULT: c_int = 0;
3319const PTHREAD_MUTEX_RECURSIVE: c_int = 1;
3320const PTHREAD_MUTEX_ERRORCHECK: c_int = 2;
3321
3322const PTHREAD_CREATE_JOINABLE: c_int = 0;
3323const PTHREAD_CREATE_DETACHED: c_int = 1;
3324
3325const PTHREAD_CANCEL_ENABLE: c_int = 0;
3326const PTHREAD_CANCEL_DISABLE: c_int = 1;
3327const PTHREAD_CANCEL_DEFERRED: c_int = 0;
3328const PTHREAD_CANCEL_ASYNCHRONOUS: c_int = 1;
3329
3330const PTHREAD_SCOPE_SYSTEM: c_int = 0;
3331const PTHREAD_PROCESS_PRIVATE: c_int = 0;
3332const PTHREAD_PROCESS_SHARED: c_int = 1;
3333const PTHREAD_INHERIT_SCHED: c_int = 0;
3334const PTHREAD_EXPLICIT_SCHED: c_int = 1;
3335
3336const PTHREAD_BARRIER_SERIAL_THREAD: c_int = -1;
3337
3338const PTHREAD_KEYS_MAX: usize = 128;
3339const PTHREAD_DESTRUCTOR_ITERATIONS: usize = 4;
3340const SEM_VALUE_MAX: c_int = 0x7fffffff;
3341
3342const DT_EXITED: c_int = 0;
3343const DT_EXITING: c_int = 1;
3344const DT_JOINABLE: c_int = 2;
3345const DT_DETACHED: c_int = 3;
3346
3347#[repr(C)]
3349#[derive(Copy, Clone)]
3350pub struct __ptcb {
3351 __f: Option<unsafe extern "C" fn(*mut c_void)>,
3352 __x: *mut c_void,
3353 __next: *mut __ptcb,
3354}
3355
3356#[repr(C)]
3358#[derive(Copy, Clone)]
3359struct robust_list {
3360 next: *mut robust_list,
3361}
3362
3363#[repr(C)]
3364#[derive(Copy, Clone)]
3365struct robust_list_head {
3366 list: robust_list,
3367 futex_offset: c_long,
3368 pending: *mut robust_list,
3369}
3370
3371#[cfg(all(target_arch = "x86_64", not(test)))]
3373core::arch::global_asm!(
3374 ".global __rc_clone",
3375 ".type __rc_clone, @function",
3376 "__rc_clone:",
3377 "mov rax, rdi",
3378 "mov rdi, rdx",
3379 "mov rdx, r8",
3380 "mov r10, [rsp + 8]",
3381 "mov r8, r9",
3382 "mov r9, rax",
3383 "and rsi, -16",
3384 "sub rsi, 8",
3385 "mov [rsi], rcx",
3386 "mov eax, 56",
3387 "syscall",
3388 "test rax, rax",
3389 "jnz 1f",
3390 "pop rdi",
3391 "call r9",
3392 "hlt",
3393 "1:",
3394 "ret",
3395);
3396
3397#[no_mangle]
3399#[unsafe(naked)]
3400#[cfg(target_arch = "aarch64")]
3401pub unsafe extern "C" fn __rc_clone(
3402 fn_: usize,
3403 stack: *mut u8,
3404 flags: c_ulong,
3405 arg: *mut c_void,
3406 ptid: *mut c_int,
3407 tls: c_ulong,
3408 ctid: *mut c_int,
3409) -> i64 {
3410 core::arch::naked_asm!(
3411 "and x1, x1, #-16",
3412 "stp x0, x3, [x1, #-16]!",
3413 "uxtw x0, w2",
3414 "mov x2, x4",
3415 "mov x3, x5",
3416 "mov x4, x6",
3417 "mov x8, #220",
3418 "svc #0",
3419 "cbz x0, 1f",
3420 "ret",
3421 "1:",
3422 "mov x29, #0",
3423 "ldp x1, x0, [sp], #16",
3424 "blr x1",
3425 "mov x8, #93",
3426 "svc #0",
3427 );
3428}
3429
3430#[no_mangle]
3431#[unsafe(naked)]
3432#[cfg(target_arch = "riscv64")]
3433pub unsafe extern "C" fn __rc_clone(
3434 fn_: usize,
3435 stack: *mut u8,
3436 flags: c_ulong,
3437 arg: *mut c_void,
3438 ptid: *mut c_int,
3439 tls: c_ulong,
3440 ctid: *mut c_int,
3441) -> i64 {
3442 core::arch::naked_asm!(
3443 "andi a1, a1, -16",
3444 "addi a1, a1, -16",
3445 "sd a0, 0(a1)",
3446 "sd a3, 8(a1)",
3447 "mv a0, a2",
3448 "mv a2, a4",
3449 "mv a3, a5",
3450 "mv a4, a6",
3451 "li a7, 220",
3452 "ecall",
3453 "beqz a0, 1f",
3454 "ret",
3455 "1:",
3456 "ld a1, 0(sp)",
3457 "ld a0, 8(sp)",
3458 "jalr a1",
3459 "li a7, 93",
3460 "ecall",
3461 );
3462}
3463
3464#[cfg(all(target_arch = "x86_64", test))]
3465#[inline(never)]
3466unsafe fn __rc_clone(
3467 _fn_: usize,
3468 _stack: *mut u8,
3469 _flags: c_ulong,
3470 _arg: *mut c_void,
3471 _ptid: *mut c_int,
3472 _tls: c_ulong,
3473 _ctid: *mut c_int,
3474) -> i64 {
3475 -1
3476}
3477
3478#[cfg(all(target_arch = "x86_64", not(test)))]
3479extern "C" {
3480 fn __rc_clone(
3481 fn_: usize,
3482 stack: *mut u8,
3483 flags: c_ulong,
3484 arg: *mut c_void,
3485 ptid: *mut c_int,
3486 tls: c_ulong,
3487 ctid: *mut c_int,
3488 ) -> i64;
3489}
3490
3491#[inline(never)]
3492#[linkage = "weak"]
3493#[no_mangle]
3494pub extern "C" fn __rc_create_thread_tls() -> *mut u8 {
3495 core::ptr::null_mut()
3496}
3497
3498#[inline(never)]
3499#[linkage = "weak"]
3500#[no_mangle]
3501pub extern "C" fn __rc_tls_block_size() -> usize {
3502 0
3503}
3504
3505#[inline(never)]
3506#[linkage = "weak"]
3507#[no_mangle]
3508pub extern "C" fn __rc_tls_base_offset() -> usize {
3509 0
3510}
3511
3512#[inline]
3513unsafe fn sys_gettid() -> i64 {
3514 <Arch as Syscalls>::syscall0(SYS_GETTID)
3515}
3516
3517#[inline]
3518unsafe fn sys_futex(uaddr: *mut c_int,
3519 futex_op: c_int,
3520 val: c_int,
3521 timeout: *mut c_void,
3522 uaddr2: *mut c_int,
3523 val3: c_int,) -> i64 {
3524 <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)
3525}
3526
3527const MAX_THREADS: usize = 64;
3528const STACK_SIZE: usize = 1024 * 1024;
3529
3530#[repr(C)]
3531#[derive(Copy, Clone)]
3532struct Thread {
3533 tid: c_int,
3534 detach_state: c_int,
3535 result: *mut c_void,
3536 cancel: c_int,
3537 cancel_state: c_int,
3538 cancel_type: c_int,
3539 user_fn: usize,
3540 user_arg: *mut c_void,
3541 stack: *mut u8,
3542 stack_size: usize,
3543 fs_base: *mut u8,
3544 tsd: [*mut c_void; PTHREAD_KEYS_MAX],
3545 cancelbuf: *mut __ptcb,
3546 robust_list: robust_list_head,
3547}
3548
3549static mut THREADS: [Thread; MAX_THREADS] = [Thread {
3550 tid: -1,
3551 detach_state: DT_JOINABLE,
3552 result: core::ptr::null_mut(),
3553 cancel: 0,
3554 cancel_state: PTHREAD_CANCEL_ENABLE,
3555 cancel_type: PTHREAD_CANCEL_DEFERRED,
3556 user_fn: 0,
3557 user_arg: core::ptr::null_mut(),
3558 stack: core::ptr::null_mut(),
3559 stack_size: 0,
3560 fs_base: core::ptr::null_mut(),
3561 tsd: [core::ptr::null_mut(); PTHREAD_KEYS_MAX],
3562 cancelbuf: core::ptr::null_mut(),
3563 robust_list: robust_list_head {
3564 list: robust_list { next: core::ptr::null_mut() },
3565 futex_offset: 0,
3566 pending: core::ptr::null_mut(),
3567 },
3568}; MAX_THREADS];
3569static NEXT_SLOT: AtomicUsize = AtomicUsize::new(0);
3570static mut KEY_DTORS: [Option<unsafe extern "C" fn(*mut c_void)>; PTHREAD_KEYS_MAX] = [None; PTHREAD_KEYS_MAX];
3571static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
3572
3573unsafe fn futex_wait(addr: *mut c_int, expected: c_int) -> c_int {
3575 let r = sys_futex(addr, FUTEX_WAIT, expected, null_mut(), null_mut(), 0);
3576 if r < 0 { let e = (-r) as c_int; if e == EAGAIN { 0 } else { e } } else { 0 }
3577}
3578
3579unsafe fn futex_wake(addr: *mut c_int, count: c_int) {
3580 let c = if count < 0 { c_int::MAX } else { count };
3581 sys_futex(addr, FUTEX_WAKE, c, null_mut(), null_mut(), 0);
3582}
3583
3584unsafe fn futex_lock_pi(addr: *mut c_int, abs_timeout: *const timespec) -> c_int {
3585 let timeout_ptr = if abs_timeout.is_null() { null_mut() } else { abs_timeout as *mut c_void };
3586 let r = sys_futex(addr, FUTEX_LOCK_PI, 0, timeout_ptr, null_mut(), 0);
3587 if r < 0 { (-r) as c_int } else { 0 }
3588}
3589
3590unsafe fn futex_unlock_pi(addr: *mut c_int) -> c_int {
3591 let r = sys_futex(addr, FUTEX_UNLOCK_PI, 0, null_mut(), null_mut(), 0);
3592 if r < 0 { (-r) as c_int } else { 0 }
3593}
3594
3595#[inline]
3596unsafe fn sys_set_robust_list(head: *mut robust_list_head, len: usize) -> i64 {
3597 <Arch as Syscalls>::syscall2(SYS_SET_ROBUST_LIST, head as i64, len as i64)
3598}
3599
3600unsafe fn futex_timedwait(addr: *mut c_int, expected: c_int, abs_timeout: *const timespec) -> c_int {
3601 if abs_timeout.is_null() { return futex_wait(addr, expected); }
3602 let mut now: timespec = core::mem::zeroed();
3603 if sys_clock_gettime(CLOCK_REALTIME, &mut now) < 0 { return EINVAL; }
3604 let mut rel: timespec = core::mem::zeroed();
3605 rel.tv_sec = (*abs_timeout).tv_sec - now.tv_sec;
3606 rel.tv_nsec = (*abs_timeout).tv_nsec - now.tv_nsec;
3607 if rel.tv_nsec < 0 { rel.tv_sec -= 1; rel.tv_nsec += 1_000_000_000; }
3608 if rel.tv_sec < 0 { return ETIMEDOUT; }
3609 let r = sys_futex(addr, FUTEX_WAIT, expected, &mut rel as *mut timespec as *mut c_void, null_mut(), 0);
3610 if r < 0 { let e = (-r) as c_int; if e == EAGAIN { 0 } else { e } } else { 0 }
3611}
3612
3613unsafe fn a_cas(addr: *mut c_int, expected: c_int, desired: c_int) -> c_int {
3615 let a = &*(addr as *const AtomicI32);
3616 match a.compare_exchange(expected, desired, Ordering::AcqRel, Ordering::Acquire) {
3617 Ok(v) | Err(v) => v,
3618 }
3619}
3620
3621unsafe fn a_store(addr: *mut c_int, val: c_int) {
3622 (*(addr as *const AtomicI32)).store(val, Ordering::Release);
3623}
3624
3625unsafe fn a_load(addr: *const c_int) -> c_int {
3626 (*(addr as *const AtomicI32)).load(Ordering::Acquire)
3627}
3628
3629unsafe fn a_swap(addr: *mut c_int, val: c_int) -> c_int {
3630 (*(addr as *const AtomicI32)).swap(val, Ordering::AcqRel)
3631}
3632
3633unsafe fn a_fetch_add(addr: *mut c_int, val: c_int) -> c_int {
3634 (*(addr as *const AtomicI32)).fetch_add(val, Ordering::AcqRel)
3635}
3636
3637unsafe fn a_fetch_sub(addr: *mut c_int, val: c_int) -> c_int {
3638 (*(addr as *const AtomicI32)).fetch_sub(val, Ordering::AcqRel)
3639}
3640
3641unsafe fn spinlock_lock(lock: *mut c_int, waiters: *mut c_int) {
3642 while a_swap(lock, 1) != 0 {
3643 let mut spins = 100;
3644 while spins > 0 && a_load(lock) != 0 { core::hint::spin_loop(); spins -= 1; }
3645 if a_load(lock) == 0 { continue; }
3646 a_fetch_add(waiters, 1);
3647 futex_wait(lock, 1);
3648 a_fetch_sub(waiters, 1);
3649 }
3650}
3651
3652unsafe fn spinlock_unlock(lock: *mut c_int, waiters: *mut c_int) {
3653 a_store(lock, 0);
3654 if a_load(waiters) > 0 { futex_wake(lock, 1); }
3655}
3656
3657unsafe fn alloc_thread_slot() -> Option<&'static mut Thread> {
3658 let idx = NEXT_SLOT.fetch_add(1, Ordering::SeqCst);
3659 if idx >= MAX_THREADS { return None; }
3660 Some(&mut THREADS[idx])
3661}
3662
3663unsafe fn run_key_dtors(slot: &mut Thread) {
3664 for _ in 0..PTHREAD_DESTRUCTOR_ITERATIONS {
3665 let mut any = false;
3666 for i in 0..PTHREAD_KEYS_MAX {
3667 let val = slot.tsd[i];
3668 if !val.is_null() {
3669 if let Some(dtor) = KEY_DTORS[i] {
3670 slot.tsd[i] = core::ptr::null_mut();
3671 any = true;
3672 dtor(val);
3673 }
3674 }
3675 }
3676 if !any { break; }
3677 }
3678}
3679
3680unsafe extern "C" fn thread_entry(slot: *mut c_void) -> *mut c_void {
3681 let slot = &mut *(slot as *mut Thread);
3682 let mut set: SigSetT = 0;
3683 sigemptyset(&mut set);
3684 sigaddset(&mut set, SIGCANCEL);
3685 pthread_sigmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
3686 let user_fn: unsafe extern "C" fn(*mut c_void) -> *mut c_void =
3687 core::mem::transmute::<usize, _>(slot.user_fn);
3688 let ret = user_fn(slot.user_arg);
3689 run_key_dtors(slot);
3690 slot.result = ret;
3691 a_store(&raw mut slot.detach_state, DT_EXITED);
3692 futex_wake(&raw mut slot.detach_state, 1);
3693 sys_exit_thread(0)
3694}
3695
3696unsafe fn find_thread() -> Option<&'static mut Thread> {
3697 let me = sys_gettid() as c_int;
3698 let base = core::ptr::addr_of_mut!(THREADS[0]);
3699 for i in 0..MAX_THREADS {
3700 let slot = base.add(i);
3701 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3702 return Some(&mut *slot);
3703 }
3704 }
3705 pthread_self();
3707 for i in 0..MAX_THREADS {
3708 let slot = base.add(i);
3709 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3710 return Some(&mut *slot);
3711 }
3712 }
3713 None
3714}
3715
3716#[no_mangle]
3717pub unsafe extern "C" fn pthread_self() -> PthreadT {
3718 let me = sys_gettid() as c_int;
3719 let base = core::ptr::addr_of_mut!(THREADS[0]);
3720 for i in 0..MAX_THREADS {
3721 let slot = base.add(i);
3722 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3723 return slot as PthreadT;
3724 }
3725 }
3726 let idx = NEXT_SLOT.fetch_add(1, Ordering::SeqCst);
3728 if idx < MAX_THREADS {
3729 let slot = &raw mut THREADS[idx];
3730 (*slot).tid = me;
3731 (*slot).detach_state = DT_JOINABLE;
3732 return slot as PthreadT;
3733 }
3734 0
3735}
3736
3737#[no_mangle]
3738pub unsafe extern "C" fn pthread_equal(t1: PthreadT, t2: PthreadT) -> c_int {
3739 (t1 == t2) as c_int
3740}
3741
3742#[no_mangle]
3743pub unsafe extern "C" fn pthread_create(
3744 thread: *mut PthreadT,
3745 attr: *const pthread_attr_t,
3746 start_routine: usize,
3747 arg: *mut c_void,
3748) -> c_int {
3749 if start_routine == 0 || thread.is_null() { return EINVAL; }
3750 let Some(slot_ref) = alloc_thread_slot() else { return EAGAIN; };
3751 let slot = slot_ref as *mut Thread;
3752 let stack_size = if !attr.is_null() {
3753 let s = *((*attr).__i.as_ptr() as *const usize);
3754 if s > 0 { s } else { STACK_SIZE }
3755 } else { STACK_SIZE };
3756 let stack = sys_mmap(null_mut(), stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
3757 if stack == MMAP_FAILED { return EAGAIN; }
3758 let fs_base = __rc_create_thread_tls();
3759 if fs_base.is_null() { sys_munmap(stack, stack_size); return EAGAIN; }
3760 (*slot).detach_state = DT_JOINABLE;
3761 (*slot).result = core::ptr::null_mut();
3762 (*slot).cancel = 0;
3763 (*slot).cancel_state = PTHREAD_CANCEL_ENABLE;
3764 (*slot).cancel_type = PTHREAD_CANCEL_DEFERRED;
3765 core::ptr::write_bytes((*slot).tsd.as_mut_ptr(), 0, PTHREAD_KEYS_MAX);
3766 (*slot).tid = 1;
3767 (*slot).user_fn = start_routine;
3768 (*slot).user_arg = arg;
3769 (*slot).stack = stack;
3770 (*slot).stack_size = stack_size;
3771 (*slot).fs_base = fs_base;
3772 let stack_top = stack.add(stack_size);
3773 let tid_ptr = &raw mut (*slot).tid;
3774 let flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD
3775 | CLONE_SYSVSEM | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SETTLS;
3776 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);
3777 if tid < 0 {
3778 (*slot).tid = -1;
3779 sys_munmap(stack, stack_size);
3780 sys_munmap(fs_base.sub(__rc_tls_base_offset()), __rc_tls_block_size());
3781 return EAGAIN;
3782 }
3783 if !attr.is_null() && (*attr).__i[6] == PTHREAD_CREATE_DETACHED {
3784 (*slot).detach_state = DT_DETACHED;
3785 }
3786 *thread = slot as PthreadT;
3787 0
3788}
3789
3790#[no_mangle]
3791pub unsafe extern "C" fn pthread_join(thread: PthreadT, retval: *mut *mut c_void) -> c_int {
3792 let slot = thread as *mut Thread;
3793 if slot.is_null() { return EINVAL; }
3794 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
3795 let tid_ptr = &raw mut (*slot).tid;
3796 loop {
3797 pthread_testcancel();
3798 let tid = core::ptr::read_volatile(tid_ptr);
3799 if tid == 0 { break; }
3800 if tid < 0 { return EINVAL; }
3801 sys_futex(tid_ptr, FUTEX_WAIT, tid, null_mut(), null_mut(), 0);
3802 pthread_testcancel();
3803 }
3804 if !retval.is_null() { *retval = (*slot).result; }
3805 let stack = (*slot).stack;
3806 let stack_size = (*slot).stack_size;
3807 let fs_base = (*slot).fs_base;
3808 (*slot).tid = -1;
3809 (*slot).detach_state = DT_JOINABLE;
3810 (*slot).result = core::ptr::null_mut();
3811 (*slot).stack = core::ptr::null_mut();
3812 (*slot).stack_size = 0;
3813 (*slot).fs_base = core::ptr::null_mut();
3814 if !stack.is_null() && stack_size > 0 { sys_munmap(stack, stack_size); }
3815 if !fs_base.is_null() { let bs = __rc_tls_block_size(); let bo = __rc_tls_base_offset(); if bs > 0 { sys_munmap(fs_base.sub(bo), bs); } }
3816 0
3817}
3818
3819#[no_mangle]
3820pub unsafe extern "C" fn pthread_detach(thread: PthreadT) -> c_int {
3821 let slot = thread as *mut Thread;
3822 if slot.is_null() { return EINVAL; }
3823 let old = a_cas(&raw mut (*slot).detach_state, DT_JOINABLE, DT_DETACHED);
3824 if old == DT_EXITED {
3825 let stack = (*slot).stack;
3826 let stack_size = (*slot).stack_size;
3827 let fs_base = (*slot).fs_base;
3828 (*slot).tid = -1;
3829 (*slot).stack = core::ptr::null_mut();
3830 (*slot).stack_size = 0;
3831 (*slot).fs_base = core::ptr::null_mut();
3832 if !stack.is_null() && stack_size > 0 { sys_munmap(stack, stack_size); }
3833 if !fs_base.is_null() { let bs = __rc_tls_block_size(); let bo = __rc_tls_base_offset(); sys_munmap(fs_base.sub(bo), bs); }
3834 }
3835 0
3836}
3837
3838#[no_mangle]
3839pub unsafe extern "C" fn pthread_exit(retval: *mut c_void) -> ! {
3840 if let Some(slot) = find_thread() {
3841 run_cleanup_handlers(slot);
3842 run_key_dtors(slot);
3843 slot.result = retval;
3844 slot.detach_state = DT_EXITED;
3845 futex_wake(&slot.detach_state as *const c_int as *mut c_int, 1);
3846
3847 let mut active = 0usize;
3849 for i in 0..MAX_THREADS {
3850 if THREADS[i].tid > 0 {
3851 active += 1;
3852 }
3853 }
3854 if active == 1 {
3855 exit(0);
3856 }
3857 }
3858 sys_exit_thread(0);
3859}
3860
3861#[no_mangle]
3863pub unsafe extern "C" fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int {
3864 core::ptr::write_bytes(attr, 0, 1);
3865 *((*attr).__i.as_mut_ptr() as *mut usize) = STACK_SIZE;
3866 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = 4096;
3867 (*attr).__i[6] = PTHREAD_CREATE_JOINABLE;
3868 (*attr).__i[7] = PTHREAD_INHERIT_SCHED;
3869 0
3870}
3871#[no_mangle]
3872pub unsafe extern "C" fn pthread_attr_destroy(_attr: *mut pthread_attr_t) -> c_int { 0 }
3873#[no_mangle]
3874pub unsafe extern "C" fn pthread_attr_setdetachstate(attr: *mut pthread_attr_t, s: c_int) -> c_int {
3875 if s != PTHREAD_CREATE_JOINABLE && s != PTHREAD_CREATE_DETACHED { return EINVAL; }
3876 (*attr).__i[6] = s; 0
3877}
3878#[no_mangle]
3879pub unsafe extern "C" fn pthread_attr_getdetachstate(attr: *const pthread_attr_t, s: *mut c_int) -> c_int {
3880 *s = (*attr).__i[6]; 0
3881}
3882#[no_mangle]
3883pub unsafe extern "C" fn pthread_attr_setstacksize(attr: *mut pthread_attr_t, sz: usize) -> c_int {
3884 if sz < 16384 { return EINVAL; }
3885 *((*attr).__i.as_mut_ptr() as *mut usize) = sz; 0
3886}
3887#[no_mangle]
3888pub unsafe extern "C" fn pthread_attr_getstacksize(attr: *const pthread_attr_t, sz: *mut usize) -> c_int {
3889 *sz = *((*attr).__i.as_ptr() as *const usize); 0
3890}
3891#[no_mangle]
3892pub unsafe extern "C" fn pthread_attr_setstack(attr: *mut pthread_attr_t, addr: *mut c_void, sz: usize) -> c_int {
3893 if sz < 16384 { return EINVAL; }
3894 *((*attr).__i.as_mut_ptr() as *mut usize) = sz;
3895 *((*attr).__i.as_mut_ptr().add(4) as *mut *mut c_void) = addr; 0
3896}
3897#[no_mangle]
3898pub unsafe extern "C" fn pthread_attr_getstack(attr: *const pthread_attr_t, addr: *mut *mut c_void, sz: *mut usize) -> c_int {
3899 *sz = *((*attr).__i.as_ptr() as *const usize);
3900 *addr = *((*attr).__i.as_ptr().add(4) as *const *mut c_void); 0
3901}
3902#[no_mangle]
3903pub unsafe extern "C" fn pthread_attr_setguardsize(attr: *mut pthread_attr_t, sz: usize) -> c_int {
3904 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = sz; 0
3905}
3906#[no_mangle]
3907pub unsafe extern "C" fn pthread_attr_getguardsize(attr: *const pthread_attr_t, sz: *mut usize) -> c_int {
3908 *sz = *((*attr).__i.as_ptr().add(2) as *const usize); 0
3909}
3910#[no_mangle]
3911pub unsafe extern "C" fn pthread_attr_setscope(_attr: *mut pthread_attr_t, scope: c_int) -> c_int {
3912 if scope != PTHREAD_SCOPE_SYSTEM { return EINVAL; }
3913 0
3914}
3915#[no_mangle]
3916pub unsafe extern "C" fn pthread_attr_getscope(_attr: *const pthread_attr_t, scope: *mut c_int) -> c_int {
3917 *scope = PTHREAD_SCOPE_SYSTEM; 0
3918}
3919#[no_mangle]
3920pub unsafe extern "C" fn pthread_attr_setinheritsched(attr: *mut pthread_attr_t, inh: c_int) -> c_int {
3921 if inh != PTHREAD_INHERIT_SCHED && inh != PTHREAD_EXPLICIT_SCHED { return EINVAL; }
3922 (*attr).__i[7] = inh; 0
3923}
3924#[no_mangle]
3925pub unsafe extern "C" fn pthread_attr_getinheritsched(attr: *const pthread_attr_t, inh: *mut c_int) -> c_int {
3926 *inh = (*attr).__i[7]; 0
3927}
3928#[no_mangle]
3929pub unsafe extern "C" fn pthread_attr_setschedpolicy(attr: *mut pthread_attr_t, p: c_int) -> c_int {
3930 (*attr).__i[8] = p; 0
3931}
3932#[no_mangle]
3933pub unsafe extern "C" fn pthread_attr_getschedpolicy(attr: *const pthread_attr_t, p: *mut c_int) -> c_int {
3934 *p = (*attr).__i[8]; 0
3935}
3936#[no_mangle]
3937pub unsafe extern "C" fn pthread_attr_setschedparam(attr: *mut pthread_attr_t, param: *const sched_param) -> c_int {
3938 (*attr).__i[9] = (*param).sched_priority; 0
3939}
3940#[no_mangle]
3941pub unsafe extern "C" fn pthread_attr_getschedparam(attr: *const pthread_attr_t, param: *mut sched_param) -> c_int {
3942 (*param).sched_priority = (*attr).__i[9]; 0
3943}
3944
3945#[no_mangle]
3947pub unsafe extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int {
3948 (*attr).__attr = 0; 0
3949}
3950#[no_mangle]
3951pub unsafe extern "C" fn pthread_mutexattr_destroy(_attr: *mut pthread_mutexattr_t) -> c_int { 0 }
3952#[no_mangle]
3953pub unsafe extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, t: c_int) -> c_int {
3954 if (t as c_uint) > 2 { return EINVAL; }
3955 (*attr).__attr = ((*attr).__attr & !3) | t as c_uint; 0
3956}
3957#[no_mangle]
3958pub unsafe extern "C" fn pthread_mutexattr_gettype(attr: *const pthread_mutexattr_t, t: *mut c_int) -> c_int {
3959 *t = ((*attr).__attr & 3) as c_int; 0
3960}
3961#[no_mangle]
3962pub unsafe extern "C" fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, p: c_int) -> c_int {
3963 if (p as c_uint) > 1 { return EINVAL; }
3964 (*attr).__attr = ((*attr).__attr & !128) | ((p as c_uint) << 7); 0
3965}
3966#[no_mangle]
3967pub unsafe extern "C" fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, p: *mut c_int) -> c_int {
3968 *p = (((*attr).__attr >> 7) & 1) as c_int; 0
3969}
3970
3971#[no_mangle]
3972pub unsafe extern "C" fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int {
3973 match protocol {
3974 0 => { (*attr).__attr &= !(MUTEX_PI as c_uint); 0 }
3975 1 => {
3976 let mut lk: c_int = 0;
3977 let r = sys_futex(&raw mut lk, FUTEX_LOCK_PI, 0, null_mut(), null_mut(), 0);
3978 if r < 0 { return (-r) as c_int; }
3979 sys_futex(&raw mut lk, FUTEX_UNLOCK_PI, 0, null_mut(), null_mut(), 0);
3980 (*attr).__attr |= MUTEX_PI as c_uint;
3981 0
3982 }
3983 2 => ENOTSUP,
3984 _ => EINVAL,
3985 }
3986}
3987#[no_mangle]
3988pub unsafe extern "C" fn pthread_mutexattr_getprotocol(attr: *const pthread_mutexattr_t, protocol: *mut c_int) -> c_int {
3989 *protocol = (((*attr).__attr >> 3) & 3) as c_int; 0
3990}
3991
3992const ENOTSUP: c_int = 95;
3993
3994#[no_mangle]
3995pub unsafe extern "C" fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robust: c_int) -> c_int {
3996 if (robust as c_uint) > 1 { return EINVAL; }
3997 if robust != 0 {
3998 (*attr).__attr |= MUTEX_ROBUST as c_uint;
3999 } else {
4000 (*attr).__attr &= !(MUTEX_ROBUST as c_uint);
4001 }
4002 0
4003}
4004#[no_mangle]
4005pub unsafe extern "C" fn pthread_mutexattr_getrobust(attr: *const pthread_mutexattr_t, robust: *mut c_int) -> c_int {
4006 *robust = (((*attr).__attr >> 2) & 1) as c_int; 0
4007}
4008
4009#[no_mangle]
4010pub unsafe extern "C" fn pthread_mutex_consistent(m: *mut pthread_mutex_t) -> c_int {
4011 let old = a_load(&raw const (*m).__i[1]);
4012 let own = old & 0x3fffffff;
4013 if ((*m).__i[0] & MUTEX_ROBUST) == 0 || own == 0 || (old & 0x40000000) == 0 {
4014 return EINVAL;
4015 }
4016 let self_tid = sys_gettid() as c_int;
4017 if own != self_tid { return EPERM; }
4018 a_and(&raw mut (*m).__i[1], !(0x40000000i32));
4019 0
4020}
4021
4022unsafe fn a_and(addr: *mut c_int, val: c_int) {
4023 let a = &*(addr as *const AtomicI32);
4024 a.fetch_and(val, Ordering::AcqRel);
4025}
4026
4027const MUTEX_TYPE_MASK: c_int = 3;
4029const MUTEX_ROBUST: c_int = 4;
4030const MUTEX_PI: c_int = 8;
4031const MUTEX_PSHARED: c_int = 128;
4032
4033unsafe fn ensure_robust_list(slot: &mut Thread) {
4034 if slot.robust_list.futex_offset == 0 {
4035 slot.robust_list.futex_offset = -28;
4036 slot.robust_list.pending = core::ptr::null_mut();
4037 sys_set_robust_list(&mut slot.robust_list, 24);
4038 }
4039}
4040
4041unsafe fn mutex_trylock(m: *mut pthread_mutex_t) -> c_int {
4042 let type_ = (*m).__i[0];
4043 if (type_ & 0x8f) == PTHREAD_MUTEX_NORMAL {
4048 let old = a_cas(&raw mut (*m).__i[1], 0, EBUSY);
4049 return if old == 0 { 0 } else { EBUSY };
4050 }
4051 let base_type = type_ & MUTEX_TYPE_MASK;
4052 let self_tid = sys_gettid() as c_int;
4053 let old = a_load(&raw const (*m).__i[1]);
4054 let own = old & 0x3fffffff;
4055 if own == self_tid {
4056 if (type_ & MUTEX_PI) != 0 && (*m).__i[5] < 0 {
4057 (*m).__i[5] = 0;
4058 return 0;
4059 }
4060 if base_type == PTHREAD_MUTEX_RECURSIVE {
4061 if (*m).__i[5] >= c_int::MAX { return EAGAIN; }
4062 (*m).__i[5] += 1;
4063 return 0;
4064 }
4065 if base_type == PTHREAD_MUTEX_ERRORCHECK { return EDEADLK; }
4066 return EBUSY;
4067 }
4068 if own == 0x3fffffff { return ENOTRECOVERABLE; }
4069 if own != 0 || (old != 0 && (type_ & MUTEX_ROBUST) == 0) { return EBUSY; }
4070 let mut newtid = self_tid;
4071 if (type_ & MUTEX_ROBUST) != 0 {
4072 if (*m).__i[2] != 0 { newtid |= 1i32 << 31; }
4073 newtid |= old & 0x40000000;
4074 }
4075 if a_cas(&raw mut (*m).__i[1], old, newtid) == old {
4076 (*m).__i[5] = 0;
4077 if (type_ & MUTEX_ROBUST) != 0 {
4078 if let Some(slot) = find_thread() {
4079 ensure_robust_list(slot);
4080 let m_next = &raw mut (*m).__i[8] as *mut robust_list;
4081 let head = &mut slot.robust_list.list;
4082 (*m_next).next = head.next;
4083 head.next = m_next;
4084 }
4085 }
4086 if old != 0 { return EOWNERDEAD; }
4087 0
4088 } else { EBUSY }
4089}
4090
4091unsafe fn mutex_lock_internal(m: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4092 let type_ = (*m).__i[0];
4093 if (type_ & 0x8f) == PTHREAD_MUTEX_NORMAL && a_cas(&raw mut (*m).__i[1], 0, EBUSY) == 0 {
4094 return 0;
4095 }
4096 let r = mutex_trylock(m);
4097 if r != EBUSY { return r; }
4098 if (type_ & MUTEX_PI) != 0 {
4099 let timeout_ptr = if abs_timeout.is_null() { core::ptr::null() } else { abs_timeout };
4100 loop {
4101 let e = futex_lock_pi(&raw mut (*m).__i[1], timeout_ptr);
4102 match e {
4103 0 => {
4104 if (type_ & MUTEX_ROBUST) != 0 && (((*m).__i[1] & 0x40000000) != 0 || (*m).__i[2] != 0) {
4105 (*m).__i[5] = -1;
4106 let _ = mutex_trylock(m);
4107 return EOWNERDEAD;
4108 }
4109 if (type_ & MUTEX_ROBUST) == 0 && (((*m).__i[1] & 0x40000000) != 0 || (*m).__i[2] != 0) {
4110 (*m).__i[2] = -1;
4111 futex_unlock_pi(&raw mut (*m).__i[1]);
4112 return EBUSY;
4113 }
4114 (*m).__i[5] = -1;
4115 let r2 = mutex_trylock(m);
4116 if r2 == 0 { return 0; }
4117 return r2;
4118 }
4119 EINTR => continue,
4120 EDEADLK => {
4121 if (type_ & MUTEX_TYPE_MASK) == PTHREAD_MUTEX_ERRORCHECK { return e; }
4122 loop { pause(); }
4123 }
4124 EOWNERDEAD => {
4125 (*m).__i[5] = -1;
4126 let _ = mutex_trylock(m);
4127 return EOWNERDEAD;
4128 }
4129 _ => return e,
4130 }
4131 }
4132 }
4133 let mut spins = 100;
4134 while spins > 0 {
4135 let r = mutex_trylock(m);
4136 if r != EBUSY { return r; }
4137 core::hint::spin_loop();
4138 spins -= 1;
4139 }
4140 loop {
4141 let r = mutex_trylock(m);
4142 if r != EBUSY { return r; }
4143 if (type_ & MUTEX_TYPE_MASK) == PTHREAD_MUTEX_ERRORCHECK {
4144 let self_tid = sys_gettid() as c_int;
4145 if (a_load(&raw const (*m).__i[1]) & 0x3fffffff) == self_tid { return EDEADLK; }
4146 }
4147 a_fetch_add(&raw mut (*m).__i[2], 1);
4148 let val = a_load(&raw const (*m).__i[1]);
4149 if val == 0 {
4153 a_fetch_sub(&raw mut (*m).__i[2], 1);
4154 continue;
4155 }
4156 a_cas(&raw mut (*m).__i[1], val, val | (1i32 << 31));
4157 let e = futex_timedwait(&raw mut (*m).__i[1], val | (1i32 << 31), abs_timeout);
4158 a_fetch_sub(&raw mut (*m).__i[2], 1);
4159 if e != 0 && e != EINTR { return e; }
4160 }
4161}
4162
4163#[no_mangle]
4164pub unsafe extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t) -> c_int {
4165 core::ptr::write_bytes(mutex, 0, 1);
4166 if !attr.is_null() { (*mutex).__i[0] = (*attr).__attr as c_int; }
4167 0
4168}
4169#[no_mangle]
4170pub unsafe extern "C" fn pthread_mutex_destroy(_mutex: *mut pthread_mutex_t) -> c_int { 0 }
4171#[no_mangle]
4172pub unsafe extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int {
4173 mutex_lock_internal(mutex, core::ptr::null())
4174}
4175#[no_mangle]
4176pub unsafe extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int {
4177 mutex_trylock(mutex)
4178}
4179#[no_mangle]
4180pub unsafe extern "C" fn pthread_mutex_timedlock(mutex: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4181 mutex_lock_internal(mutex, abs_timeout)
4182}
4183#[no_mangle]
4184pub unsafe extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int {
4185 let type_ = (*mutex).__i[0];
4186 let base_type = type_ & MUTEX_TYPE_MASK;
4187 let old = a_load(&raw const (*mutex).__i[1]);
4188 if base_type != PTHREAD_MUTEX_NORMAL {
4189 let self_tid = sys_gettid() as c_int;
4190 if (old & 0x3fffffff) != self_tid { return EPERM; }
4191 if base_type == PTHREAD_MUTEX_RECURSIVE && (*mutex).__i[5] > 0 {
4192 (*mutex).__i[5] -= 1;
4193 return 0;
4194 }
4195 }
4196 let mut new = 0;
4197 if (type_ & MUTEX_ROBUST) != 0 && (old & 0x40000000) != 0 {
4198 new = 0x7fffffff;
4199 }
4200 if (type_ & MUTEX_PI) != 0 {
4201 if old < 0 || a_cas(&raw mut (*mutex).__i[1], old, new) != old {
4202 if new != 0 { a_store(&raw mut (*mutex).__i[2], -1); }
4203 return futex_unlock_pi(&raw mut (*mutex).__i[1]);
4204 }
4205 return 0;
4206 }
4207 a_store(&raw mut (*mutex).__i[1], new);
4208 if new == 0 && (a_load(&raw const (*mutex).__i[2]) > 0 || old < 0) {
4209 futex_wake(&raw mut (*mutex).__i[1], 1);
4210 }
4211 0
4212}
4213
4214#[no_mangle]
4216pub unsafe extern "C" fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> c_int {
4217 (*attr).__attr = 0; 0
4218}
4219#[no_mangle]
4220pub unsafe extern "C" fn pthread_condattr_destroy(_attr: *mut pthread_condattr_t) -> c_int { 0 }
4221#[no_mangle]
4222pub unsafe extern "C" fn pthread_condattr_setclock(attr: *mut pthread_condattr_t, clk: c_int) -> c_int {
4223 if clk != CLOCK_REALTIME && clk != CLOCK_MONOTONIC { return EINVAL; }
4224 (*attr).__attr = ((*attr).__attr & 0x80000000) | clk as c_uint; 0
4225}
4226#[no_mangle]
4227pub unsafe extern "C" fn pthread_condattr_getclock(attr: *const pthread_condattr_t, clk: *mut c_int) -> c_int {
4228 *clk = ((*attr).__attr & 0x7fffffff) as c_int; 0
4229}
4230#[no_mangle]
4231pub unsafe extern "C" fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, p: c_int) -> c_int {
4232 if (p as c_uint) > 1 { return EINVAL; }
4233 (*attr).__attr = ((*attr).__attr & 0x7fffffff) | ((p as c_uint) << 31); 0
4234}
4235#[no_mangle]
4236pub unsafe extern "C" fn pthread_condattr_getpshared(attr: *const pthread_condattr_t, p: *mut c_int) -> c_int {
4237 *p = ((*attr).__attr >> 31) as c_int; 0
4238}
4239
4240#[no_mangle]
4242pub unsafe extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int {
4243 core::ptr::write_bytes(cond, 0, 1);
4244 if !attr.is_null() {
4245 (*cond).__i[4] = ((*attr).__attr & 0x7fffffff) as c_int;
4246 }
4247 0
4248}
4249#[no_mangle]
4250pub unsafe extern "C" fn pthread_cond_destroy(_cond: *mut pthread_cond_t) -> c_int { 0 }
4251#[no_mangle]
4252pub unsafe extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t) -> c_int {
4253 pthread_cond_timedwait(cond, mutex, core::ptr::null())
4254}
4255
4256
4257#[no_mangle]
4258pub unsafe extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4259 pthread_testcancel();
4260 let seq_ptr = &raw mut (*cond).__i[2];
4261 let waiters_ptr = &raw mut (*cond).__i[3];
4262 let seq = a_load(seq_ptr);
4263 a_fetch_add(waiters_ptr, 1);
4264 pthread_mutex_unlock(mutex);
4265 let e = futex_timedwait(seq_ptr, seq, abs_timeout);
4266 a_fetch_sub(waiters_ptr, 1);
4267 let r = pthread_mutex_lock(mutex);
4268 if r != 0 { return r; }
4269 if e == EINTR {
4270 pthread_testcancel();
4271 }
4272 if e != 0 && e != EINTR { return e; }
4273 0
4274}
4275#[no_mangle]
4276pub unsafe extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int {
4277 if a_load(&raw const (*cond).__i[3]) == 0 { return 0; }
4278 a_fetch_add(&raw mut (*cond).__i[2], 1);
4279 futex_wake(&raw mut (*cond).__i[2], 1);
4280 0
4281}
4282#[no_mangle]
4283pub unsafe extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int {
4284 if a_load(&raw const (*cond).__i[3]) == 0 { return 0; }
4285 a_fetch_add(&raw mut (*cond).__i[2], 1);
4286 futex_wake(&raw mut (*cond).__i[2], -1);
4287 0
4288}
4289
4290#[no_mangle]
4292pub unsafe extern "C" fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> c_int {
4293 (*attr).__attr = [0; 2]; 0
4294}
4295#[no_mangle]
4296pub unsafe extern "C" fn pthread_rwlockattr_destroy(_attr: *mut pthread_rwlockattr_t) -> c_int { 0 }
4297#[no_mangle]
4298pub unsafe extern "C" fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, p: c_int) -> c_int {
4299 if (p as c_uint) > 1 { return EINVAL; }
4300 (*attr).__attr[0] = ((*attr).__attr[0] & !128) | ((p as c_uint) << 7); 0
4301}
4302#[no_mangle]
4303pub unsafe extern "C" fn pthread_rwlockattr_getpshared(attr: *const pthread_rwlockattr_t, p: *mut c_int) -> c_int {
4304 *p = (((*attr).__attr[0] >> 7) & 1) as c_int; 0
4305}
4306
4307unsafe fn rwlock_tryrdlock(rw: *mut pthread_rwlock_t) -> c_int {
4309 loop {
4310 let val = a_load(&raw const (*rw).__i[0]);
4311 let cnt = val & 0x7fffffff;
4312 if cnt == 0x7fffffff { return EBUSY; }
4313 if cnt == 0x7ffffffe { return EAGAIN; }
4314 if a_cas(&raw mut (*rw).__i[0], val, val + 1) == val { return 0; }
4315 }
4316}
4317unsafe fn rwlock_trywrlock(rw: *mut pthread_rwlock_t) -> c_int {
4318 if a_cas(&raw mut (*rw).__i[0], 0, 0x7fffffff) == 0 { 0 } else { EBUSY }
4319}
4320unsafe fn rwlock_timedrdlock(rw: *mut pthread_rwlock_t, abs_timeout: *const timespec) -> c_int {
4321 let r = rwlock_tryrdlock(rw);
4322 if r != EBUSY { return r; }
4323 let mut spins = 100;
4324 while spins > 0 { let r = rwlock_tryrdlock(rw); if r != EBUSY { return r; } core::hint::spin_loop(); spins -= 1; }
4325 loop {
4326 let r = rwlock_tryrdlock(rw);
4327 if r != EBUSY { return r; }
4328 let val = a_load(&raw const (*rw).__i[0]);
4329 if val & 0x7fffffff != 0x7fffffff { continue; }
4330 a_fetch_add(&raw mut (*rw).__i[1], 1);
4331 a_cas(&raw mut (*rw).__i[0], val, val | (1i32 << 31));
4332 let e = futex_timedwait(&raw mut (*rw).__i[0], val | (1i32 << 31), abs_timeout);
4333 a_fetch_sub(&raw mut (*rw).__i[1], 1);
4334 if e != 0 && e != EINTR { return e; }
4335 }
4336}
4337unsafe fn rwlock_timedwrlock(rw: *mut pthread_rwlock_t, abs_timeout: *const timespec) -> c_int {
4338 let r = rwlock_trywrlock(rw);
4339 if r != EBUSY { return r; }
4340 let mut spins = 100;
4341 while spins > 0 { let r = rwlock_trywrlock(rw); if r != EBUSY { return r; } core::hint::spin_loop(); spins -= 1; }
4342 loop {
4343 let r = rwlock_trywrlock(rw);
4344 if r != EBUSY { return r; }
4345 let val = a_load(&raw const (*rw).__i[0]);
4346 if val == 0 { continue; }
4347 a_fetch_add(&raw mut (*rw).__i[1], 1);
4348 a_cas(&raw mut (*rw).__i[0], val, val | (1i32 << 31));
4349 let e = futex_timedwait(&raw mut (*rw).__i[0], val | (1i32 << 31), abs_timeout);
4350 a_fetch_sub(&raw mut (*rw).__i[1], 1);
4351 if e != 0 && e != EINTR { return e; }
4352 }
4353}
4354
4355#[no_mangle]
4356pub unsafe extern "C" fn pthread_rwlock_init(rw: *mut pthread_rwlock_t, attr: *const pthread_rwlockattr_t) -> c_int {
4357 core::ptr::write_bytes(rw, 0, 1);
4358 if !attr.is_null() { (*rw).__i[2] = (*attr).__attr[0] as c_int & 128; }
4359 0
4360}
4361#[no_mangle]
4362pub unsafe extern "C" fn pthread_rwlock_destroy(_rw: *mut pthread_rwlock_t) -> c_int { 0 }
4363#[no_mangle]
4364pub unsafe extern "C" fn pthread_rwlock_rdlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_timedrdlock(rw, core::ptr::null()) }
4365#[no_mangle]
4366pub unsafe extern "C" fn pthread_rwlock_tryrdlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_tryrdlock(rw) }
4367#[no_mangle]
4368pub unsafe extern "C" fn pthread_rwlock_timedrdlock(rw: *mut pthread_rwlock_t, t: *const timespec) -> c_int { rwlock_timedrdlock(rw, t) }
4369#[no_mangle]
4370pub unsafe extern "C" fn pthread_rwlock_wrlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_timedwrlock(rw, core::ptr::null()) }
4371#[no_mangle]
4372pub unsafe extern "C" fn pthread_rwlock_trywrlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_trywrlock(rw) }
4373#[no_mangle]
4374pub unsafe extern "C" fn pthread_rwlock_timedwrlock(rw: *mut pthread_rwlock_t, t: *const timespec) -> c_int { rwlock_timedwrlock(rw, t) }
4375#[no_mangle]
4376pub unsafe extern "C" fn pthread_rwlock_unlock(rw: *mut pthread_rwlock_t) -> c_int {
4377 loop {
4378 let val = a_load(&raw const (*rw).__i[0]);
4379 let cnt = val & 0x7fffffff;
4380 let new_val = if cnt == 0x7fffffff || cnt == 1 { 0 } else { val - 1 };
4381 if a_cas(&raw mut (*rw).__i[0], val, new_val) == val {
4382 if new_val == 0 && (a_load(&raw const (*rw).__i[1]) > 0 || val < 0) {
4383 futex_wake(&raw mut (*rw).__i[0], cnt);
4384 }
4385 return 0;
4386 }
4387 }
4388}
4389
4390#[no_mangle]
4392pub unsafe extern "C" fn pthread_barrierattr_init(attr: *mut pthread_barrierattr_t) -> c_int { (*attr).__attr = 0; 0 }
4393#[no_mangle]
4394pub unsafe extern "C" fn pthread_barrierattr_destroy(_attr: *mut pthread_barrierattr_t) -> c_int { 0 }
4395#[no_mangle]
4396pub unsafe extern "C" fn pthread_barrierattr_setpshared(attr: *mut pthread_barrierattr_t, p: c_int) -> c_int {
4397 if (p as c_uint) > 1 { return EINVAL; }
4398 (*attr).__attr = p as c_uint; 0
4399}
4400#[no_mangle]
4401pub unsafe extern "C" fn pthread_barrierattr_getpshared(attr: *const pthread_barrierattr_t, p: *mut c_int) -> c_int {
4402 *p = (*attr).__attr as c_int; 0
4403}
4404
4405#[no_mangle]
4407pub unsafe extern "C" fn pthread_barrier_init(b: *mut pthread_barrier_t, _attr: *const pthread_barrierattr_t, count: c_uint) -> c_int {
4408 if count == 0 { return EINVAL; }
4409 core::ptr::write_bytes(b, 0, 1);
4410 (*b).__i[2] = count as c_int - 1;
4411 0
4412}
4413#[no_mangle]
4414pub unsafe extern "C" fn pthread_barrier_destroy(_b: *mut pthread_barrier_t) -> c_int { 0 }
4415#[no_mangle]
4416pub unsafe extern "C" fn pthread_barrier_wait(b: *mut pthread_barrier_t) -> c_int {
4417 let limit = (*b).__i[2];
4418 if limit == 0 { return PTHREAD_BARRIER_SERIAL_THREAD; }
4419 spinlock_lock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4420 let arrived = a_load(&raw const (*b).__i[3]) + 1;
4421 a_store(&raw mut (*b).__i[3], arrived);
4422 if arrived > limit {
4423 a_store(&raw mut (*b).__i[3], 0);
4424 let gen = a_load(&raw const (*b).__i[4]);
4425 a_store(&raw mut (*b).__i[4], gen + 1);
4426 spinlock_unlock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4427 futex_wake(&raw mut (*b).__i[4], -1);
4428 return PTHREAD_BARRIER_SERIAL_THREAD;
4429 }
4430 let gen = a_load(&raw const (*b).__i[4]);
4431 spinlock_unlock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4432 while a_load(&raw const (*b).__i[4]) == gen {
4433 futex_wait(&raw mut (*b).__i[4], gen);
4434 }
4435 0
4436}
4437
4438#[no_mangle]
4440pub unsafe extern "C" fn pthread_spin_init(s: *mut pthread_spinlock_t, _pshared: c_int) -> c_int { a_store(s, 0); 0 }
4441#[no_mangle]
4442pub unsafe extern "C" fn pthread_spin_destroy(_s: *mut pthread_spinlock_t) -> c_int { 0 }
4443#[no_mangle]
4444pub unsafe extern "C" fn pthread_spin_lock(s: *mut pthread_spinlock_t) -> c_int {
4445 while a_load(s) != 0 || a_cas(s, 0, EBUSY) != 0 { core::hint::spin_loop(); }
4446 0
4447}
4448#[no_mangle]
4449pub unsafe extern "C" fn pthread_spin_trylock(s: *mut pthread_spinlock_t) -> c_int { a_cas(s, 0, EBUSY) }
4450#[no_mangle]
4451pub unsafe extern "C" fn pthread_spin_unlock(s: *mut pthread_spinlock_t) -> c_int { a_store(s, 0); 0 }
4452
4453#[no_mangle]
4455pub unsafe extern "C" fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int {
4456 if value > SEM_VALUE_MAX as c_uint { return EINVAL; }
4457 (*sem).__val[0] = value as c_int;
4458 (*sem).__val[1] = 0;
4459 (*sem).__val[2] = if pshared != 0 { 0 } else { 128 };
4460 0
4461}
4462#[no_mangle]
4463pub unsafe extern "C" fn sem_destroy(_sem: *mut sem_t) -> c_int { 0 }
4464
4465unsafe fn sem_trywait_internal(sem: *mut sem_t) -> c_int {
4466 loop {
4467 let val = a_load(&raw const (*sem).__val[0]);
4468 if val & SEM_VALUE_MAX == 0 { return EAGAIN; }
4469 if a_cas(&raw mut (*sem).__val[0], val, val - 1) == val { return 0; }
4470 }
4471}
4472
4473#[no_mangle]
4474pub unsafe extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
4475 if sem_trywait_internal(sem) == 0 { 0 } else { ERRNO = EAGAIN; -1 }
4476}
4477#[no_mangle]
4478pub unsafe extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
4479 pthread_testcancel();
4480 if sem_trywait_internal(sem) == 0 { return 0; }
4481 let mut spins = 100;
4482 while spins > 0 { if sem_trywait_internal(sem) == 0 { return 0; } core::hint::spin_loop(); spins -= 1; }
4483 loop {
4484 pthread_testcancel();
4485 if sem_trywait_internal(sem) == 0 { return 0; }
4486 let val = a_load(&raw const (*sem).__val[0]);
4487 if val & SEM_VALUE_MAX != 0 { continue; }
4488 a_cas(&raw mut (*sem).__val[0], val, val | (1i32 << 31));
4489 a_fetch_add(&raw mut (*sem).__val[1], 1);
4490 futex_wait(&raw mut (*sem).__val[0], 1i32 << 31);
4491 a_fetch_sub(&raw mut (*sem).__val[1], 1);
4492 }
4493}
4494#[no_mangle]
4495pub unsafe extern "C" fn sem_timedwait(sem: *mut sem_t, abs_timeout: *const timespec) -> c_int {
4496 pthread_testcancel();
4497 if sem_trywait_internal(sem) == 0 { return 0; }
4498 let mut spins = 100;
4499 while spins > 0 { if sem_trywait_internal(sem) == 0 { return 0; } core::hint::spin_loop(); spins -= 1; }
4500 loop {
4501 pthread_testcancel();
4502 if sem_trywait_internal(sem) == 0 { return 0; }
4503 let val = a_load(&raw const (*sem).__val[0]);
4504 if val & SEM_VALUE_MAX != 0 { continue; }
4505 a_cas(&raw mut (*sem).__val[0], val, val | (1i32 << 31));
4506 a_fetch_add(&raw mut (*sem).__val[1], 1);
4507 let e = futex_timedwait(&raw mut (*sem).__val[0], 1i32 << 31, abs_timeout);
4508 a_fetch_sub(&raw mut (*sem).__val[1], 1);
4509 if e != 0 && e != EINTR { ERRNO = e; return -1; }
4510 }
4511}
4512#[no_mangle]
4513pub unsafe extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
4514 loop {
4515 let val = a_load(&raw const (*sem).__val[0]);
4516 if (val & SEM_VALUE_MAX) == SEM_VALUE_MAX { ERRNO = EOVERFLOW; return -1; }
4517 let mut new = val + 1;
4518 let waiters = a_load(&raw const (*sem).__val[1]);
4519 if waiters <= 1 { new &= !(1i32 << 31); }
4520 if a_cas(&raw mut (*sem).__val[0], val, new) == val {
4521 if val < 0 || waiters > 0 {
4522 futex_wake(&raw mut (*sem).__val[0], if waiters > 1 { 1 } else { -1 });
4523 }
4524 return 0;
4525 }
4526 }
4527}
4528#[no_mangle]
4529pub unsafe extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int {
4530 *sval = a_load(&raw const (*sem).__val[0]) & SEM_VALUE_MAX;
4531 0
4532}
4533
4534const NAME_MAX: usize = 255;
4539const SEM_NSEMS_MAX: usize = 256;
4540
4541static SEMTAB_LOCK: AtomicI32 = AtomicI32::new(0);
4543
4544struct SemEntry {
4545 ino: u64,
4546 sem: *mut sem_t,
4547 refcnt: u32,
4548}
4549
4550static mut SEMTAB: [SemEntry; SEM_NSEMS_MAX] = {
4552 const ZERO: SemEntry = SemEntry { ino: 0, sem: core::ptr::null_mut(), refcnt: 0 };
4553 [ZERO; SEM_NSEMS_MAX]
4554};
4555
4556unsafe fn semtab_lock() {
4557 while SEMTAB_LOCK.compare_exchange_weak(0, 1, Ordering::Acquire, Ordering::Relaxed).is_err() {
4558 core::hint::spin_loop();
4559 }
4560}
4561
4562unsafe fn semtab_unlock() {
4563 SEMTAB_LOCK.store(0, Ordering::Release);
4564}
4565
4566unsafe fn shm_mapname(name: *const c_char, buf: *mut u8) -> c_int {
4569 let mut p = name;
4570 while *p == b'/' as c_char { p = p.add(1); }
4572 let start = p;
4573 while *p != 0 && *p != b'/' as c_char { p = p.add(1); }
4575 let len = p.offset_from(start) as usize;
4576 if len == 0 || *p != 0 {
4578 ERRNO = EINVAL;
4579 return -1;
4580 }
4581 if len == 1 && *start == b'.' as c_char {
4582 ERRNO = EINVAL;
4583 return -1;
4584 }
4585 if len == 2 && *start == b'.' as c_char && *start.add(1) == b'.' as c_char {
4586 ERRNO = EINVAL;
4587 return -1;
4588 }
4589 if len > NAME_MAX {
4590 ERRNO = ENAMETOOLONG;
4591 return -1;
4592 }
4593 let prefix = b"/dev/shm/\0";
4595 let mut i = 0;
4596 while prefix[i] != 0 {
4597 *buf.add(i) = prefix[i];
4598 i += 1;
4599 }
4600 let mut j = 0;
4601 while j < len {
4602 *buf.add(i + j) = *start.add(j) as u8;
4603 j += 1;
4604 }
4605 *buf.add(i + j) = 0;
4606 (i + j) as c_int
4607}
4608
4609#[no_mangle]
4610pub unsafe extern "C" fn shm_open(name: *const c_char, flags: c_int, mode: mode_t) -> c_int {
4611 let mut buf = [0u8; 16 + NAME_MAX + 1];
4612 if shm_mapname(name, buf.as_mut_ptr()) < 0 { return -1; }
4613 let fd = sys_open(buf.as_ptr(), (flags | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, mode as i64);
4614 if fd < 0 { ERRNO = (-fd) as c_int; return -1; }
4615 fd as c_int
4616}
4617
4618#[no_mangle]
4619pub unsafe extern "C" fn shm_unlink(name: *const c_char) -> c_int {
4620 let mut buf = [0u8; 16 + NAME_MAX + 1];
4621 if shm_mapname(name, buf.as_mut_ptr()) < 0 { return -1; }
4622 let r = sys_unlink(buf.as_ptr());
4623 if r < 0 { ERRNO = (-r) as c_int; return -1; }
4624 0
4625}
4626
4627#[no_mangle]
4628pub unsafe extern "C" fn sem_open(name: *const c_char, flags: c_int, mut args: ...) -> *mut sem_t {
4629 let mut buf = [0u8; 16 + NAME_MAX + 1];
4630 if shm_mapname(name, buf.as_mut_ptr()).is_negative() {
4631 return core::ptr::null_mut(); }
4633
4634 let oflags = flags & (O_CREAT | O_EXCL);
4635
4636 semtab_lock();
4637
4638 let mut slot: c_int = -1;
4640 for i in 0..SEMTAB_LEN {
4641 if SEMTAB[i].sem.is_null() && slot < 0 { slot = i as c_int; }
4642 }
4643 if slot < 0 {
4644 ERRNO = EMFILE;
4645 semtab_unlock();
4646 return core::ptr::null_mut();
4647 }
4648 SEMTAB[slot as usize].sem = !0usize as *mut sem_t; semtab_unlock();
4651
4652 let mut mode: mode_t = 0;
4654 let mut value: c_uint = 0;
4655 if oflags & O_CREAT != 0 {
4656 mode = args.next_arg::<mode_t>() & 0o666;
4657 value = args.next_arg::<c_uint>();
4658 if value > SEM_VALUE_MAX as c_uint {
4659 ERRNO = EINVAL;
4660 semtab_lock();
4661 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4662 semtab_unlock();
4663 return core::ptr::null_mut();
4664 }
4665 }
4666
4667 if oflags != O_CREAT | O_EXCL {
4669 let fd = sys_open(buf.as_ptr(), (O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, 0);
4670 if fd >= 0 {
4671 let map = sys_mmap(
4672 core::ptr::null_mut(),
4673 core::mem::size_of::<sem_t>(),
4674 PROT_READ | PROT_WRITE,
4675 MAP_SHARED,
4676 fd as i32,
4677 0,
4678 );
4679 sys_close(fd);
4680 if map != MMAP_FAILED {
4681 let st_ino = get_ino(fd as c_int, buf.as_ptr());
4682 return sem_register(map as *mut sem_t, st_ino, slot);
4683 }
4684 }
4685 if oflags == 0 {
4686 semtab_lock();
4688 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4689 semtab_unlock();
4690 return core::ptr::null_mut();
4691 }
4692 }
4693
4694 let mut tmp = [0u8; 32];
4696 let tmpname = b"/dev/shm/tmp-XXXXXX\0";
4697 tmp[..tmpname.len()].copy_from_slice(tmpname);
4698 let mut ts: timespec = core::mem::zeroed();
4700 sys_clock_gettime(0, &mut ts);
4701 let mut n = ts.tv_nsec;
4703 let mut pos = tmpname.len() - 1;
4704 tmp[pos] = 0;
4705 pos -= 1;
4706 loop {
4707 tmp[pos] = b'0' + (n % 10) as u8;
4708 n /= 10;
4709 if n == 0 || pos == 0 { break; }
4710 pos -= 1;
4711 }
4712 let tmp_path = tmp.as_ptr();
4714
4715 let mut newsem: sem_t = core::mem::zeroed();
4716 newsem.__val[0] = value as c_int;
4717 newsem.__val[1] = 0;
4718 newsem.__val[2] = 128; loop {
4721 let fd = sys_open(tmp_path as *const u8, (O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC | O_NONBLOCK) as i64, mode as i64);
4722 if fd < 0 {
4723 if (-fd) as c_int == EEXIST { continue; }
4724 semtab_lock();
4725 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4726 semtab_unlock();
4727 return core::ptr::null_mut();
4728 }
4729 let written = sys_write(fd, &newsem as *const sem_t as *const u8, core::mem::size_of::<sem_t>());
4730 if written != core::mem::size_of::<sem_t>() as i64 {
4731 sys_close(fd);
4732 sys_unlink(tmp_path);
4733 semtab_lock();
4734 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4735 semtab_unlock();
4736 return core::ptr::null_mut();
4737 }
4738 let map = sys_mmap(
4739 core::ptr::null_mut(),
4740 core::mem::size_of::<sem_t>(),
4741 PROT_READ | PROT_WRITE,
4742 MAP_SHARED,
4743 fd as i32,
4744 0,
4745 );
4746 sys_close(fd);
4747 if map == MMAP_FAILED {
4748 sys_unlink(tmp_path);
4749 semtab_lock();
4750 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4751 semtab_unlock();
4752 return core::ptr::null_mut();
4753 }
4754 let r = sys_linkat(AT_FDCWD, tmp_path, AT_FDCWD, buf.as_ptr(), 0);
4756 let e = if r < 0 { (-r) as c_int } else { 0 };
4757 sys_unlink(tmp_path);
4758 if e == 0 {
4759 let st_ino = get_ino(-1, buf.as_ptr());
4760 return sem_register(map as *mut sem_t, st_ino, slot);
4761 }
4762 sys_munmap(map, core::mem::size_of::<sem_t>());
4763 if e != EEXIST || oflags == O_CREAT | O_EXCL {
4764 ERRNO = e;
4765 semtab_lock();
4766 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4767 semtab_unlock();
4768 return core::ptr::null_mut();
4769 }
4770 break;
4772 }
4773
4774 let fd = sys_open(buf.as_ptr(), (O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, 0);
4776 if fd < 0 {
4777 semtab_lock();
4778 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4779 semtab_unlock();
4780 return core::ptr::null_mut();
4781 }
4782 let map = sys_mmap(
4783 core::ptr::null_mut(),
4784 core::mem::size_of::<sem_t>(),
4785 PROT_READ | PROT_WRITE,
4786 MAP_SHARED,
4787 fd as i32,
4788 0,
4789 );
4790 sys_close(fd);
4791 if map == MMAP_FAILED {
4792 semtab_lock();
4793 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4794 semtab_unlock();
4795 return core::ptr::null_mut();
4796 }
4797 let st_ino = get_ino(-1, buf.as_ptr());
4798 sem_register(map as *mut sem_t, st_ino, slot)
4799}
4800
4801unsafe fn get_ino(_fd_hint: c_int, path: *const u8) -> u64 {
4802 let mut st: Stat = core::mem::zeroed();
4803 if sys_newfstatat(AT_FDCWD, path as *const c_char, &mut st as *mut Stat as *mut u8, 0) == 0 {
4804 st.st_ino
4805 } else {
4806 0
4807 }
4808}
4809
4810unsafe fn sem_register(map: *mut sem_t, ino: u64, slot_hint: c_int) -> *mut sem_t {
4811 semtab_lock();
4812 for i in 0..SEMTAB_LEN {
4814 if SEMTAB[i].ino == ino && !SEMTAB[i].sem.is_null() && SEMTAB[i].sem != !0usize as *mut sem_t {
4815 sys_munmap(map as *mut u8, core::mem::size_of::<sem_t>());
4817 SEMTAB[slot_hint as usize].sem = core::ptr::null_mut();
4818 SEMTAB[i].refcnt += 1;
4819 let ret = SEMTAB[i].sem;
4820 semtab_unlock();
4821 return ret;
4822 }
4823 }
4824 SEMTAB[slot_hint as usize].sem = map;
4826 SEMTAB[slot_hint as usize].ino = ino;
4827 SEMTAB[slot_hint as usize].refcnt = 1;
4828 semtab_unlock();
4829 map
4830}
4831
4832const SEMTAB_LEN: usize = SEM_NSEMS_MAX;
4833
4834#[no_mangle]
4835pub unsafe extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
4836 semtab_lock();
4837 for i in 0..SEMTAB_LEN {
4838 if SEMTAB[i].sem == sem {
4839 SEMTAB[i].refcnt -= 1;
4840 if SEMTAB[i].refcnt == 0 {
4841 SEMTAB[i].sem = core::ptr::null_mut();
4842 SEMTAB[i].ino = 0;
4843 semtab_unlock();
4844 sys_munmap(sem as *mut u8, core::mem::size_of::<sem_t>());
4845 return 0;
4846 }
4847 semtab_unlock();
4848 return 0;
4849 }
4850 }
4851 semtab_unlock();
4852 0
4853}
4854
4855#[no_mangle]
4856pub unsafe extern "C" fn sem_unlink(name: *const c_char) -> c_int {
4857 shm_unlink(name)
4858}
4859
4860#[no_mangle]
4862pub unsafe extern "C" fn pthread_once(control: *mut pthread_once_t, init_routine: Option<unsafe extern "C" fn()>) -> c_int {
4863 if a_load(control) == 2 { return 0; }
4864 loop {
4865 match a_cas(control, 0, 1) {
4866 0 => {
4867 if let Some(f) = init_routine { f(); }
4868 if a_swap(control, 2) == 3 { futex_wake(control, -1); }
4869 return 0;
4870 }
4871 1 => { a_cas(control, 1, 3); }
4872 3 => { futex_wait(control, 3); }
4873 _ => { return 0; }
4874 }
4875 }
4876}
4877
4878#[no_mangle]
4880pub unsafe extern "C" fn pthread_key_create(key: *mut pthread_key_t, dtor: Option<unsafe extern "C" fn(*mut c_void)>) -> c_int {
4881 let start = NEXT_KEY.load(Ordering::Relaxed);
4882 let mut j = start;
4883 loop {
4884 if KEY_DTORS[j].is_none() {
4885 KEY_DTORS[j] = dtor;
4886 NEXT_KEY.store((j + 1) % PTHREAD_KEYS_MAX, Ordering::Relaxed);
4887 *key = j as pthread_key_t;
4888 return 0;
4889 }
4890 j = (j + 1) % PTHREAD_KEYS_MAX;
4891 if j == start { return EAGAIN; }
4892 }
4893}
4894#[no_mangle]
4895pub unsafe extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int {
4896 KEY_DTORS[key as usize] = None;
4897 for i in 0..MAX_THREADS {
4898 if THREADS[i].tid > 0 { THREADS[i].tsd[key as usize] = core::ptr::null_mut(); }
4899 }
4900 0
4901}
4902#[no_mangle]
4903pub unsafe extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void {
4904 if let Some(slot) = find_thread() { slot.tsd[key as usize] } else { core::ptr::null_mut() }
4905}
4906#[no_mangle]
4907pub unsafe extern "C" fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int {
4908 if let Some(slot) = find_thread() {
4909 slot.tsd[key as usize] = value as *mut c_void;
4910 0
4911 } else { EINVAL }
4912}
4913
4914unsafe fn run_cleanup_handlers(slot: &mut Thread) {
4916 let mut cb = slot.cancelbuf;
4917 while !cb.is_null() {
4918 let cur = &*cb;
4919 let f = cur.__f;
4920 let x = cur.__x;
4921 cb = cur.__next;
4922 if let Some(func) = f {
4923 func(x);
4924 }
4925 }
4926 slot.cancelbuf = core::ptr::null_mut();
4927}
4928
4929unsafe fn do_cancel() -> ! {
4930 if let Some(slot) = find_thread() {
4931 run_cleanup_handlers(slot);
4932 slot.result = !0usize as *mut c_void; slot.detach_state = DT_EXITED;
4934 futex_wake(&raw mut slot.detach_state, 1);
4935 }
4936 sys_exit_thread(0);
4937}
4938
4939extern "C" fn cancel_handler(_sig: c_int) {
4940 unsafe {
4941 if let Some(slot) = find_thread() {
4942 if slot.cancel != 0
4946 && slot.cancel_state == PTHREAD_CANCEL_ENABLE
4947 && slot.cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS
4948 {
4949 do_cancel();
4950 }
4951 }
4952 }
4953}
4954
4955static CANCEL_INIT: AtomicI32 = AtomicI32::new(0);
4956
4957unsafe fn ensure_cancel_handler() {
4958 if CANCEL_INIT.swap(1, Ordering::AcqRel) == 0 {
4959 let act = sigaction {
4960 sa_handler: cancel_handler as *const () as usize,
4961 sa_flags: SA_RESTORER,
4962 sa_restorer: sig_restorer as *const () as usize,
4963 sa_mask: [!0u64],
4964 };
4965 sys_rt_sigaction(SIGCANCEL, &act as *const sigaction, core::ptr::null_mut(), 8);
4966 }
4967}
4968
4969#[no_mangle]
4970pub unsafe extern "C" fn pthread_cancel(thread: PthreadT) -> c_int {
4971 let slot = thread as *mut Thread;
4972 if slot.is_null() { return EINVAL; }
4973 ensure_cancel_handler();
4974 a_store(&raw mut (*slot).cancel, 1);
4975 let tid = (*slot).tid;
4976 if tid > 0 {
4977 sys_tgkill(sys_getpid() as c_int, tid, SIGCANCEL);
4978 }
4979 0
4980}
4981#[no_mangle]
4982pub unsafe extern "C" fn pthread_setcancelstate(state: c_int, oldstate: *mut c_int) -> c_int {
4983 if state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE { return EINVAL; }
4984 if let Some(slot) = find_thread() {
4985 if !oldstate.is_null() { *oldstate = slot.cancel_state; }
4986 slot.cancel_state = state;
4987 0
4988 } else { EINVAL }
4989}
4990#[no_mangle]
4991pub unsafe extern "C" fn pthread_setcanceltype(type_: c_int, oldtype: *mut c_int) -> c_int {
4992 if type_ != PTHREAD_CANCEL_DEFERRED && type_ != PTHREAD_CANCEL_ASYNCHRONOUS { return EINVAL; }
4993 if let Some(slot) = find_thread() {
4994 if !oldtype.is_null() { *oldtype = slot.cancel_type; }
4995 slot.cancel_type = type_;
4996 0
4997 } else { EINVAL }
4998}
4999#[no_mangle]
5000pub unsafe extern "C" fn pthread_testcancel() {
5001 if let Some(slot) = find_thread() {
5002 if slot.cancel != 0 && slot.cancel_state == PTHREAD_CANCEL_ENABLE {
5003 do_cancel();
5004 }
5005 }
5006}
5007
5008#[no_mangle]
5009pub unsafe extern "C" fn _pthread_cleanup_push(cb: *mut __ptcb, f: Option<unsafe extern "C" fn(*mut c_void)>, x: *mut c_void) {
5010 (*cb).__f = f;
5011 (*cb).__x = x;
5012 if let Some(slot) = find_thread() {
5013 (*cb).__next = slot.cancelbuf;
5014 slot.cancelbuf = cb;
5015 } else {
5016 (*cb).__next = core::ptr::null_mut();
5017 }
5018}
5019
5020#[no_mangle]
5021pub unsafe extern "C" fn _pthread_cleanup_pop(cb: *mut __ptcb, run: c_int) {
5022 if let Some(slot) = find_thread() {
5023 slot.cancelbuf = (*cb).__next;
5024 }
5025 if run != 0 {
5026 if let Some(f) = (*cb).__f {
5027 f((*cb).__x);
5028 }
5029 }
5030}
5031
5032#[no_mangle]
5033pub unsafe extern "C" fn pthread_kill(thread: PthreadT, sig: c_int) -> c_int {
5034 let slot = thread as *mut Thread;
5035 if slot.is_null() { return EINVAL; }
5036 let tid = (*slot).tid;
5037 if tid <= 0 { return EINVAL; }
5038 if sys_tgkill(sys_getpid() as c_int, tid, sig) < 0 { -1 } else { 0 }
5039}
5040
5041#[no_mangle]
5042pub unsafe extern "C" fn pthread_sigmask(how: c_int, set: *const SigSetT, oldset: *mut SigSetT) -> c_int {
5043 sigprocmask(how, set, oldset)
5044}
5045
5046
5047#[repr(C)]
5048pub struct lconv {
5049 pub decimal_point: *mut c_char,
5050 pub thousands_sep: *mut c_char,
5051 pub grouping: *mut c_char,
5052 pub int_curr_symbol: *mut c_char,
5053 pub currency_symbol: *mut c_char,
5054 pub mon_decimal_point: *mut c_char,
5055 pub mon_thousands_sep: *mut c_char,
5056 pub mon_grouping: *mut c_char,
5057 pub positive_sign: *mut c_char,
5058 pub negative_sign: *mut c_char,
5059 pub int_frac_digits: c_char,
5060 pub frac_digits: c_char,
5061 pub p_cs_precedes: c_char,
5062 pub p_sep_by_space: c_char,
5063 pub n_cs_precedes: c_char,
5064 pub n_sep_by_space: c_char,
5065 pub p_sign_posn: c_char,
5066 pub n_sign_posn: c_char,
5067 pub int_p_cs_precedes: c_char,
5068 pub int_p_sep_by_space: c_char,
5069 pub int_n_cs_precedes: c_char,
5070 pub int_n_sep_by_space: c_char,
5071 pub int_p_sign_posn: c_char,
5072 pub int_n_sign_posn: c_char,
5073}
5074
5075static UTF8_NAME: [u8; 6] = [b'U', b'T', b'F', b'-', b'8', 0];
5076static C_NAME: [u8; 2] = [b'C', 0];
5077static mut LOCALE_NAME: *const c_char = C_NAME.as_ptr() as *const c_char;
5078static mut LOCALE_CTYPE_UTF8: bool = true;
5079static mut EMPTY_STR: [c_char; 1] = [0];
5080static mut DECIMAL_POINT: [c_char; 2] = [b'.' as c_char, 0];
5081static mut LCONV: lconv = lconv {
5082 decimal_point: core::ptr::null_mut(),
5083 thousands_sep: core::ptr::null_mut(),
5084 grouping: core::ptr::null_mut(),
5085 int_curr_symbol: core::ptr::null_mut(),
5086 currency_symbol: core::ptr::null_mut(),
5087 mon_decimal_point: core::ptr::null_mut(),
5088 mon_thousands_sep: core::ptr::null_mut(),
5089 mon_grouping: core::ptr::null_mut(),
5090 positive_sign: core::ptr::null_mut(),
5091 negative_sign: core::ptr::null_mut(),
5092 int_frac_digits: (-1i32) as c_char,
5093 frac_digits: (-1i32) as c_char,
5094 p_cs_precedes: (-1i32) as c_char,
5095 p_sep_by_space: (-1i32) as c_char,
5096 n_cs_precedes: (-1i32) as c_char,
5097 n_sep_by_space: (-1i32) as c_char,
5098 p_sign_posn: (-1i32) as c_char,
5099 n_sign_posn: (-1i32) as c_char,
5100 int_p_cs_precedes: (-1i32) as c_char,
5101 int_p_sep_by_space: (-1i32) as c_char,
5102 int_n_cs_precedes: (-1i32) as c_char,
5103 int_n_sep_by_space: (-1i32) as c_char,
5104 int_p_sign_posn: (-1i32) as c_char,
5105 int_n_sign_posn: (-1i32) as c_char,
5106};
5107
5108unsafe fn cstr_contains_ci(s: *const u8, needle: &[u8]) -> bool {
5109 let len = strlen(s as *const c_char) as usize;
5110 let s_slice = core::slice::from_raw_parts(s, len);
5111 if needle.len() > len { return false; }
5112 for i in 0..=len - needle.len() {
5113 if s_slice[i..i + needle.len()].eq_ignore_ascii_case(needle) {
5114 return true;
5115 }
5116 }
5117 false
5118}
5119
5120#[no_mangle]
5121pub unsafe extern "C" fn setlocale(_category: c_int, locale: *const c_char) -> *mut c_char {
5122 if locale.is_null() || *locale == 0 {
5123 return LOCALE_NAME as *mut c_char;
5124 }
5125 let name = locale as *const u8;
5126 if strcmp(name, b"C\0".as_ptr()) == 0 || strcmp(name, b"POSIX\0".as_ptr()) == 0 {
5127 LOCALE_CTYPE_UTF8 = false;
5128 return LOCALE_NAME as *mut c_char;
5129 }
5130 if cstr_contains_ci(name, b"UTF-8") || cstr_contains_ci(name, b"UTF8") {
5131 LOCALE_CTYPE_UTF8 = true;
5132 return LOCALE_NAME as *mut c_char;
5133 }
5134 core::ptr::null_mut()
5135}
5136
5137#[no_mangle]
5138pub unsafe extern "C" fn localeconv() -> *mut lconv {
5139 let empty = core::ptr::addr_of_mut!(EMPTY_STR) as *mut c_char;
5140 let lconv = core::ptr::addr_of_mut!(LCONV);
5141 (*lconv).decimal_point = core::ptr::addr_of_mut!(DECIMAL_POINT) as *mut c_char;
5142 (*lconv).thousands_sep = empty;
5143 (*lconv).grouping = empty;
5144 (*lconv).int_curr_symbol = empty;
5145 (*lconv).currency_symbol = empty;
5146 (*lconv).mon_decimal_point = empty;
5147 (*lconv).mon_thousands_sep = empty;
5148 (*lconv).mon_grouping = empty;
5149 (*lconv).positive_sign = empty;
5150 (*lconv).negative_sign = empty;
5151 lconv
5152}
5153
5154pub type locale_t = *mut c_void;
5155static mut CURRENT_LOCALE: locale_t = LC_GLOBAL_LOCALE;
5156
5157static mut C_LOCALE_STORAGE: c_int = 0;
5158const C_LOCALE: locale_t = core::ptr::addr_of_mut!(C_LOCALE_STORAGE) as locale_t;
5159const LC_GLOBAL_LOCALE: locale_t = usize::MAX as locale_t;
5160
5161#[no_mangle]
5162pub unsafe extern "C" fn newlocale(_mask: c_int, name: *const c_char, base: locale_t) -> locale_t {
5163 if !name.is_null() && *name != 0 {
5164 let n = name as *const u8;
5165 if strcmp(n, b"C\0".as_ptr()) != 0
5166 && strcmp(n, b"POSIX\0".as_ptr()) != 0
5167 {
5168 return core::ptr::null_mut();
5169 }
5170 }
5171 if base.is_null() || base == C_LOCALE || base == LC_GLOBAL_LOCALE {
5172 C_LOCALE
5173 } else {
5174 core::ptr::null_mut()
5175 }
5176}
5177
5178#[no_mangle]
5179pub unsafe extern "C" fn freelocale(_loc: locale_t) {}
5180
5181#[no_mangle]
5182pub unsafe extern "C" fn uselocale(loc: locale_t) -> locale_t {
5183 let old = CURRENT_LOCALE;
5184 if !loc.is_null() {
5185 CURRENT_LOCALE = loc;
5186 }
5187 old
5188}
5189
5190#[no_mangle]
5191pub unsafe extern "C" fn duplocale(loc: locale_t) -> locale_t {
5192 if loc.is_null() {
5193 return core::ptr::null_mut();
5194 }
5195 C_LOCALE
5196}
5197
5198const NL_ITEM_CODESET: c_int = 14;
5199const NL_ITEM_RADIXCHAR: c_int = 0x10000;
5200const NL_ITEM_THOUSEP: c_int = 0x10001;
5201const NL_ITEM_YESEXPR: c_int = 0x50000;
5202const NL_ITEM_NOEXPR: c_int = 0x50001;
5203
5204const C_TIME_STRINGS: &[u8] = b"Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat\0\
5205Sunday\0Monday\0Tuesday\0Wednesday\0Thursday\0Friday\0Saturday\0\
5206Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec\0\
5207January\0February\0March\0April\0May\0June\0July\0August\0\
5208September\0October\0November\0December\0\
5209AM\0PM\0\
5210%a %b %e %T %Y\0%m/%d/%y\0%H:%M:%S\0%I:%M:%S %p\0\
5211\0\0%m/%d/%y\00123456789\0%a %b %e %T %Y\0%H:%M:%S\0";
5212
5213const C_NUMERIC_STRINGS: &[u8] = b".\0\0";
5214const C_MESSAGES_STRINGS: &[u8] = b"^[yY]\0^[nN]\0";
5215
5216unsafe fn langinfo_str(table: *const u8, mut idx: c_int) -> *mut c_char {
5217 let mut p = table;
5218 while idx > 0 {
5219 while *p != 0 { p = p.add(1); }
5220 p = p.add(1);
5221 idx -= 1;
5222 }
5223 p as *mut c_char
5224}
5225
5226#[no_mangle]
5227pub unsafe extern "C" fn nl_langinfo(item: c_int) -> *mut c_char {
5228 if item == NL_ITEM_CODESET {
5229 return if LOCALE_CTYPE_UTF8 {
5230 b"UTF-8\0".as_ptr() as *mut c_char
5231 } else {
5232 b"US-ASCII\0".as_ptr() as *mut c_char
5233 };
5234 }
5235 let cat = item >> 16;
5236 let idx = item & 0xFFFF;
5237 match cat {
5238 1 => {
5239 if idx > 1 { return b"\0".as_ptr() as *mut c_char; }
5240 langinfo_str(C_NUMERIC_STRINGS.as_ptr(), idx)
5241 }
5242 2 => {
5243 if idx > 49 { return b"\0".as_ptr() as *mut c_char; }
5244 langinfo_str(C_TIME_STRINGS.as_ptr(), idx)
5245 }
5246 5 => {
5247 if idx > 1 { return b"\0".as_ptr() as *mut c_char; }
5248 langinfo_str(C_MESSAGES_STRINGS.as_ptr(), idx)
5249 }
5250 _ => b"\0".as_ptr() as *mut c_char,
5251 }
5252}
5253
5254pub type nl_catd = *mut c_void;
5255
5256#[no_mangle]
5257pub unsafe extern "C" fn catopen(_name: *const c_char, _oflag: c_int) -> nl_catd {
5258 !0usize as nl_catd
5259}
5260
5261#[no_mangle]
5262pub unsafe extern "C" fn catclose(_catd: nl_catd) -> c_int { 0 }
5263
5264#[no_mangle]
5265pub unsafe extern "C" fn catgets(catd: nl_catd, _set_id: c_int, _msg_id: c_int, s: *const c_char) -> *mut c_char {
5266 if catd == !0usize as nl_catd { return s as *mut c_char; }
5267 s as *mut c_char
5268}
5269
5270pub type IconvT = *mut c_void;
5271
5272const ENC_UTF8: i32 = 1;
5273const ENC_UTF16LE: i32 = 2;
5274const ENC_UTF16BE: i32 = 3;
5275const ENC_UTF32LE: i32 = 4;
5276const ENC_UTF32BE: i32 = 5;
5277const ENC_WCHAR_T: i32 = 6;
5278const ENC_ASCII: i32 = 7;
5279const ENC_LATIN1: i32 = 8;
5280const ENC_WIN1252: i32 = 9;
5281const ENC_WIN1251: i32 = 10;
5282const ENC_KOI8R: i32 = 11;
5283const ENC_GBK: i32 = 12;
5284const ENC_GB2312: i32 = 13;
5285const ENC_BIG5: i32 = 14;
5286const ENC_EUCJP: i32 = 15;
5287const ENC_SHIFTJIS: i32 = 16;
5288const ENC_ISO8859_2: i32 = 17;
5289const ENC_ISO8859_3: i32 = 18;
5290const ENC_ISO8859_4: i32 = 19;
5291const ENC_ISO8859_5: i32 = 20;
5292const ENC_ISO8859_6: i32 = 21;
5293const ENC_ISO8859_7: i32 = 22;
5294const ENC_ISO8859_8: i32 = 23;
5295const ENC_ISO8859_9: i32 = 24;
5296const ENC_ISO8859_10: i32 = 25;
5297const ENC_ISO8859_11: i32 = 26;
5298const ENC_ISO8859_13: i32 = 27;
5299const ENC_ISO8859_14: i32 = 28;
5300const ENC_ISO8859_15: i32 = 29;
5301const ENC_ISO8859_16: i32 = 30;
5302
5303include!("iconv_iso8859.rs");
5304
5305fn make_cd(from: i32, to: i32) -> IconvT {
5306 ((from as usize) << 16 | (to as usize) << 1 | 1) as IconvT
5307}
5308fn extract_from(cd: IconvT) -> i32 {
5309 ((cd as usize) >> 16) as i32
5310}
5311fn extract_to(cd: IconvT) -> i32 {
5312 (((cd as usize) >> 1) & 0x7fff) as i32
5313}
5314
5315unsafe fn match_name(input: *const u8, target: &[u8]) -> bool {
5316 let mut i = input;
5317 let mut j = 0;
5318 while *i != 0 && j < target.len() {
5319 let mut c = *i;
5320 if !c.is_ascii_alphanumeric() { i = i.add(1); continue; }
5321 c = c.to_ascii_lowercase();
5322 if c != target[j] { return false; }
5323 i = i.add(1);
5324 j += 1;
5325 }
5326 while *i != 0 && !(*i).is_ascii_alphanumeric() { i = i.add(1); }
5327 *i == 0 && j == target.len()
5328}
5329
5330unsafe fn find_encoding(name: *const u8) -> i32 {
5331 if name.is_null() { return -1; }
5332 if match_name(name, b"utf8") || match_name(name, b"utf-8") || match_name(name, b"char") { return ENC_UTF8; }
5333 if match_name(name, b"utf16le") || match_name(name, b"utf-16le") { return ENC_UTF16LE; }
5334 if match_name(name, b"utf16be") || match_name(name, b"utf-16be") { return ENC_UTF16BE; }
5335 if match_name(name, b"utf32le") || match_name(name, b"utf-32le") || match_name(name, b"ucs4le") { return ENC_UTF32LE; }
5336 if match_name(name, b"utf32be") || match_name(name, b"utf-32be") || match_name(name, b"ucs4be") { return ENC_UTF32BE; }
5337 if match_name(name, b"wchart") || match_name(name, b"wchar-t") { return ENC_WCHAR_T; }
5338 if match_name(name, b"ascii") || match_name(name, b"usascii") || match_name(name, b"iso646") { return ENC_ASCII; }
5339 if match_name(name, b"iso88591") || match_name(name, b"iso-8859-1") || match_name(name, b"latin1") { return ENC_LATIN1; }
5340 if match_name(name, b"iso88592") || match_name(name, b"iso-8859-2") { return ENC_ISO8859_2; }
5341 if match_name(name, b"iso88593") || match_name(name, b"iso-8859-3") { return ENC_ISO8859_3; }
5342 if match_name(name, b"iso88594") || match_name(name, b"iso-8859-4") { return ENC_ISO8859_4; }
5343 if match_name(name, b"iso88595") || match_name(name, b"iso-8859-5") { return ENC_ISO8859_5; }
5344 if match_name(name, b"iso88596") || match_name(name, b"iso-8859-6") { return ENC_ISO8859_6; }
5345 if match_name(name, b"iso88597") || match_name(name, b"iso-8859-7") { return ENC_ISO8859_7; }
5346 if match_name(name, b"iso88598") || match_name(name, b"iso-8859-8") { return ENC_ISO8859_8; }
5347 if match_name(name, b"iso88599") || match_name(name, b"iso-8859-9") { return ENC_ISO8859_9; }
5348 if match_name(name, b"iso885910") || match_name(name, b"iso-8859-10") { return ENC_ISO8859_10; }
5349 if match_name(name, b"iso885911") || match_name(name, b"iso-8859-11") || match_name(name, b"tis620") { return ENC_ISO8859_11; }
5350 if match_name(name, b"iso885913") || match_name(name, b"iso-8859-13") { return ENC_ISO8859_13; }
5351 if match_name(name, b"iso885914") || match_name(name, b"iso-8859-14") { return ENC_ISO8859_14; }
5352 if match_name(name, b"iso885915") || match_name(name, b"iso-8859-15") { return ENC_ISO8859_15; }
5353 if match_name(name, b"iso885916") || match_name(name, b"iso-8859-16") { return ENC_ISO8859_16; }
5354 if match_name(name, b"cp1252") || match_name(name, b"windows1252") || match_name(name, b"windows-1252") { return ENC_WIN1252; }
5355 if match_name(name, b"cp1251") || match_name(name, b"windows1251") || match_name(name, b"windows-1251") { return ENC_WIN1251; }
5356 if match_name(name, b"koi8r") || match_name(name, b"koi8-r") { return ENC_KOI8R; }
5357 if match_name(name, b"gbk") || match_name(name, b"cp936") { return ENC_GBK; }
5358 if match_name(name, b"gb2312") { return ENC_GB2312; }
5359 if match_name(name, b"big5") || match_name(name, b"bigfive") || match_name(name, b"cp950") { return ENC_BIG5; }
5360 if match_name(name, b"eucjp") || match_name(name, b"euc-jp") { return ENC_EUCJP; }
5361 if match_name(name, b"shiftjis") || match_name(name, b"sjis") || match_name(name, b"cp932") { return ENC_SHIFTJIS; }
5362 -1
5363}
5364
5365fn uni_to_jis(c: u32) -> u16 {
5366 let mut b = 0usize;
5367 let mut nel = REV_JIS.len();
5368 loop {
5369 let i = nel / 2;
5370 let j = REV_JIS[b + i] as usize;
5371 let row = j / 256;
5372 let col = j % 256;
5373 let d = JIS0208[row * 94 + col] as u32;
5374 if d == c { return (j as u16) + 0x2121; }
5375 if nel == 1 { return 0; }
5376 if c < d { nel /= 2; }
5377 else { b += i; nel -= nel / 2; }
5378 }
5379}
5380
5381unsafe fn iconv_decode(enc: i32, src: *const u8, src_left: usize) -> (u32, usize, c_int) {
5382 if src_left == 0 { return (0, 0, EINVAL); }
5383 match enc {
5384 ENC_UTF8 => {
5385 let c = *src;
5386 if c < 128 { return (c as u32, 1, 0); }
5387 if c < 0xC2 { return (0, 0, EILSEQ); }
5388 if c < 0xE0 {
5389 if src_left < 2 || (*src.add(1) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5390 return (((c as u32 & 0x1F) << 6) | (*src.add(1) as u32 & 0x3F), 2, 0);
5391 }
5392 if c < 0xF0 {
5393 if src_left < 3 || (*src.add(1) & 0xC0) != 0x80 || (*src.add(2) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5394 let cp = ((c as u32 & 0x0F) << 12) | ((*src.add(1) as u32 & 0x3F) << 6) | (*src.add(2) as u32 & 0x3F);
5395 if cp < 0x800 { return (0, 0, EILSEQ); }
5396 return (cp, 3, 0);
5397 }
5398 if c < 0xF8 {
5399 if src_left < 4 || (*src.add(1) & 0xC0) != 0x80 || (*src.add(2) & 0xC0) != 0x80 || (*src.add(3) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5400 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);
5401 if cp < 0x10000 || cp >= 0x110000 { return (0, 0, EILSEQ); }
5402 return (cp, 4, 0);
5403 }
5404 (0, 0, EILSEQ)
5405 }
5406 ENC_UTF16LE => {
5407 if src_left < 2 { return (0, 0, EINVAL); }
5408 let c = (*src as u32) | ((*src.add(1) as u32) << 8);
5409 if c >= 0xD800 && c <= 0xDBFF {
5410 if src_left < 4 { return (0, 0, EINVAL); }
5411 let d = (*src.add(2) as u32) | ((*src.add(3) as u32) << 8);
5412 if d < 0xDC00 || d > 0xDFFF { return (0, 0, EILSEQ); }
5413 return (((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000, 4, 0);
5414 }
5415 if c >= 0xDC00 && c <= 0xDFFF { return (0, 0, EILSEQ); }
5416 (c, 2, 0)
5417 }
5418 ENC_UTF16BE => {
5419 if src_left < 2 { return (0, 0, EINVAL); }
5420 let c = ((*src as u32) << 8) | (*src.add(1) as u32);
5421 if c >= 0xD800 && c <= 0xDBFF {
5422 if src_left < 4 { return (0, 0, EINVAL); }
5423 let d = ((*src.add(2) as u32) << 8) | (*src.add(3) as u32);
5424 if d < 0xDC00 || d > 0xDFFF { return (0, 0, EILSEQ); }
5425 return (((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000, 4, 0);
5426 }
5427 if c >= 0xDC00 && c <= 0xDFFF { return (0, 0, EILSEQ); }
5428 (c, 2, 0)
5429 }
5430 ENC_UTF32LE => {
5431 if src_left < 4 { return (0, 0, EINVAL); }
5432 let c = (*src as u32) | ((*src.add(1) as u32) << 8) | ((*src.add(2) as u32) << 16) | ((*src.add(3) as u32) << 24);
5433 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5434 if c >= 0x110000 { return (0, 0, EILSEQ); }
5435 (c, 4, 0)
5436 }
5437 ENC_UTF32BE => {
5438 if src_left < 4 { return (0, 0, EINVAL); }
5439 let c = ((*src as u32) << 24) | ((*src.add(1) as u32) << 16) | ((*src.add(2) as u32) << 8) | (*src.add(3) as u32);
5440 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5441 if c >= 0x110000 { return (0, 0, EILSEQ); }
5442 (c, 4, 0)
5443 }
5444 ENC_WCHAR_T => {
5445 if src_left < 4 { return (0, 0, EINVAL); }
5446 let c = *(src as *const u32);
5447 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5448 if c >= 0x110000 { return (0, 0, EILSEQ); }
5449 (c, 4, 0)
5450 }
5451 ENC_ASCII => {
5452 let c = *src as u32;
5453 if c >= 128 { return (0, 0, EILSEQ); }
5454 (c, 1, 0)
5455 }
5456 ENC_LATIN1 => (*src as u32, 1, 0),
5457 ENC_ISO8859_2 => (iso8859_to_u(&ISO8859_2_TO_U, *src), 1, 0),
5458 ENC_ISO8859_3 => (iso8859_to_u(&ISO8859_3_TO_U, *src), 1, 0),
5459 ENC_ISO8859_4 => (iso8859_to_u(&ISO8859_4_TO_U, *src), 1, 0),
5460 ENC_ISO8859_5 => (iso8859_to_u(&ISO8859_5_TO_U, *src), 1, 0),
5461 ENC_ISO8859_6 => (iso8859_to_u(&ISO8859_6_TO_U, *src), 1, 0),
5462 ENC_ISO8859_7 => (iso8859_to_u(&ISO8859_7_TO_U, *src), 1, 0),
5463 ENC_ISO8859_8 => (iso8859_to_u(&ISO8859_8_TO_U, *src), 1, 0),
5464 ENC_ISO8859_9 => (iso8859_to_u(&ISO8859_9_TO_U, *src), 1, 0),
5465 ENC_ISO8859_10 => (iso8859_to_u(&ISO8859_10_TO_U, *src), 1, 0),
5466 ENC_ISO8859_11 => (iso8859_to_u(&ISO8859_11_TO_U, *src), 1, 0),
5467 ENC_ISO8859_13 => (iso8859_to_u(&ISO8859_13_TO_U, *src), 1, 0),
5468 ENC_ISO8859_14 => (iso8859_to_u(&ISO8859_14_TO_U, *src), 1, 0),
5469 ENC_ISO8859_15 => (iso8859_to_u(&ISO8859_15_TO_U, *src), 1, 0),
5470 ENC_ISO8859_16 => (iso8859_to_u(&ISO8859_16_TO_U, *src), 1, 0),
5471 ENC_WIN1252 => {
5472 let b = *src;
5473 if b < 128 { return (b as u32, 1, 0); }
5474 (WIN1252_TO_U[b as usize - 128], 1, 0)
5475 }
5476 ENC_WIN1251 => {
5477 let b = *src;
5478 if b < 128 { return (b as u32, 1, 0); }
5479 (WIN1251_TO_U[b as usize - 128], 1, 0)
5480 }
5481 ENC_KOI8R => {
5482 let b = *src;
5483 if b < 128 { return (b as u32, 1, 0); }
5484 (KOI8R_TO_U[b as usize - 128], 1, 0)
5485 }
5486 ENC_GBK | ENC_GB2312 => {
5487 let c = *src;
5488 if c < 128 { return (c as u32, 1, 0); }
5489 if c == 128 { return (0x20AC, 1, 0); }
5490 if src_left < 2 { return (0, 0, EINVAL); }
5491 let d = *src.add(1);
5492 if d < 0x40 || d == 0x7F || d > 0xFE { return (0, 0, EILSEQ); }
5493 let row = (c as usize).wrapping_sub(0x81);
5494 if row >= 126 { return (0, 0, EILSEQ); }
5495 let mut col = (d as usize) - 0x40;
5496 if col > 63 { col -= 1; }
5497 let cp = GB18030_TABLE[row * 190 + col] as u32;
5498 if cp == 0 { return (0, 0, EILSEQ); }
5499 (cp, 2, 0)
5500 }
5501 ENC_BIG5 => {
5502 let c = *src;
5503 if c < 128 { return (c as u32, 1, 0); }
5504 if src_left < 2 { return (0, 0, EINVAL); }
5505 let d = *src.add(1);
5506 if d < 0x40 || d == 0x7F || d > 0xFE { return (0, 0, EILSEQ); }
5507 let mut col = (d as usize) - 0x40;
5508 if col > 0x3E { col -= 0x22; }
5509 if c >= 0xA1 && c < 0xFA {
5510 let row = (c as usize) - 0xA1;
5511 if row >= 89 { return (0, 0, EILSEQ); }
5512 let cp = BIG5_TABLE[row * 157 + col] as u32;
5513 if cp == 0 { return (0, 0, EILSEQ); }
5514 return (cp, 2, 0);
5515 }
5516 (0, 0, EILSEQ)
5517 }
5518 ENC_EUCJP => {
5519 let c = *src;
5520 if c < 128 { return (c as u32, 1, 0); }
5521 if c == 0x8E {
5522 if src_left < 2 { return (0, 0, EINVAL); }
5523 let d = *src.add(1);
5524 if d < 0xA1 || d > 0xDF { return (0, 0, EILSEQ); }
5525 return ((d as u32) + 0xFF61 - 0xA1, 2, 0);
5526 }
5527 if c < 0xA1 { return (0, 0, EILSEQ); }
5528 if src_left < 2 { return (0, 0, EINVAL); }
5529 let d = *src.add(1);
5530 if d < 0xA1 || d > 0xFE { return (0, 0, EILSEQ); }
5531 let row = (c as usize) - 0xA1;
5532 let col = (d as usize) - 0xA1;
5533 if row >= 84 || col >= 94 { return (0, 0, EILSEQ); }
5534 let cp = JIS0208[row * 94 + col] as u32;
5535 if cp == 0 { return (0, 0, EILSEQ); }
5536 (cp, 2, 0)
5537 }
5538 ENC_SHIFTJIS => {
5539 let c = *src;
5540 if c < 128 { return (c as u32, 1, 0); }
5541 if c >= 0xA1 && c <= 0xDF { return ((c as u32) + 0xFF61 - 0xA1, 1, 0); }
5542 if src_left < 2 { return (0, 0, EINVAL); }
5543 let d = *src.add(1);
5544 if d < 0x40 || d == 0x7F || d > 0xFC { return (0, 0, EILSEQ); }
5545 let row = if c >= 129 && c <= 159 { (c as usize) - 129 }
5546 else if c >= 224 && c <= 239 { (c as usize) - 193 }
5547 else { return (0, 0, EILSEQ); };
5548 let (col, row_adj) = if d >= 64 && d <= 158 && d != 127 {
5549 let mut dd = d as usize;
5550 if dd > 127 { dd -= 1; }
5551 (dd - 64, row * 2)
5552 } else if d >= 159 && d <= 252 {
5553 ((d as usize) - 159, row * 2 + 1)
5554 } else {
5555 return (0, 0, EILSEQ);
5556 };
5557 if row_adj >= 84 { return (0, 0, EILSEQ); }
5558 let cp = JIS0208[row_adj * 94 + col] as u32;
5559 if cp == 0 { return (0, 0, EILSEQ); }
5560 (cp, 2, 0)
5561 }
5562 _ => (0, 0, EILSEQ),
5563 }
5564}
5565
5566unsafe fn iconv_encode(enc: i32, c: u32, dst: *mut u8, dst_left: usize) -> (usize, c_int) {
5567 match enc {
5568 ENC_UTF8 => {
5569 if c < 0x80 {
5570 if dst_left < 1 { return (0, E2BIG); }
5571 *dst = c as u8; return (1, 0);
5572 }
5573 if c < 0x800 {
5574 if dst_left < 2 { return (0, E2BIG); }
5575 *dst = (0xC0 | (c >> 6)) as u8;
5576 *dst.add(1) = (0x80 | (c & 0x3F)) as u8;
5577 return (2, 0);
5578 }
5579 if c < 0x10000 {
5580 if dst_left < 3 { return (0, E2BIG); }
5581 *dst = (0xE0 | (c >> 12)) as u8;
5582 *dst.add(1) = (0x80 | ((c >> 6) & 0x3F)) as u8;
5583 *dst.add(2) = (0x80 | (c & 0x3F)) as u8;
5584 return (3, 0);
5585 }
5586 if dst_left < 4 { return (0, E2BIG); }
5587 *dst = (0xF0 | (c >> 18)) as u8;
5588 *dst.add(1) = (0x80 | ((c >> 12) & 0x3F)) as u8;
5589 *dst.add(2) = (0x80 | ((c >> 6) & 0x3F)) as u8;
5590 *dst.add(3) = (0x80 | (c & 0x3F)) as u8;
5591 (4, 0)
5592 }
5593 ENC_UTF16LE => {
5594 if c < 0x10000 {
5595 if dst_left < 2 { return (0, E2BIG); }
5596 *dst = (c & 0xFF) as u8;
5597 *dst.add(1) = (c >> 8) as u8;
5598 return (2, 0);
5599 }
5600 if dst_left < 4 { return (0, E2BIG); }
5601 let c = c - 0x10000;
5602 let hi = ((c >> 10) + 0xD800) as u16;
5603 let lo = ((c & 0x3FF) + 0xDC00) as u16;
5604 *dst = (hi & 0xFF) as u8; *dst.add(1) = (hi >> 8) as u8;
5605 *dst.add(2) = (lo & 0xFF) as u8; *dst.add(3) = (lo >> 8) as u8;
5606 (4, 0)
5607 }
5608 ENC_UTF16BE => {
5609 if c < 0x10000 {
5610 if dst_left < 2 { return (0, E2BIG); }
5611 *dst = (c >> 8) as u8;
5612 *dst.add(1) = (c & 0xFF) as u8;
5613 return (2, 0);
5614 }
5615 if dst_left < 4 { return (0, E2BIG); }
5616 let c = c - 0x10000;
5617 let hi = ((c >> 10) + 0xD800) as u16;
5618 let lo = ((c & 0x3FF) + 0xDC00) as u16;
5619 *dst = (hi >> 8) as u8; *dst.add(1) = (hi & 0xFF) as u8;
5620 *dst.add(2) = (lo >> 8) as u8; *dst.add(3) = (lo & 0xFF) as u8;
5621 (4, 0)
5622 }
5623 ENC_UTF32LE => {
5624 if dst_left < 4 { return (0, E2BIG); }
5625 *dst = (c & 0xFF) as u8; *dst.add(1) = ((c >> 8) & 0xFF) as u8;
5626 *dst.add(2) = ((c >> 16) & 0xFF) as u8; *dst.add(3) = (c >> 24) as u8;
5627 (4, 0)
5628 }
5629 ENC_UTF32BE => {
5630 if dst_left < 4 { return (0, E2BIG); }
5631 *dst = (c >> 24) as u8; *dst.add(1) = ((c >> 16) & 0xFF) as u8;
5632 *dst.add(2) = ((c >> 8) & 0xFF) as u8; *dst.add(3) = (c & 0xFF) as u8;
5633 (4, 0)
5634 }
5635 ENC_WCHAR_T => {
5636 if dst_left < 4 { return (0, E2BIG); }
5637 *(dst as *mut u32) = c;
5638 (4, 0)
5639 }
5640 ENC_ASCII => {
5641 if c < 128 {
5642 if dst_left < 1 { return (0, E2BIG); }
5643 *dst = c as u8; return (1, 0);
5644 }
5645 (0, EILSEQ)
5646 }
5647 ENC_LATIN1 => {
5648 if c < 256 {
5649 if dst_left < 1 { return (0, E2BIG); }
5650 *dst = c as u8; return (1, 0);
5651 }
5652 (0, EILSEQ)
5653 }
5654 ENC_ISO8859_2 => {
5655 if let Some(b) = u_to_iso8859(&ISO8859_2_TO_U, c) {
5656 if dst_left < 1 { return (0, E2BIG); }
5657 *dst = b; return (1, 0);
5658 }
5659 (0, EILSEQ)
5660 }
5661 ENC_ISO8859_3 => {
5662 if let Some(b) = u_to_iso8859(&ISO8859_3_TO_U, c) {
5663 if dst_left < 1 { return (0, E2BIG); }
5664 *dst = b; return (1, 0);
5665 }
5666 (0, EILSEQ)
5667 }
5668 ENC_ISO8859_4 => {
5669 if let Some(b) = u_to_iso8859(&ISO8859_4_TO_U, c) {
5670 if dst_left < 1 { return (0, E2BIG); }
5671 *dst = b; return (1, 0);
5672 }
5673 (0, EILSEQ)
5674 }
5675 ENC_ISO8859_5 => {
5676 if let Some(b) = u_to_iso8859(&ISO8859_5_TO_U, c) {
5677 if dst_left < 1 { return (0, E2BIG); }
5678 *dst = b; return (1, 0);
5679 }
5680 (0, EILSEQ)
5681 }
5682 ENC_ISO8859_6 => {
5683 if let Some(b) = u_to_iso8859(&ISO8859_6_TO_U, c) {
5684 if dst_left < 1 { return (0, E2BIG); }
5685 *dst = b; return (1, 0);
5686 }
5687 (0, EILSEQ)
5688 }
5689 ENC_ISO8859_7 => {
5690 if let Some(b) = u_to_iso8859(&ISO8859_7_TO_U, c) {
5691 if dst_left < 1 { return (0, E2BIG); }
5692 *dst = b; return (1, 0);
5693 }
5694 (0, EILSEQ)
5695 }
5696 ENC_ISO8859_8 => {
5697 if let Some(b) = u_to_iso8859(&ISO8859_8_TO_U, c) {
5698 if dst_left < 1 { return (0, E2BIG); }
5699 *dst = b; return (1, 0);
5700 }
5701 (0, EILSEQ)
5702 }
5703 ENC_ISO8859_9 => {
5704 if let Some(b) = u_to_iso8859(&ISO8859_9_TO_U, c) {
5705 if dst_left < 1 { return (0, E2BIG); }
5706 *dst = b; return (1, 0);
5707 }
5708 (0, EILSEQ)
5709 }
5710 ENC_ISO8859_10 => {
5711 if let Some(b) = u_to_iso8859(&ISO8859_10_TO_U, c) {
5712 if dst_left < 1 { return (0, E2BIG); }
5713 *dst = b; return (1, 0);
5714 }
5715 (0, EILSEQ)
5716 }
5717 ENC_ISO8859_11 => {
5718 if let Some(b) = u_to_iso8859(&ISO8859_11_TO_U, c) {
5719 if dst_left < 1 { return (0, E2BIG); }
5720 *dst = b; return (1, 0);
5721 }
5722 (0, EILSEQ)
5723 }
5724 ENC_ISO8859_13 => {
5725 if let Some(b) = u_to_iso8859(&ISO8859_13_TO_U, c) {
5726 if dst_left < 1 { return (0, E2BIG); }
5727 *dst = b; return (1, 0);
5728 }
5729 (0, EILSEQ)
5730 }
5731 ENC_ISO8859_14 => {
5732 if let Some(b) = u_to_iso8859(&ISO8859_14_TO_U, c) {
5733 if dst_left < 1 { return (0, E2BIG); }
5734 *dst = b; return (1, 0);
5735 }
5736 (0, EILSEQ)
5737 }
5738 ENC_ISO8859_15 => {
5739 if let Some(b) = u_to_iso8859(&ISO8859_15_TO_U, c) {
5740 if dst_left < 1 { return (0, E2BIG); }
5741 *dst = b; return (1, 0);
5742 }
5743 (0, EILSEQ)
5744 }
5745 ENC_ISO8859_16 => {
5746 if let Some(b) = u_to_iso8859(&ISO8859_16_TO_U, c) {
5747 if dst_left < 1 { return (0, E2BIG); }
5748 *dst = b; return (1, 0);
5749 }
5750 (0, EILSEQ)
5751 }
5752 ENC_WIN1252 => {
5753 if c < 128 {
5754 if dst_left < 1 { return (0, E2BIG); }
5755 *dst = c as u8; return (1, 0);
5756 }
5757 if c >= 0xA0 && c <= 0xFF && WIN1252_TO_U[c as usize - 128] == c {
5758 if dst_left < 1 { return (0, E2BIG); }
5759 *dst = c as u8; return (1, 0);
5760 }
5761 for i in 0..128usize {
5762 if WIN1252_TO_U[i] == c {
5763 if dst_left < 1 { return (0, E2BIG); }
5764 *dst = (i + 128) as u8; return (1, 0);
5765 }
5766 }
5767 (0, EILSEQ)
5768 }
5769 ENC_WIN1251 => {
5770 if c < 128 {
5771 if dst_left < 1 { return (0, E2BIG); }
5772 *dst = c as u8; return (1, 0);
5773 }
5774 for i in 0..128usize {
5775 if WIN1251_TO_U[i] == c {
5776 if dst_left < 1 { return (0, E2BIG); }
5777 *dst = (i + 128) as u8; return (1, 0);
5778 }
5779 }
5780 (0, EILSEQ)
5781 }
5782 ENC_KOI8R => {
5783 if c < 128 {
5784 if dst_left < 1 { return (0, E2BIG); }
5785 *dst = c as u8; return (1, 0);
5786 }
5787 for i in 0..128usize {
5788 if KOI8R_TO_U[i] == c {
5789 if dst_left < 1 { return (0, E2BIG); }
5790 *dst = (i + 128) as u8; return (1, 0);
5791 }
5792 }
5793 (0, EILSEQ)
5794 }
5795 ENC_GBK | ENC_GB2312 => {
5796 if c < 128 {
5797 if dst_left < 1 { return (0, E2BIG); }
5798 *dst = c as u8; return (1, 0);
5799 }
5800 if c == 0x20AC {
5801 if dst_left < 1 { return (0, E2BIG); }
5802 *dst = 128; return (1, 0);
5803 }
5804 for row in 0..126usize {
5805 for col in 0..190usize {
5806 if GB18030_TABLE[row * 190 + col] as u32 == c {
5807 if dst_left < 2 { return (0, E2BIG); }
5808 *dst = (row + 0x81) as u8;
5809 *dst.add(1) = if col <= 62 { (col + 0x40) as u8 } else { (col + 0x41) as u8 };
5810 return (2, 0);
5811 }
5812 }
5813 }
5814 (0, EILSEQ)
5815 }
5816 ENC_BIG5 => {
5817 if c < 128 {
5818 if dst_left < 1 { return (0, E2BIG); }
5819 *dst = c as u8; return (1, 0);
5820 }
5821 for row in 0..89usize {
5822 for col in 0..157usize {
5823 if BIG5_TABLE[row * 157 + col] as u32 == c {
5824 if dst_left < 2 { return (0, E2BIG); }
5825 *dst = (row + 0xA1) as u8;
5826 *dst.add(1) = if col <= 0x3E { (col + 0x40) as u8 } else { (col + 0x62) as u8 };
5827 return (2, 0);
5828 }
5829 }
5830 }
5831 (0, EILSEQ)
5832 }
5833 ENC_EUCJP => {
5834 if c < 128 {
5835 if dst_left < 1 { return (0, E2BIG); }
5836 *dst = c as u8; return (1, 0);
5837 }
5838 if c >= 0xFF61 && c <= 0xFF9F {
5839 if dst_left < 2 { return (0, E2BIG); }
5840 *dst = 0x8E;
5841 *dst.add(1) = (c - 0xFF61 + 0xA1) as u8;
5842 return (2, 0);
5843 }
5844 let jis = uni_to_jis(c);
5845 if jis == 0 { return (0, EILSEQ); }
5846 if dst_left < 2 { return (0, E2BIG); }
5847 *dst = ((jis >> 8) as u8).wrapping_add(0x80);
5848 *dst.add(1) = ((jis & 0xFF) as u8).wrapping_add(0x80);
5849 (2, 0)
5850 }
5851 ENC_SHIFTJIS => {
5852 if c < 128 {
5853 if dst_left < 1 { return (0, E2BIG); }
5854 *dst = c as u8; return (1, 0);
5855 }
5856 if c >= 0xFF61 && c <= 0xFF9F {
5857 if dst_left < 1 { return (0, E2BIG); }
5858 *dst = (c - 0xFF61 + 0xA1) as u8;
5859 return (1, 0);
5860 }
5861 let jis = uni_to_jis(c);
5862 if jis == 0 { return (0, EILSEQ); }
5863 if dst_left < 2 { return (0, E2BIG); }
5864 let r = (jis >> 8) as usize;
5865 let d = (jis & 0xFF) as usize;
5866 *dst = ((r + 1) / 2 + if r < 95 { 112 } else { 176 }) as u8;
5867 *dst.add(1) = if r % 2 == 1 { (d + 31 + d / 96) as u8 } else { (d + 126) as u8 };
5868 (2, 0)
5869 }
5870 _ => (0, EILSEQ),
5871 }
5872}
5873
5874#[no_mangle]
5875pub unsafe extern "C" fn iconv_open(tocode: *const c_char, fromcode: *const c_char) -> IconvT {
5876 let to = find_encoding(tocode as *const u8);
5877 let from = find_encoding(fromcode as *const u8);
5878 if to < 0 || from < 0 {
5879 ERRNO = EINVAL;
5880 return !0usize as IconvT;
5881 }
5882 make_cd(from, to)
5883}
5884
5885#[no_mangle]
5886pub unsafe extern "C" fn iconv(
5887 cd: IconvT,
5888 inbuf: *mut *mut c_char,
5889 inbytesleft: *mut SizeT,
5890 outbuf: *mut *mut c_char,
5891 outbytesleft: *mut SizeT,
5892) -> SizeT {
5893 if cd == !0usize as IconvT {
5894 ERRNO = EINVAL;
5895 return !0usize;
5896 }
5897 if inbuf.is_null() || outbuf.is_null() { return 0; }
5898 let from = extract_from(cd);
5899 let to = extract_to(cd);
5900 let mut src = *inbuf as *const u8;
5901 let mut dst = *outbuf as *mut u8;
5902 let mut src_left = *inbytesleft;
5903 let mut dst_left = *outbytesleft;
5904 let mut subst = 0usize;
5905 while src_left > 0 {
5906 let (cp, consumed, err) = iconv_decode(from, src, src_left);
5907 if err != 0 {
5908 if err == EINVAL { break; }
5909 ERRNO = err;
5910 return !0usize;
5911 }
5912 let (written, err) = iconv_encode(to, cp, dst, dst_left);
5913 if err != 0 {
5914 if err == E2BIG {
5915 ERRNO = E2BIG;
5916 return !0usize;
5917 }
5918 if dst_left < 1 {
5919 ERRNO = E2BIG;
5920 return !0usize;
5921 }
5922 *dst = b'*';
5923 dst = dst.add(1);
5924 dst_left -= 1;
5925 subst += 1;
5926 } else {
5927 dst = dst.add(written);
5928 dst_left -= written;
5929 }
5930 src = src.add(consumed);
5931 src_left -= consumed;
5932 }
5933 *inbuf = src as *mut c_char;
5934 *outbuf = dst as *mut c_char;
5935 *inbytesleft = src_left;
5936 *outbytesleft = dst_left;
5937 subst
5938}
5939
5940#[no_mangle]
5941pub unsafe extern "C" fn iconv_close(_cd: IconvT) -> c_int { 0 }
5942
5943#[no_mangle]
5948pub unsafe extern "C" fn write(fd: c_int, buf: *const c_void, count: SizeT) -> SSizeT {
5949 sys_write(fd as i64, buf as *const u8, count) as SSizeT
5950}
5951
5952#[no_mangle]
5953pub unsafe extern "C" fn read(fd: c_int, buf: *mut c_void, count: SizeT) -> SSizeT {
5954 sys_read(fd as i64, buf as *mut u8, count) as SSizeT
5955}
5956
5957#[no_mangle]
5958pub unsafe extern "C" fn open(path: *const c_char, flags: c_int, mode: c_int) -> c_int {
5959 sys_open(path as *const u8, flags as i64, mode as i64) as c_int
5960}
5961
5962#[no_mangle]
5963pub unsafe extern "C" fn close(fd: c_int) -> c_int {
5964 sys_close(fd as i64);
5965 0
5966}
5967
5968#[no_mangle]
5969pub unsafe extern "C" fn lseek(fd: c_int, offset: i64, whence: c_int) -> i64 {
5970 sys_lseek(fd as i64, offset, whence as i64)
5971}
5972
5973const O_RDONLY: i32 = 0;
5978const O_WRONLY: i32 = 1;
5979const O_RDWR: i32 = 2;
5980const O_CREAT: i32 = 64;
5981const O_TRUNC: i32 = 512;
5982const O_APPEND: i32 = 1024;
5983const O_EXCL: i32 = 128;
5984const O_NONBLOCK: i32 = 2048;
5985const O_NOFOLLOW: i32 = if cfg!(target_arch = "aarch64") { 0o100000 } else { 0o400000 };
5986const O_DIRECTORY: i32 = if cfg!(target_arch = "aarch64") { 0o40000 } else { 0o200000 };
5987const O_CLOEXEC: i32 = 0x80000;
5988
5989const F_GETFD: i32 = 1;
5990const F_SETFD: i32 = 2;
5991const F_GETFL: i32 = 3;
5992const F_SETFL: i32 = 4;
5993const F_GETLK: i32 = 5;
5994const F_SETLK: i32 = 6;
5995const F_SETLKW: i32 = 7;
5996const F_DUPFD: i32 = 0;
5997const F_DUPFD_CLOEXEC: i32 = 1030;
5998const FD_CLOEXEC: i32 = 1;
5999
6000const TIOCGWINSZ: u32 = 0x5413;
6001
6002#[repr(C)]
6003struct winsize {
6004 ws_row: u16,
6005 ws_col: u16,
6006 ws_xpixel: u16,
6007 ws_ypixel: u16,
6008}
6009
6010#[inline]
6011unsafe fn sys_pipe2(fds: *mut c_int, flags: i32) -> i64 {
6012 <Arch as Syscalls>::syscall2(SYS_PIPE2, fds as i64, flags as i64)
6013}
6014
6015#[inline]
6016unsafe fn sys_dup3(oldfd: i32, newfd: i32, flags: i32) -> i64 {
6017 <Arch as Syscalls>::syscall3(SYS_DUP3, oldfd as i64, newfd as i64, flags as i64)
6018}
6019
6020#[inline]
6021unsafe fn sys_fcntl(fd: i32, cmd: i32, arg: i64) -> i64 {
6022 <Arch as Syscalls>::syscall3(SYS_FCNTL, fd as i64, cmd as i64, arg as i64)
6023}
6024
6025#[inline]
6026unsafe fn sys_ioctl(fd: c_int, request: u32, arg: *mut u8) -> i64 {
6027 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, request as i64, arg as i64)
6028}
6029
6030#[inline]
6031unsafe fn sys_unlinkat(dirfd: i32, path: *const u8, flags: i32) -> i64 {
6032 <Arch as Syscalls>::syscall3(SYS_UNLINKAT, dirfd as i64, path as i64, flags as i64)
6033}
6034
6035#[inline]
6036unsafe fn sys_renameat2(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: u32) -> i64 {
6037 <Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
6038}
6039
6040const UNGET: usize = 8;
6045const F_PERM: u32 = 1;
6046const F_NORD: u32 = 4;
6047const F_NOWR: u32 = 8;
6048const F_EOF: u32 = 16;
6049const F_ERR: u32 = 32;
6050const F_SVB: u32 = 64;
6051const F_APP: u32 = 128;
6052
6053const BUFSIZ: usize = 1024;
6054
6055const _IOFBF: c_int = 0;
6056const _IOLBF: c_int = 1;
6057const _IONBF: c_int = 2;
6058
6059const SEEK_SET: c_int = 0;
6060const SEEK_CUR: c_int = 1;
6061const SEEK_END: c_int = 2;
6062
6063#[repr(C)]
6065pub struct FILE {
6066 flags: c_uint,
6067 rpos: *mut u8,
6068 rend: *mut u8,
6069 close: Option<unsafe extern "C" fn(*mut FILE) -> c_int>,
6070 wend: *mut u8,
6071 wpos: *mut u8,
6072 mustbezero_1: *mut u8,
6073 wbase: *mut u8,
6074 read_fn: Option<unsafe extern "C" fn(*mut FILE, *mut u8, usize) -> usize>,
6075 write_fn: Option<unsafe extern "C" fn(*mut FILE, *const u8, usize) -> usize>,
6076 seek_fn: Option<unsafe extern "C" fn(*mut FILE, i64, c_int) -> i64>,
6077 buf: *mut u8,
6078 buf_size: usize,
6079 prev: *mut FILE,
6080 next: *mut FILE,
6081 fd: c_int,
6082 pipe_pid: c_int,
6083 lockcount: c_long,
6084 mode: c_int,
6085 lock: c_int,
6086 lbf: c_int,
6087 cookie: *mut c_void,
6088 off: i64,
6089 getln_buf: *mut c_char,
6090 mustbezero_2: *mut c_void,
6091 shend: *mut u8,
6092 shlim: i64,
6093 shcnt: i64,
6094 ungotten: [c_int; UNGET],
6095 ungotten_count: c_int,
6096 _eof: c_int,
6097 _err: c_int,
6098}
6099
6100static mut STDIN_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6101static mut STDOUT_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6102static mut STDERR_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6103
6104static mut STDIN_FILE: FILE = FILE {
6105 flags: 0, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6106 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6107 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6108 read_fn: None, write_fn: None, seek_fn: None,
6109 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6110 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6111 fd: 0, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6112 cookie: core::ptr::null_mut(), off: 0,
6113 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6114 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6115 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6116};
6117static mut STDOUT_FILE: FILE = FILE {
6118 flags: F_NOWR as u32 + F_SVB as u32, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6119 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6120 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6121 read_fn: None, write_fn: None, seek_fn: None,
6122 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6123 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6124 fd: 1, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6125 cookie: core::ptr::null_mut(), off: 0,
6126 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6127 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6128 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6129};
6130static mut STDERR_FILE: FILE = FILE {
6131 flags: F_NOWR as u32, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6132 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6133 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6134 read_fn: None, write_fn: None, seek_fn: None,
6135 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6136 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6137 fd: 2, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6138 cookie: core::ptr::null_mut(), off: 0,
6139 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6140 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6141 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6142};
6143
6144#[no_mangle]
6145pub static mut stdin: *mut FILE = &raw mut STDIN_FILE as *mut FILE;
6146#[no_mangle]
6147pub static mut stdout: *mut FILE = &raw mut STDOUT_FILE as *mut FILE;
6148#[no_mangle]
6149pub static mut stderr: *mut FILE = &raw mut STDERR_FILE as *mut FILE;
6150
6151unsafe fn __stdio_init() {
6156 STDIN_FILE.buf = core::ptr::addr_of_mut!(STDIN_BUF) as *mut u8;
6157 STDIN_FILE.buf_size = BUFSIZ;
6158 STDIN_FILE.read_fn = Some(__stdio_read);
6159 STDIN_FILE.write_fn = Some(__stdio_write);
6160 STDIN_FILE.seek_fn = Some(__stdio_seek);
6161 STDOUT_FILE.buf = core::ptr::addr_of_mut!(STDOUT_BUF) as *mut u8;
6162 STDOUT_FILE.buf_size = BUFSIZ;
6163 STDOUT_FILE.lbf = b'\n' as c_int;
6164 STDOUT_FILE.read_fn = Some(__stdio_read);
6165 STDOUT_FILE.write_fn = Some(__stdio_write);
6166 STDOUT_FILE.seek_fn = Some(__stdio_seek);
6167 STDERR_FILE.buf = core::ptr::addr_of_mut!(STDERR_BUF) as *mut u8;
6168 STDERR_FILE.buf_size = BUFSIZ;
6169 STDERR_FILE.read_fn = Some(__stdio_read);
6170 STDERR_FILE.write_fn = Some(__stdio_write);
6171 STDERR_FILE.seek_fn = Some(__stdio_seek);
6172}
6173
6174unsafe fn buf_ptr(f: *mut FILE) -> *mut u8 {
6175 (f as *mut u8).add(core::mem::size_of::<FILE>())
6176}
6177
6178unsafe extern "C" fn __stdio_read(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
6179 let n = sys_read((*f).fd as i64, buf, len);
6180 if n <= 0 {
6181 if n == 0 { (*f).flags |= F_EOF; } else { (*f).flags |= F_ERR; (*f)._err = 1; }
6182 return 0;
6183 }
6184 n as usize
6185}
6186
6187unsafe extern "C" fn __stdio_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
6188 let l = (*f).wpos as usize - (*f).wbase as usize;
6189 let mut iov = [
6190 ((*f).wbase as *const u8, l),
6191 (buf, len),
6192 ];
6193 if iov[0].1 == 0 { iov = [iov[1], (core::ptr::null(), 0)]; }
6194 if (*f).flags & F_APP != 0 {
6195 let _ = sys_lseek((*f).fd as i64, 0, SEEK_END as i64);
6196 }
6197 let mut rem = iov[0].1 + iov[1].1;
6198 let mut idx = 0usize;
6199 while rem > 0 {
6200 let ptr = iov[idx].0;
6201 let cnt = iov[idx].1;
6202 if cnt == 0 { idx += 1; continue; }
6203 let n = sys_write((*f).fd as i64, ptr, cnt);
6204 if n <= 0 {
6205 (*f).wpos = core::ptr::null_mut();
6206 (*f).wbase = core::ptr::null_mut();
6207 (*f).wend = core::ptr::null_mut();
6208 (*f).flags |= F_ERR;
6209 return if iov[idx].0 == buf { 0 } else { len };
6210 }
6211 rem -= n as usize;
6212 iov[idx].0 = iov[idx].0.add(n as usize);
6213 iov[idx].1 -= n as usize;
6214 if iov[idx].1 == 0 { idx += 1; }
6215 }
6216 (*f).wend = (*f).buf.add((*f).buf_size);
6217 (*f).wbase = (*f).buf;
6218 (*f).wpos = (*f).buf;
6219 len
6220}
6221
6222unsafe extern "C" fn __stdio_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
6223 sys_lseek((*f).fd as i64, off, whence as i64)
6224}
6225
6226unsafe fn init_file(
6227 f: *mut FILE,
6228 fd: c_int,
6229 mode: *const c_char,
6230 close_fn: Option<unsafe extern "C" fn(*mut FILE) -> c_int>,
6231 buf_area: *mut u8,
6232 buf_sz: usize,
6233) {
6234 core::ptr::write_bytes(f as *mut u8, 0, core::mem::size_of::<FILE>());
6235 (*f).fd = fd;
6236 (*f).close = close_fn;
6237 (*f).lock = 0;
6238 (*f).lbf = -1;
6239 (*f).buf = buf_area;
6240 (*f).buf_size = buf_sz;
6241 (*f).read_fn = Some(__stdio_read);
6242 (*f).write_fn = Some(__stdio_write);
6243 (*f).seek_fn = Some(__stdio_seek);
6244 let m = *mode;
6245 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
6246 if m == b'r' as c_char && !has_plus {
6247 (*f).flags = F_NORD;
6248 } else if !has_plus {
6249 (*f).flags = F_NOWR;
6250 }
6251}
6252
6253unsafe extern "C" fn __stdio_close(f: *mut FILE) -> c_int {
6254 sys_close((*f).fd as i64);
6255 0
6256}
6257
6258unsafe fn fmodeflags(mode: *const c_char) -> c_int {
6259 let mut flags: c_int;
6260 let m = *mode;
6261 if !strchr(mode as *const u8, b'+' as c_int).is_null() {
6262 flags = O_RDWR;
6263 } else if m == b'r' as c_char {
6264 flags = O_RDONLY;
6265 } else {
6266 flags = O_WRONLY;
6267 }
6268 if !strchr(mode as *const u8, b'x' as c_int).is_null() { flags |= O_EXCL; }
6269 if !strchr(mode as *const u8, b'e' as c_int).is_null() { flags |= O_CLOEXEC; }
6270 if m != b'r' as c_char { flags |= O_CREAT; }
6271 if m == b'w' as c_char { flags |= O_TRUNC; }
6272 if m == b'a' as c_char { flags |= O_APPEND; }
6273 flags
6274}
6275
6276const O_ACCMODE: c_int = O_RDONLY | O_WRONLY | O_RDWR;
6277
6278unsafe fn flush_buf(f: *mut FILE) -> c_int {
6279 if (*f).wpos == (*f).wbase {
6280 if !(*f).wpos.is_null() {
6281 (*f).wend = (*f).buf.add((*f).buf_size);
6282 (*f).wpos = (*f).wbase;
6283 }
6284 return 0;
6285 }
6286 if let Some(wfunc) = (*f).write_fn {
6287 let ret = wfunc(f, core::ptr::null(), 0);
6288 if ret == 0 && (*f).wpos.is_null() { return -1; }
6289 return 0;
6290 }
6291 (*f).flags |= F_ERR;
6292 -1
6293}
6294
6295#[no_mangle]
6300pub unsafe extern "C" fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE {
6301 if filename.is_null() || mode.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
6302 let m = *mode;
6303 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
6304 ERRNO = EINVAL; return core::ptr::null_mut();
6305 }
6306 let flags = fmodeflags(mode);
6307 let fd = sys_open(filename as *const u8, flags as i64, 0o666);
6308 if fd < 0 { ERRNO = (-fd) as c_int; return core::ptr::null_mut(); }
6309 fdopen(fd as c_int, mode)
6310}
6311
6312#[no_mangle]
6313pub unsafe extern "C" fn fdopen(fd: c_int, mode: *const c_char) -> *mut FILE {
6314 if fd < 0 || mode.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
6315 let m = *mode;
6316 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
6317 ERRNO = EINVAL; return core::ptr::null_mut();
6318 }
6319 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
6320 if f.is_null() { ERRNO = ENOMEM; return core::ptr::null_mut(); }
6321 let buf = buf_ptr(f);
6322 init_file(f, fd, mode, Some(__stdio_close), buf, BUFSIZ);
6323 if !strchr(mode as *const u8, b'a' as c_int).is_null() { (*f).flags |= F_APP; }
6324 if !strchr(mode as *const u8, b'e' as c_int).is_null() { sys_fcntl(fd, F_SETFD, FD_CLOEXEC as i64); }
6325 if (*f).flags & F_NOWR == 0 {
6326 let mut ws: winsize = core::mem::zeroed();
6327 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 {
6328 (*f).lbf = b'\n' as c_int;
6329 }
6330 }
6331 f
6332}
6333
6334#[no_mangle]
6335pub unsafe extern "C" fn freopen(
6336 filename: *const c_char, mode: *const c_char, f: *mut FILE,
6337) -> *mut FILE {
6338 fflush(f);
6339 if (*f).pipe_pid > 0 { let _ = __stdio_close(f); }
6340 if filename.is_null() {
6341 let flags = fmodeflags(mode);
6342 if flags == 0 { return core::ptr::null_mut(); }
6343 let mut fl = flags & !(O_CREAT | O_EXCL | O_CLOEXEC);
6344 if (*f).flags & F_APP != 0 { fl = (fl & !O_ACCMODE) | O_WRONLY | O_APPEND; }
6345 if sys_fcntl((*f).fd, F_SETFL, fl as i64) < 0 { return core::ptr::null_mut(); }
6346 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
6347 if has_plus {
6348 (*f).flags &= !(F_NORD | F_NOWR);
6349 } else if *mode == b'r' as c_char {
6350 (*f).flags = ((*f).flags & !F_NOWR) | F_NORD;
6351 } else {
6352 (*f).flags = ((*f).flags & !F_NORD) | F_NOWR;
6353 }
6354 return f;
6355 }
6356 let new_f = fopen(filename, mode);
6357 if new_f.is_null() { let _ = __stdio_close(f); return core::ptr::null_mut(); }
6358 if (*new_f).fd == (*f).fd {
6359 (*new_f).fd = -1;
6360 } else {
6361 sys_dup3((*new_f).fd, (*f).fd, 0);
6362 let _ = __stdio_close(new_f);
6363 }
6364 (*f).flags = (*new_f).flags;
6365 (*f).rpos = core::ptr::null_mut();
6366 (*f).rend = core::ptr::null_mut();
6367 (*f).wpos = core::ptr::null_mut();
6368 (*f).wbase = core::ptr::null_mut();
6369 (*f).wend = core::ptr::null_mut();
6370 (*f).lbf = (*new_f).lbf;
6371 (*f).pipe_pid = 0;
6372 free(new_f as *mut c_void);
6373 f
6374}
6375
6376#[no_mangle]
6377pub unsafe extern "C" fn fclose(f: *mut FILE) -> c_int {
6378 if f.is_null() { return -1; }
6379 let r = fflush(f);
6380 if let Some(close_fn) = (*f).close { let _ = close_fn(f); }
6381 if r != 0 { -1 } else { 0 }
6382}
6383
6384#[no_mangle]
6389pub unsafe extern "C" fn setvbuf(f: *mut FILE, buf: *mut c_char, mode: c_int, size: usize) -> c_int {
6390 if mode != _IOFBF && mode != _IOLBF && mode != _IONBF { return -1; }
6391 fflush(f);
6392 (*f).rpos = core::ptr::null_mut();
6393 (*f).rend = core::ptr::null_mut();
6394 (*f).wpos = core::ptr::null_mut();
6395 (*f).wbase = core::ptr::null_mut();
6396 (*f).wend = core::ptr::null_mut();
6397 if mode == _IONBF {
6398 (*f).buf_size = 0;
6399 } else if !buf.is_null() && size > 0 {
6400 (*f).buf = buf as *mut u8;
6401 (*f).buf_size = size;
6402 }
6403 (*f).lbf = if mode == _IOLBF { b'\n' as c_int } else { -1 };
6404 0
6405}
6406
6407#[no_mangle]
6408pub unsafe extern "C" fn setbuf(f: *mut FILE, buf: *mut c_char) {
6409 if buf.is_null() { setvbuf(f, core::ptr::null_mut(), _IONBF, 0); }
6410 else { setvbuf(f, buf, _IOFBF, BUFSIZ); }
6411}
6412
6413#[no_mangle]
6414pub unsafe extern "C" fn setbuffer(f: *mut FILE, buf: *mut c_char, size: usize) {
6415 if buf.is_null() { setvbuf(f, core::ptr::null_mut(), _IONBF, 0); }
6416 else { setvbuf(f, buf, _IOFBF, size); }
6417}
6418
6419#[no_mangle]
6420pub unsafe extern "C" fn fflush(f: *mut FILE) -> c_int {
6421 if f.is_null() {
6422 let mut r = 0;
6423 if !stdout.is_null() && !(*stdout).wpos.is_null() && (*stdout).wpos != (*stdout).wbase {
6424 if flush_buf(stdout) != 0 { r = -1; }
6425 }
6426 if !stderr.is_null() && !(*stderr).wpos.is_null() && (*stderr).wpos != (*stderr).wbase {
6427 if flush_buf(stderr) != 0 { r = -1; }
6428 }
6429 return r;
6430 }
6431 if !(*f).wpos.is_null() && (*f).wpos != (*f).wbase {
6432 return flush_buf(f);
6433 }
6434 0
6435}
6436
6437#[no_mangle]
6442pub unsafe extern "C" fn fwide(_f: *mut FILE, mode: c_int) -> c_int { mode }
6443
6444#[no_mangle]
6445pub unsafe extern "C" fn feof(f: *mut FILE) -> c_int { if (*f)._eof != 0 { 1 } else { 0 } }
6446
6447#[no_mangle]
6448pub unsafe extern "C" fn ferror(f: *mut FILE) -> c_int { if (*f)._err != 0 { 1 } else { 0 } }
6449
6450#[no_mangle]
6451pub unsafe extern "C" fn clearerr(f: *mut FILE) { (*f)._eof = 0; (*f)._err = 0; }
6452
6453#[no_mangle]
6454pub unsafe extern "C" fn fileno(f: *mut FILE) -> c_int { (*f).fd }
6455
6456#[no_mangle]
6461pub unsafe extern "C" fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int {
6462 fseeko(stream, offset as i64, whence)
6463}
6464
6465#[no_mangle]
6466pub unsafe extern "C" fn ftell(stream: *mut FILE) -> c_long {
6467 ftello(stream) as c_long
6468}
6469
6470#[no_mangle]
6471pub unsafe extern "C" fn rewind(stream: *mut FILE) {
6472 fseek(stream, 0, SEEK_SET);
6473 (*stream)._eof = 0;
6474 (*stream)._err = 0;
6475}
6476
6477#[no_mangle]
6478pub unsafe extern "C" fn fseeko(stream: *mut FILE, offset: i64, whence: c_int) -> c_int {
6479 if whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END {
6480 ERRNO = EINVAL;
6481 return -1;
6482 }
6483 let f = &mut *stream;
6484 let mut adj_offset = offset;
6485 if whence == SEEK_CUR {
6486 if !f.rpos.is_null() {
6487 adj_offset -= f.rend as i64 - f.rpos as i64;
6488 }
6489 adj_offset -= f.ungotten_count as i64;
6490 }
6491 if !f.wpos.is_null() && f.wpos != f.wbase {
6492 if flush_buf(stream) != 0 { return -1; }
6493 }
6494 f.wpos = core::ptr::null_mut();
6495 f.wbase = core::ptr::null_mut();
6496 f.wend = core::ptr::null_mut();
6497 if let Some(sfunc) = f.seek_fn {
6498 let r = sfunc(stream, adj_offset, whence);
6499 if r < 0 { return -1; }
6500 } else {
6501 ERRNO = EINVAL;
6502 return -1;
6503 }
6504 f.rpos = core::ptr::null_mut();
6505 f.rend = core::ptr::null_mut();
6506 f._eof = 0;
6507 f.ungotten_count = 0;
6508 0
6509}
6510
6511#[no_mangle]
6512pub unsafe extern "C" fn ftello(stream: *mut FILE) -> i64 {
6513 let f = &mut *stream;
6514 if f.flags & F_APP != 0 && !f.wpos.is_null() && f.wpos != f.wbase {
6515 if fflush(stream) != 0 { return -1; }
6516 }
6517 let sfunc = match f.seek_fn { Some(s) => s, None => return -1 };
6518 let pos = sfunc(stream, 0,
6519 if (f.flags & F_APP) != 0 && !f.wpos.is_null() && f.wpos != f.wbase { SEEK_END } else { SEEK_CUR });
6520 if pos < 0 { return -1; }
6521 let mut pos = pos;
6522 if !f.rpos.is_null() {
6523 pos += f.rpos as i64 - f.rend as i64;
6524 } else if !f.wbase.is_null() {
6525 pos += f.wpos as i64 - f.wbase as i64;
6526 }
6527 pos - f.ungotten_count as i64
6528}
6529
6530#[no_mangle]
6531pub unsafe extern "C" fn fgetpos(stream: *mut FILE, pos: *mut i64) -> c_int {
6532 let off = ftello(stream);
6533 if off < 0 { return -1; }
6534 *pos = off;
6535 0
6536}
6537
6538#[no_mangle]
6539pub unsafe extern "C" fn fsetpos(stream: *mut FILE, pos: *const i64) -> c_int {
6540 fseeko(stream, *pos, SEEK_SET)
6541}
6542
6543#[no_mangle]
6548pub unsafe extern "C" fn fgetc(stream: *mut FILE) -> c_int {
6549 let f = &mut *stream;
6550 if f.ungotten_count > 0 {
6551 f.ungotten_count -= 1;
6552 return f.ungotten[f.ungotten_count as usize];
6553 }
6554 if !f.rpos.is_null() && f.rpos < f.rend {
6555 let c = *f.rpos;
6556 f.rpos = f.rpos.add(1);
6557 return c as c_int;
6558 }
6559 if f._eof != 0 { return -1; }
6560 if let Some(rfunc) = f.read_fn {
6561 let mut buf = [0u8; 1];
6562 let n = rfunc(stream, buf.as_mut_ptr(), 1);
6563 if n == 0 {
6564 if f.flags & F_ERR != 0 { f._err = 1; } else { f._eof = 1; }
6565 return -1;
6566 }
6567 buf[0] as c_int
6568 } else {
6569 f._eof = 1;
6570 -1
6571 }
6572}
6573
6574#[no_mangle]
6575pub unsafe extern "C" fn getc(stream: *mut FILE) -> c_int { fgetc(stream) }
6576
6577#[no_mangle]
6578pub unsafe extern "C" fn getchar() -> c_int { fgetc(stdin) }
6579
6580#[no_mangle]
6581pub unsafe extern "C" fn ungetc(c: c_int, stream: *mut FILE) -> c_int {
6582 if c == -1 { return -1; }
6583 let f = &mut *stream;
6584 if f.ungotten_count >= UNGET as c_int { return -1; }
6585 f.ungotten[f.ungotten_count as usize] = c;
6586 f.ungotten_count += 1;
6587 f._eof = 0;
6588 c
6589}
6590
6591#[no_mangle]
6596pub unsafe extern "C" fn fgets(s: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char {
6597 if n <= 0 { return null_mut(); }
6598 let max = (n - 1) as usize;
6599 let mut i = 0usize;
6600 while i < max {
6601 let c = fgetc(stream);
6602 if c == -1 { if i == 0 { return null_mut(); } break; }
6603 *s.add(i) = c as c_char;
6604 i += 1;
6605 if c == b'\n' as c_int { break; }
6606 }
6607 *s.add(i) = 0;
6608 s
6609}
6610
6611#[no_mangle]
6613pub unsafe extern "C" fn gets(s: *mut c_char) -> *mut c_char {
6614 let mut i = 0usize;
6615 loop {
6616 let c = fgetc(stdin);
6617 if c == -1 { if i == 0 { return null_mut(); } break; }
6618 if c == b'\n' as c_int { break; }
6619 *s.add(i) = c as c_char;
6620 i += 1;
6621 }
6622 *s.add(i) = 0;
6623 s
6624}
6625
6626#[no_mangle]
6627pub unsafe extern "C" fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut FILE {
6628 fopen(filename, mode)
6629}
6630
6631const PERROR_BUF_SIZE: usize = 64;
6633static mut PERROR_BUF: [u8; PERROR_BUF_SIZE] = [0; PERROR_BUF_SIZE];
6634
6635#[no_mangle]
6636pub unsafe extern "C" fn perror(msg: *const c_char) {
6637 let fd = (*stderr).fd;
6638 if !msg.is_null() && *msg != 0 {
6639 let len = strlen(msg as *const c_char);
6640 write_str(fd, msg as *const u8, len);
6641 write_str(fd, b": ".as_ptr(), 2);
6642 }
6643 let e = ERRNO;
6644 let text = strerror(e) as *const u8;
6645 write_str(fd, text, strlen(text as *const c_char));
6646 write_str(fd, b"\n".as_ptr(), 1);
6647}
6648
6649#[no_mangle]
6650pub unsafe extern "C" fn fread(
6651 ptr: *mut c_void, size: SizeT, nmemb: SizeT, stream: *mut FILE,
6652) -> SizeT {
6653 if size == 0 || nmemb == 0 { return 0; }
6654 let total = size * nmemb;
6655 let mut rd = 0usize;
6656 while rd < total {
6657 let c = fgetc(stream);
6658 if c == -1 { break; }
6659 *(ptr as *mut u8).add(rd) = c as u8;
6660 rd += 1;
6661 }
6662 rd / size
6663}
6664
6665unsafe fn write_str(fd: c_int, s: *const u8, len: usize) {
6670 let mut written = 0usize;
6671 while written < len {
6672 let n = sys_write(fd as i64, s.add(written), len - written);
6673 if n <= 0 { break; }
6674 written += n as usize;
6675 }
6676}
6677
6678#[no_mangle]
6679unsafe fn __overflow(f: *mut FILE, c: c_int) -> c_int {
6680 if (*f).wpos.is_null() {
6681 (*f).wbase = (*f).buf;
6682 (*f).wpos = (*f).buf;
6683 (*f).wend = (*f).buf.add((*f).buf_size);
6684 }
6685 if flush_buf(f) == -1 { return -1; }
6686 if (*f).wpos >= (*f).wend {
6687 if let Some(wfunc) = (*f).write_fn {
6688 let byte = c as u8;
6689 let ret = wfunc(f, &byte as *const u8, 1);
6690 if ret == 0 { return -1; }
6691 }
6692 return c;
6693 }
6694 *(*f).wpos = c as u8;
6695 (*f).wpos = (*f).wpos.add(1);
6696 if c == (*f).lbf || (*f).wpos >= (*f).wend { let _ = flush_buf(f); }
6697 c
6698}
6699
6700#[no_mangle]
6701pub unsafe extern "C" fn puts(s: *const c_char) -> c_int {
6702 let len = strlen(s as *const c_char);
6703 let _ = fwrite(s as *const c_void, 1, len, stdout);
6704 let _ = fwrite(b"\n".as_ptr() as *const c_void, 1, 1, stdout);
6705 let f = &mut *stdout;
6706 if f.lbf >= 0 { let _ = flush_buf(stdout); }
6707 (len + 1) as c_int
6708}
6709
6710#[no_mangle]
6711pub unsafe extern "C" fn fputs(s: *const c_char, stream: *mut FILE) -> c_int {
6712 let len = strlen(s as *const c_char);
6713 fwrite(s as *const c_void, 1, len, stream) as c_int
6714}
6715
6716#[no_mangle]
6717pub unsafe extern "C" fn fputc(c: c_int, stream: *mut FILE) -> c_int {
6718 let f = &mut *stream;
6719 if f.wpos.is_null() || f.wpos >= f.wend {
6720 if __overflow(f, c) == -1 { return -1; }
6721 return c;
6722 }
6723 *f.wpos = c as u8;
6724 f.wpos = f.wpos.add(1);
6725 if c == f.lbf || f.wpos >= f.wend { let _ = flush_buf(f); }
6726 c
6727}
6728
6729#[no_mangle]
6730pub unsafe extern "C" fn putc(c: c_int, stream: *mut FILE) -> c_int { fputc(c, stream) }
6731
6732#[no_mangle]
6733pub unsafe extern "C" fn putchar(c: c_int) -> c_int { fputc(c, stdout) }
6734
6735#[no_mangle]
6736pub unsafe extern "C" fn fwrite(
6737 ptr: *const c_void, size: SizeT, nmemb: SizeT, stream: *mut FILE,
6738) -> SizeT {
6739 if size == 0 || nmemb == 0 { return 0; }
6740 let total = size * nmemb;
6741 let f = &mut *stream;
6742 if f.buf_size == 0 {
6743 if let Some(wfunc) = f.write_fn {
6744 let ret = wfunc(stream, ptr as *const u8, total);
6745 return ret / size;
6746 }
6747 return 0;
6748 }
6749 if f.wpos.is_null() {
6750 f.wbase = f.buf;
6751 f.wpos = f.buf;
6752 f.wend = f.buf.add(f.buf_size);
6753 }
6754 let mut remaining = total;
6755 let mut src = ptr as *const u8;
6756 while remaining > 0 {
6757 let space = f.wend as usize - f.wpos as usize;
6758 if space == 0 {
6759 if flush_buf(f as *mut FILE) == -1 { break; }
6760 continue;
6761 }
6762 let n = if remaining < space { remaining } else { space };
6763 core::ptr::copy_nonoverlapping(src, f.wpos, n);
6764 f.wpos = f.wpos.add(n);
6765 src = src.add(n);
6766 remaining -= n;
6767 if f.wpos >= f.wend { let _ = flush_buf(f as *mut FILE); }
6768 }
6769 if f.lbf >= 0 { let _ = flush_buf(f as *mut FILE); }
6770 (total - remaining) / size
6771}
6772
6773unsafe fn wide_to_mb(dst: *mut u8, cap: usize, src: *const wchar_t) -> usize {
6778 let mut o = 0usize;
6779 let mut i = 0usize;
6780 let mut st: c_uint = 0;
6781 while *src.add(i) != 0 {
6782 let mut tmp = [0u8; 8];
6783 let n = wcrtomb(tmp.as_mut_ptr() as *mut c_char, *src.add(i), &mut st);
6784 if n == !0usize || n == 0 { break; }
6785 if o + n > cap { break; }
6786 core::ptr::copy_nonoverlapping(tmp.as_ptr(), dst.add(o), n);
6787 o += n;
6788 i += 1;
6789 }
6790 o
6791}
6792
6793macro_rules! impl_format {
6794 ($fmt:expr, $args:expr, $write_char:expr, $write_str:expr) => {{
6795 let fmt = $fmt;
6796 let args = &mut $args;
6797 let mut count: usize = 0;
6798 let mut i = 0usize;
6799 loop {
6800 let c = *fmt.add(i) as u8;
6801 if c == 0 { break; }
6802 if c != b'%' {
6803 ($write_char)(c);
6804 count += 1; i += 1; continue;
6805 }
6806 i += 1;
6807 let mut flags: u8 = 0;
6809 loop {
6810 let fc = *fmt.add(i) as u8;
6811 match fc {
6812 b'-' => { flags |= FLAG_MINUS; i += 1; }
6813 b'+' => { flags |= FLAG_PLUS; i += 1; }
6814 b' ' => { flags |= FLAG_SPACE; i += 1; }
6815 b'0' => { flags |= FLAG_ZERO; i += 1; }
6816 b'#' => { flags |= FLAG_HASH; i += 1; }
6817 _ => break,
6818 }
6819 }
6820 let mut width: usize = 0;
6822 if *fmt.add(i) as u8 == b'*' {
6823 width = args.next_arg::<c_int>() as usize; i += 1;
6824 } else {
6825 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
6826 width = width * 10 + ((*fmt.add(i) as u8) - b'0') as usize; i += 1;
6827 }
6828 }
6829 let mut precision: i32 = -1;
6831 if *fmt.add(i) as u8 == b'.' {
6832 i += 1;
6833 if *fmt.add(i) as u8 == b'*' {
6834 precision = args.next_arg::<c_int>(); i += 1;
6835 } else {
6836 precision = 0;
6837 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
6838 precision = precision * 10 + ((*fmt.add(i) as u8) - b'0') as i32; i += 1;
6839 }
6840 }
6841 }
6842 let len_mod = *fmt.add(i) as u8;
6844 let spec: u8;
6845 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' {
6846 i += 1;
6847 let len_mod2 = *fmt.add(i) as u8;
6848 if (len_mod == b'h' && len_mod2 == b'h') || (len_mod == b'l' && len_mod2 == b'l') {
6849 i += 1;
6850 spec = *fmt.add(i) as u8;
6851 match (len_mod, len_mod2, spec) {
6853 (b'h', b'h', b'n') => {
6854 let p = args.next_arg::<*mut c_void>();
6855 if !p.is_null() { *(p as *mut u8) = count as u8; }
6856 }
6857 (b'l', b'l', b'n') => {
6858 let p = args.next_arg::<*mut c_void>();
6859 if !p.is_null() { *(p as *mut c_longlong) = count as c_longlong; }
6860 }
6861 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
6862 let val = args.next_arg::<c_longlong>();
6863 let neg = val < 0;
6864 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
6865 let b = format_u64(abs);
6866 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
6867 let mut fbuf = [0u8; 32];
6868 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
6869 ($write_str)(fbuf.as_ptr(), len); count += len;
6870 }
6871 (b'l', b'l', b'u') => {
6872 let val = args.next_arg::<c_ulonglong>();
6873 let b = format_u64(val as u64);
6874 let mut fbuf = [0u8; 32];
6875 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
6876 ($write_str)(fbuf.as_ptr(), len); count += len;
6877 }
6878 (b'l', b'l', b'o') => {
6879 let val = args.next_arg::<c_ulonglong>();
6880 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
6881 let mut fbuf = [0u8; 32];
6882 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
6883 ($write_str)(fbuf.as_ptr(), len); count += len;
6884 }
6885 (b'l', b'l', b'x') => {
6886 let val = args.next_arg::<c_ulonglong>();
6887 let b = format_hex(val as u64, false);
6888 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
6889 let mut fbuf = [0u8; 32];
6890 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6891 ($write_str)(fbuf.as_ptr(), len); count += len;
6892 }
6893 (b'l', b'l', b'X') => {
6894 let val = args.next_arg::<c_ulonglong>();
6895 let b = format_hex(val as u64, true);
6896 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
6897 let mut fbuf = [0u8; 32];
6898 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6899 ($write_str)(fbuf.as_ptr(), len); count += len;
6900 }
6901 _ => { ($write_char)(b'%'); ($write_char)(len_mod); ($write_char)(len_mod2); ($write_char)(spec); count += 4; }
6902 }
6903 } else {
6904 spec = len_mod2;
6905 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
6908 match (lm, spec) {
6909 (b'h', b'n') => {
6910 let p = args.next_arg::<*mut c_void>();
6911 if !p.is_null() { *(p as *mut u16) = count as u16; }
6912 }
6913 (b'l', b'n') => {
6914 let p = args.next_arg::<*mut c_void>();
6915 if !p.is_null() { *(p as *mut c_long) = count as c_long; }
6916 }
6917 (b'z', b'n') | (b't', b'n') => {
6918 let p = args.next_arg::<*mut c_void>();
6919 if !p.is_null() { *(p as *mut usize) = count; }
6920 }
6921 (b'j', b'n') => {
6922 let p = args.next_arg::<*mut c_void>();
6923 if !p.is_null() { *(p as *mut c_ulonglong) = count as c_ulonglong; }
6924 }
6925 (b'l', b'd') | (b'l', b'i') => {
6926 let val = args.next_arg::<c_long>();
6927 let neg = val < 0;
6928 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
6929 let b = format_u64(abs);
6930 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
6931 let mut fbuf = [0u8; 32];
6932 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
6933 ($write_str)(fbuf.as_ptr(), len); count += len;
6934 }
6935 (b'l', b'u') => {
6936 let val = args.next_arg::<c_ulong>();
6937 let b = format_u64(val as u64);
6938 let mut fbuf = [0u8; 32];
6939 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
6940 ($write_str)(fbuf.as_ptr(), len); count += len;
6941 }
6942 (b'l', b's') => {
6943 let p = args.next_arg::<*const wchar_t>();
6944 if p.is_null() {
6945 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
6946 let pad = width.saturating_sub(slen);
6947 if flags & FLAG_MINUS != 0 { ($write_str)(b"(null)".as_ptr(), slen); for _ in 0..pad { ($write_char)(b' '); } }
6948 else { for _ in 0..pad { ($write_char)(b' '); } ($write_str)(b"(null)".as_ptr(), slen); }
6949 count += slen + pad;
6950 } else {
6951 let mut mb = [0u8; 4096];
6952 let mut n = wide_to_mb(mb.as_mut_ptr(), mb.len(), p);
6953 if precision >= 0 && (precision as usize) < n { n = precision as usize; }
6954 let pad = width.saturating_sub(n);
6955 if flags & FLAG_MINUS != 0 { ($write_str)(mb.as_ptr(), n); for _ in 0..pad { ($write_char)(b' '); } }
6956 else { for _ in 0..pad { ($write_char)(b' '); } ($write_str)(mb.as_ptr(), n); }
6957 count += n + pad;
6958 }
6959 }
6960 (b'l', b'c') => {
6961 let ch = args.next_arg::<c_int>();
6962 let mut mb = [0u8; 8];
6963 let mut st: c_uint = 0;
6964 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, ch, &mut st);
6965 if n != !0usize { ($write_str)(mb.as_ptr(), n); count += n; }
6966 }
6967 (b'l', b'x') => {
6968 let val = args.next_arg::<c_ulong>();
6969 let b = format_hex(val as u64, false);
6970 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
6971 let mut fbuf = [0u8; 32];
6972 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6973 ($write_str)(fbuf.as_ptr(), len); count += len;
6974 }
6975 (b'l', b'X') => {
6976 let val = args.next_arg::<c_ulong>();
6977 let b = format_hex(val as u64, true);
6978 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
6979 let mut fbuf = [0u8; 32];
6980 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6981 ($write_str)(fbuf.as_ptr(), len); count += len;
6982 }
6983 (b'l', b'o') => {
6984 let val = args.next_arg::<c_ulong>();
6985 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
6986 let mut fbuf = [0u8; 32];
6987 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
6988 ($write_str)(fbuf.as_ptr(), len); count += len;
6989 }
6990 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
6991 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
6992 let val = args.next_arg::<f64>();
6993 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
6994 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
6995 let mut fbuf = [0u8; 4224];
6996 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
6997 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
6998 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
6999 ($write_str)(fbuf.as_ptr(), total); count += total;
7000 }
7001 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
7002 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
7003 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
7004 let val = {
7005 let lo: u64 = args.next_arg::<u64>();
7006 let hi: u64 = args.next_arg::<u64>();
7007 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
7008 f128::from_bits(combined) as f64
7009 };
7010 #[cfg(target_arch = "x86_64")]
7011 let val = args.next_arg::<f64>();
7012 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7013 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7014 let mut fbuf = [0u8; 4224];
7015 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7016 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
7017 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
7018 ($write_str)(fbuf.as_ptr(), total); count += total;
7019 }
7020 _ => { ($write_char)(b'%'); ($write_char)(len_mod); ($write_char)(spec); count += 3; }
7021 }
7022 }
7023 } else {
7024 spec = *fmt.add(i) as u8;
7025 match spec {
7026 b's' => {
7027 let s = args.next_arg::<*const c_char>();
7028 if s.is_null() {
7029 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
7030 let padded_len = if width > slen { width } else { slen };
7031 let pad = padded_len - slen;
7032 if flags & FLAG_MINUS != 0 {
7033 ($write_str)(b"(null)".as_ptr(), slen);
7034 for _ in 0..pad { ($write_char)(b' '); }
7035 } else {
7036 for _ in 0..pad { ($write_char)(b' '); }
7037 ($write_str)(b"(null)".as_ptr(), slen);
7038 }
7039 count += padded_len;
7040 } else {
7041 let full_len = strlen(s as *const c_char);
7042 let slen = if precision >= 0 { (precision as usize).min(full_len) } else { full_len };
7043 let padded_len = if width > slen { width } else { slen };
7044 let pad = padded_len - slen;
7045 if flags & FLAG_MINUS != 0 {
7046 ($write_str)(s as *const u8, slen);
7047 for _ in 0..pad { ($write_char)(b' '); }
7048 } else {
7049 for _ in 0..pad { ($write_char)(b' '); }
7050 ($write_str)(s as *const u8, slen);
7051 }
7052 count += padded_len;
7053 }
7054 }
7055 b'd' | b'i' => {
7056 let d = args.next_arg::<c_int>();
7057 let neg = d < 0;
7058 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
7059 let b = format_u64(abs);
7060 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7061 let mut fbuf = [0u8; 32];
7062 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7063 ($write_str)(fbuf.as_ptr(), len); count += len;
7064 }
7065 b'u' => {
7066 let u = args.next_arg::<c_uint>();
7067 let b = format_u64(u as u64);
7068 let mut fbuf = [0u8; 32];
7069 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7070 ($write_str)(fbuf.as_ptr(), len); count += len;
7071 }
7072 b'x' => {
7073 let x = args.next_arg::<c_uint>();
7074 let b = format_hex(x as u64, false);
7075 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7076 let mut fbuf = [0u8; 32];
7077 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7078 ($write_str)(fbuf.as_ptr(), len); count += len;
7079 }
7080 b'X' => {
7081 let x = args.next_arg::<c_uint>();
7082 let b = format_hex(x as u64, true);
7083 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7084 let mut fbuf = [0u8; 32];
7085 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7086 ($write_str)(fbuf.as_ptr(), len); count += len;
7087 }
7088 b'o' => {
7089 let o = args.next_arg::<c_uint>();
7090 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
7091 let mut fbuf = [0u8; 32];
7092 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7093 ($write_str)(fbuf.as_ptr(), len); count += len;
7094 }
7095 b'c' => {
7096 let ch = args.next_arg::<c_int>();
7097 if width > 1 {
7098 let pad = width - 1;
7099 if flags & FLAG_MINUS != 0 {
7100 ($write_char)(ch as u8); count += 1;
7101 for _ in 0..pad { ($write_char)(b' '); count += 1; }
7102 } else {
7103 for _ in 0..pad { ($write_char)(b' '); count += 1; }
7104 ($write_char)(ch as u8); count += 1;
7105 }
7106 } else {
7107 ($write_char)(ch as u8); count += 1;
7108 }
7109 }
7110 b'p' => {
7111 let p = args.next_arg::<*const c_void>();
7112 let mut fbuf = [0u8; 20];
7113 fbuf[0] = b'0'; fbuf[1] = b'x';
7114 let b = format_hex(p as u64, false);
7115 core::ptr::copy_nonoverlapping(b.0.as_ptr(), fbuf.as_mut_ptr().add(2), b.1);
7116 ($write_str)(fbuf.as_ptr(), b.1 + 2); count += b.1 + 2;
7117 }
7118 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
7119 let val = args.next_arg::<f64>();
7120 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7121 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7122 let mut fbuf = [0u8; 4224];
7123 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7124 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
7125 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
7126 ($write_str)(fbuf.as_ptr(), total); count += total;
7127 }
7128 b'%' => { ($write_char)(b'%'); count += 1; }
7129 b'n' => {
7130 let p = args.next_arg::<*mut c_void>();
7131 if !p.is_null() { *(p as *mut c_int) = count as c_int; }
7132 }
7133 _ => { ($write_char)(b'%'); ($write_char)(spec); count += 2; }
7134 }
7135 }
7136 i += 1;
7137 }
7138 count as c_int
7139 }};
7140}
7141
7142unsafe fn format_u64(mut val: u64) -> ([u8; 20], usize) {
7143 let mut buf = [0u8; 20];
7144 if val == 0 { buf[0] = b'0'; return (buf, 1); }
7145 let mut tmp = [0u8; 20];
7146 let mut pos = 20;
7147 while val > 0 { pos -= 1; tmp[pos] = b'0' + (val % 10) as u8; val /= 10; }
7148 let len = 20 - pos;
7149 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7150 (buf, len)
7151}
7152
7153unsafe fn format_i64(val: i64) -> ([u8; 21], usize) {
7154 let mut buf = [0u8; 21];
7155 if val < 0 {
7156 buf[0] = b'-';
7157 let (inner, len) = format_u64((-(val as i128)) as u64);
7158 core::ptr::copy_nonoverlapping(inner.as_ptr(), buf.as_mut_ptr().add(1), len);
7159 (buf, len + 1)
7160 } else {
7161 let (inner, len) = format_u64(val as u64);
7162 core::ptr::copy_nonoverlapping(inner.as_ptr(), buf.as_mut_ptr(), len);
7163 (buf, len)
7164 }
7165}
7166
7167unsafe fn format_hex(mut val: u64, uppercase: bool) -> ([u8; 16], usize) {
7168 let digits = if uppercase { b"0123456789ABCDEF" } else { b"0123456789abcdef" };
7169 let mut buf = [0u8; 16];
7170 if val == 0 { buf[0] = b'0'; return (buf, 1); }
7171 let mut tmp = [0u8; 16];
7172 let mut pos = 16;
7173 while val > 0 { pos -= 1; tmp[pos] = digits[(val & 0xf) as usize]; val >>= 4; }
7174 let len = 16 - pos;
7175 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7176 (buf, len)
7177}
7178
7179unsafe fn format_octal(mut val: u64, alt: bool) -> ([u8; 24], usize) {
7180 let mut buf = [0u8; 24];
7181 if val == 0 {
7182 buf[0] = b'0';
7183 return (buf, 1);
7184 }
7185 let mut tmp = [0u8; 24];
7186 let mut pos = 24;
7187 while val > 0 {
7188 pos -= 1;
7189 tmp[pos] = b'0' + (val & 7) as u8;
7190 val >>= 3;
7191 }
7192 let len = 24 - pos;
7193 if alt {
7194 tmp[pos - 1] = b'0';
7195 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos - 1), buf.as_mut_ptr(), len + 1);
7196 (buf, len + 1)
7197 } else {
7198 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7199 (buf, len)
7200 }
7201}
7202
7203unsafe fn format_int(
7204 dst: *mut u8,
7205 digits: *const u8,
7206 digits_len: usize,
7207 sign: Option<u8>,
7208 prefix: Option<u8>,
7209 precision: i32,
7210 width: usize,
7211 flags: u8,
7212 octal_alt: bool,
7213) -> usize {
7214 let num_digits = if precision == 0 && digits_len == 1 && *digits == b'0' && !octal_alt {
7215 0
7216 } else {
7217 digits_len
7218 };
7219 let prec = precision as usize;
7220 let zero_pad = if precision >= 0 && prec > num_digits { prec - num_digits } else { 0 };
7221
7222 let sign_len = sign.map_or(0, |_| 1);
7223 let prefix_len = prefix.map_or(0, |_| 2);
7224 let content_len = sign_len + prefix_len + zero_pad + num_digits;
7225
7226 let mut buf = [0u8; 32];
7227 let mut pos = 0usize;
7228 if let Some(c) = sign { buf[pos] = c; pos += 1; }
7229 if let Some(c) = prefix { buf[pos] = b'0'; pos += 1; buf[pos] = c; pos += 1; }
7230 for _ in 0..zero_pad { buf[pos] = b'0'; pos += 1; }
7231 if num_digits > 0 {
7232 core::ptr::copy_nonoverlapping(digits, buf.as_mut_ptr().add(pos), num_digits);
7233 }
7234
7235 if content_len >= width {
7236 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, content_len);
7237 return content_len;
7238 }
7239 let pad = width - content_len;
7240 if flags & FLAG_MINUS != 0 {
7241 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, content_len);
7242 for i in 0..pad { *dst.add(content_len + i) = b' '; }
7243 } else if flags & FLAG_ZERO != 0 && precision < 0 {
7244 let fixed = sign_len + prefix_len;
7245 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, fixed);
7246 for i in fixed..width - num_digits { *dst.add(i) = b'0'; }
7247 if num_digits > 0 {
7248 core::ptr::copy_nonoverlapping(digits, dst.add(width - num_digits), num_digits);
7249 }
7250 } else {
7251 for i in 0..pad { *dst.add(i) = b' '; }
7252 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst.add(pad), content_len);
7253 }
7254 width
7255}
7256
7257unsafe fn format_f64(val: f64) -> ([u8; 64], usize) {
7258 let mut buf = [0u8; 64];
7259 let mut pos = 0usize;
7260 let mut v = val;
7261 if v.is_nan() {
7262 let nan = b"nan";
7263 core::ptr::copy_nonoverlapping(nan.as_ptr(), buf.as_mut_ptr(), 3);
7264 return (buf, 3);
7265 }
7266 if v < 0.0 { buf[pos] = b'-'; pos += 1; v = -v; }
7267 if v.is_infinite() {
7268 let inf = b"inf";
7269 core::ptr::copy_nonoverlapping(inf.as_ptr(), buf.as_mut_ptr().add(pos), 3);
7270 return (buf, pos + 3);
7271 }
7272 let int_part = v as u64;
7273 let frac = v - int_part as f64;
7274 let (ibuf, ilen) = format_u64(int_part);
7275 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), buf.as_mut_ptr().add(pos), ilen);
7276 pos += ilen;
7277 buf[pos] = b'.';
7278 pos += 1;
7279 let mut f = frac;
7280 for _ in 0..6 { f *= 10.0; let digit = f as u8; buf[pos] = b'0' + digit; pos += 1; f -= digit as f64; }
7281 (buf, pos)
7282}
7283
7284const FMT_F: u8 = 0;
7286const FMT_E: u8 = 1;
7287const FMT_G: u8 = 2;
7288const FMT_A: u8 = 3;
7289
7290const FLAG_HASH: u8 = 1;
7291const FLAG_PLUS: u8 = 2;
7292const FLAG_SPACE: u8 = 4;
7293const FLAG_ZERO: u8 = 8;
7294const FLAG_MINUS: u8 = 16;
7295
7296unsafe fn bigint_to_decimal(buf: *mut u8, mant: u64, shift: u32) -> usize {
7301 let nlimbs = (2 + (shift + 31) / 32) as usize;
7303 let mut limbs = [0u32; 36];
7304 limbs[0] = mant as u32;
7305 limbs[1] = (mant >> 32) as u32;
7306
7307 let ws = (shift / 32) as usize;
7308 let bs = shift % 32;
7309
7310 if ws > 0 {
7312 let mut i = 1usize;
7313 loop {
7314 limbs[i + ws] = limbs[i];
7315 if i == 0 { break; }
7316 i -= 1;
7317 }
7318 for j in 0..ws { limbs[j] = 0; }
7319 }
7320 if bs > 0 {
7322 let mut carry = 0u32;
7323 let end = nlimbs.min(ws + 3);
7324 for i in ws..end {
7325 let new_val = (limbs[i] << bs) | carry;
7326 carry = limbs[i] >> (32 - bs);
7327 limbs[i] = new_val;
7328 }
7329 }
7330
7331 let mut used = nlimbs;
7333 while used > 0 && limbs[used - 1] == 0 { used -= 1; }
7334 if used == 0 { *buf = b'0'; return 1; }
7335
7336 let mut digits = [0u8; 400];
7338 let mut nd = 0usize;
7339 loop {
7340 let mut all_zero = true;
7341 for i in 0..used { if limbs[i] != 0 { all_zero = false; break; } }
7342 if all_zero { break; }
7343 let mut rem = 0u64;
7344 for i in (0..used).rev() {
7345 let val = (rem << 32) | limbs[i] as u64;
7346 limbs[i] = (val / 10) as u32;
7347 rem = val % 10;
7348 }
7349 digits[nd] = rem as u8;
7350 nd += 1;
7351 }
7352 for i in 0..nd { *buf.add(i) = b'0' + digits[nd - 1 - i]; }
7354 nd
7355}
7356
7357unsafe fn frac_digits_u128(buf: *mut u8, frac_bits: u64, shift: u32, count: usize) -> bool {
7360 let mask: u128 = (1u128 << shift) - 1;
7361 let mut rem = frac_bits as u128;
7362 for i in 0..count {
7363 rem *= 10;
7364 let digit = (rem >> shift) as u8;
7365 rem &= mask;
7366 *buf.add(i) = digit;
7367 }
7368 rem != 0
7369}
7370
7371unsafe fn frac_digits_bigint(buf: *mut u8, frac_bits: u64, shift: u32, count: usize) -> bool {
7374 let nlimbs = ((shift + 31) / 32) as usize;
7375 let mut rem = [0u32; 36]; rem[0] = frac_bits as u32;
7377 if nlimbs > 1 { rem[1] = (frac_bits >> 32) as u32; }
7378 let hi_word = (shift / 32) as usize;
7380 let hi_bit = shift % 32;
7381 if hi_bit > 0 && hi_word < nlimbs {
7382 rem[hi_word] &= (1u32 << hi_bit) - 1;
7383 }
7384 let clear_from = if hi_bit > 0 { hi_word + 1 } else { hi_word };
7386 for j in clear_from..nlimbs { rem[j] = 0; }
7387
7388 for i in 0..count {
7389 let mut carry = 0u64;
7391 for j in 0..nlimbs {
7392 let val = rem[j] as u64 * 10 + carry;
7393 rem[j] = val as u32;
7394 carry = val >> 32;
7395 }
7396 let digit: u32;
7398 if hi_bit == 0 {
7399 digit = if hi_word < nlimbs { rem[hi_word] } else { carry as u32 };
7400 } else {
7401 let mut d = if hi_word < nlimbs { rem[hi_word] >> hi_bit } else { 0 };
7402 if hi_word + 1 < nlimbs {
7403 d |= rem[hi_word + 1] << (32 - hi_bit);
7404 } else if carry > 0 {
7405 d |= (carry as u32) << (32 - hi_bit);
7406 }
7407 digit = d;
7408 }
7409 *buf.add(i) = digit.min(9) as u8;
7410 if hi_bit == 0 {
7412 if hi_word < nlimbs { rem[hi_word] = 0; }
7413 } else {
7414 if hi_word < nlimbs {
7415 rem[hi_word] &= (1u32 << hi_bit) - 1;
7416 }
7417 for j in (hi_word + 1)..nlimbs { rem[j] = 0; }
7418 }
7419 }
7420 for i in 0..nlimbs { if rem[i] != 0 { return true; } }
7422 false
7423}
7424
7425unsafe fn increment_decimal(buf: *mut u8, len: &mut usize) {
7427 let mut j = *len;
7428 loop {
7429 if j == 0 {
7430 let l = *len;
7432 for i in (0..l).rev() { *buf.add(i + 1) = *buf.add(i); }
7433 *buf = b'1';
7434 *len = l + 1;
7435 return;
7436 }
7437 j -= 1;
7438 let d = *buf.add(j);
7439 if d < b'9' { *buf.add(j) = d + 1; return; }
7440 *buf.add(j) = b'0';
7441 }
7442}
7443
7444unsafe fn format_f64_full(
7446 dst: *mut u8, val: f64, fmt_type: u8, precision: i32, flags: u8, uppercase: bool,
7447) -> usize {
7448 let mut pos = 0usize;
7449
7450 if val.is_nan() {
7452 let nan_s: &[u8] = if uppercase { b"NAN" } else { b"nan" };
7453 core::ptr::copy_nonoverlapping(nan_s.as_ptr(), dst, 3);
7454 return 3;
7455 }
7456 let neg = val.is_sign_negative();
7457 let v = if neg { -val } else { val };
7458
7459 if v.is_infinite() {
7461 if neg { *dst.add(pos) = b'-'; pos += 1; }
7462 else if flags & FLAG_PLUS != 0 { *dst.add(pos) = b'+'; pos += 1; }
7463 else if flags & FLAG_SPACE != 0 { *dst.add(pos) = b' '; pos += 1; }
7464 let inf_s: &[u8] = if uppercase { b"INF" } else { b"inf" };
7465 core::ptr::copy_nonoverlapping(inf_s.as_ptr(), dst.add(pos), 3);
7466 return pos + 3;
7467 }
7468
7469 if neg { *dst.add(pos) = b'-'; pos += 1; }
7471 else if flags & FLAG_PLUS != 0 { *dst.add(pos) = b'+'; pos += 1; }
7472 else if flags & FLAG_SPACE != 0 { *dst.add(pos) = b' '; pos += 1; }
7473
7474 if fmt_type == FMT_A {
7476 return pos + fmt_hex_float(dst.add(pos), val, precision, flags, uppercase);
7477 }
7478
7479 let p: usize;
7481 let mut exp: i32;
7482 let use_f: bool;
7483
7484 match fmt_type {
7485 FMT_G => {
7486 let gp = if precision < 0 { 6usize } else if precision == 0 { 1usize } else { precision as usize };
7487 exp = if v > 0.0 { compute_exp10(v) } else { 0 };
7488 use_f = exp >= -4 && exp < gp as i32;
7489 if use_f {
7490 p = if exp < 0 { gp + ((-exp) as usize - 1) }
7491 else if (exp as usize) < gp { gp - exp as usize - 1 }
7492 else { 0 };
7493 } else {
7494 p = gp - 1;
7495 }
7496 }
7497 FMT_E => {
7498 p = if precision < 0 { 6usize } else { precision as usize };
7499 exp = if v > 0.0 { compute_exp10(v) } else { 0 };
7500 use_f = false;
7501 }
7502 _ => {
7503 p = if precision < 0 { 6usize } else { precision as usize };
7504 exp = 0;
7505 use_f = true;
7506 }
7507 }
7508
7509 if v == 0.0 {
7510 *dst.add(pos) = b'0'; pos += 1;
7511 if !(fmt_type == FMT_G && flags & FLAG_HASH == 0) {
7512 if p > 0 || flags & FLAG_HASH != 0 {
7513 *dst.add(pos) = b'.'; pos += 1;
7514 for _ in 0..p { *dst.add(pos) = b'0'; pos += 1; }
7515 }
7516 }
7517 if !use_f {
7518 let ec = if uppercase { b'E' } else { b'e' };
7519 *dst.add(pos) = ec; pos += 1;
7520 *dst.add(pos) = b'+'; pos += 1;
7521 *dst.add(pos) = b'0'; pos += 1;
7522 *dst.add(pos) = b'0'; pos += 1;
7523 }
7524 return pos;
7525 }
7526
7527 if use_f {
7529 let bits = v.to_bits();
7530 let raw_mant = bits & 0x000FFFFFFFFFFFFF;
7531 let raw_exp_bits = ((bits >> 52) & 0x7FF) as i32;
7532 let (mant_b, bin_exp) = if raw_exp_bits == 0 {
7533 (raw_mant, -1022i32)
7534 } else {
7535 (raw_mant | (1u64 << 52), raw_exp_bits - 1023)
7536 };
7537
7538 let mut ibuf = [0u8; 400];
7540 let mut ilen: usize;
7541 if bin_exp < 0 {
7542 ibuf[0] = b'0'; ilen = 1;
7543 } else if bin_exp <= 63 {
7544 let int_val = if bin_exp <= 52 { mant_b >> (52 - bin_exp) }
7545 else { mant_b << (bin_exp - 52) };
7546 let (buf2, len2) = format_u64(int_val);
7547 ibuf[..len2].copy_from_slice(&buf2[..len2]);
7548 ilen = len2;
7549 } else {
7550 ilen = bigint_to_decimal(ibuf.as_mut_ptr(), mant_b, (bin_exp - 52) as u32);
7551 }
7552
7553 let mut fbuf = [0u8; 1100];
7555 let mut has_rest = false;
7556 if p > 0 && bin_exp < 52 {
7557 let shift = (52 - bin_exp) as u32;
7558 let frac_bits = if bin_exp >= 0 { mant_b & ((1u64 << shift) - 1) } else { mant_b };
7559 if shift <= 124 {
7560 has_rest = frac_digits_u128(fbuf.as_mut_ptr(), frac_bits, shift, p + 1);
7561 } else {
7562 has_rest = frac_digits_bigint(fbuf.as_mut_ptr(), frac_bits, shift, p + 1);
7563 }
7564 }
7565
7566 if p > 0 && bin_exp < 52 {
7568 let next_d = fbuf[p];
7569 let last_d = fbuf[p - 1];
7570 if next_d > 5 || (next_d == 5 && (has_rest || last_d & 1 != 0)) {
7571 let mut carry = true;
7572 for j in (0..p).rev() {
7573 if !carry { break; }
7574 fbuf[j] += 1;
7575 if fbuf[j] < 10 { carry = false; break; }
7576 fbuf[j] = 0;
7577 }
7578 if carry { increment_decimal(ibuf.as_mut_ptr(), &mut ilen); }
7579 }
7580 } else if p == 0 {
7581 if bin_exp >= 0 && bin_exp < 52 {
7583 let shift = (52 - bin_exp) as u32;
7584 let frac_bits = mant_b & ((1u64 << shift) - 1);
7585 let half = 1u64 << (shift - 1);
7586 let last_d = ibuf[ilen - 1] - b'0';
7587 if frac_bits > half || (frac_bits == half && last_d & 1 != 0) {
7588 increment_decimal(ibuf.as_mut_ptr(), &mut ilen);
7589 }
7590 }
7591 }
7592
7593 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), dst.add(pos), ilen);
7595 pos += ilen;
7596 if p > 0 || flags & FLAG_HASH != 0 {
7597 *dst.add(pos) = b'.'; pos += 1;
7598 for i in 0..p { *dst.add(pos) = b'0' + fbuf[i]; pos += 1; }
7599 }
7600 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7601 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7602 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7603 }
7604 return pos;
7605 }
7606
7607 let mut fbuf = [0u8; 20];
7610 let mut int_part: u64;
7611 {
7612 let bits_v = v.to_bits();
7613 let raw_mant_v = bits_v & 0x000FFFFFFFFFFFFF;
7614 let raw_exp_v = ((bits_v >> 52) & 0x7FF) as i32;
7615 let (mant_b_v, bin_exp_v) = if raw_exp_v == 0 {
7616 (raw_mant_v, -1022i32)
7617 } else {
7618 (raw_mant_v | (1u64 << 52), raw_exp_v - 1023)
7619 };
7620
7621 let s: i32 = (p as i32) + 1 - exp;
7622 let bs: i32 = bin_exp_v - 52 + s;
7623
7624 let mut limbs = [0u32; 40];
7625 limbs[0] = mant_b_v as u32;
7626 limbs[1] = (mant_b_v >> 32) as u32;
7627 let mut nlimbs: usize = if limbs[1] != 0 { 2 } else { 1 };
7628
7629 if s > 0 {
7630 for _ in 0..(s as usize) {
7631 let mut carry = 0u64;
7632 for j in 0..nlimbs {
7633 let val = limbs[j] as u64 * 5 + carry;
7634 limbs[j] = val as u32;
7635 carry = val >> 32;
7636 }
7637 if carry > 0 { limbs[nlimbs] = carry as u32; nlimbs += 1; }
7638 }
7639 }
7640
7641 if bs > 0 {
7642 let ws = (bs as u32 / 32) as usize;
7643 let bit = bs as u32 % 32;
7644 if ws > 0 {
7645 let mut i = nlimbs;
7646 while i > 0 { i -= 1; if i + ws < 40 { limbs[i + ws] = limbs[i]; } limbs[i] = 0; }
7647 nlimbs += ws;
7648 }
7649 if bit > 0 {
7650 let mut carry = 0u32;
7651 for i in ws..nlimbs {
7652 let new_val = (limbs[i] << bit) | carry;
7653 carry = limbs[i] >> (32 - bit);
7654 limbs[i] = new_val;
7655 }
7656 if carry > 0 && nlimbs < 40 { limbs[nlimbs] = carry; nlimbs += 1; }
7657 }
7658 }
7659
7660 let mut has_rest = false;
7661 if s < 0 {
7662 for _ in 0..(-s as usize) {
7663 let mut rem = 0u64;
7664 for i in (0..nlimbs).rev() {
7665 let val = (rem << 32) | limbs[i] as u64;
7666 limbs[i] = (val / 5) as u32;
7667 rem = val % 5;
7668 }
7669 if rem != 0 { has_rest = true; }
7670 }
7671 }
7672
7673 if bs < 0 {
7674 let rshift = (-bs) as u32;
7675 let ws = (rshift / 32) as usize;
7676 let bit = rshift % 32;
7677 if ws > 0 {
7678 for j in 0..ws.min(nlimbs) { if limbs[j] != 0 { has_rest = true; } }
7679 for i in ws..nlimbs { limbs[i - ws] = limbs[i]; }
7680 nlimbs = nlimbs.saturating_sub(ws);
7681 }
7682 if bit > 0 && nlimbs > 0 {
7683 let mask = (1u32 << bit) - 1;
7684 if limbs[0] & mask != 0 { has_rest = true; }
7685 for i in 0..nlimbs - 1 {
7686 limbs[i] = (limbs[i] >> bit) | (limbs[i + 1] << (32 - bit));
7687 }
7688 limbs[nlimbs - 1] >>= bit;
7689 }
7690 }
7691
7692 while nlimbs > 0 && limbs[nlimbs - 1] == 0 { nlimbs -= 1; }
7693
7694 let ndigits = p + 2;
7695 let mut all_digits = [0u8; 25];
7696 let mut nd = 0usize;
7697 if nlimbs > 0 {
7698 loop {
7699 let mut all_zero = true;
7700 for i in 0..nlimbs { if limbs[i] != 0 { all_zero = false; break; } }
7701 if all_zero { break; }
7702 let mut rem64 = 0u64;
7703 for i in (0..nlimbs).rev() {
7704 let val = (rem64 << 32) | limbs[i] as u64;
7705 limbs[i] = (val / 10) as u32;
7706 rem64 = val % 10;
7707 }
7708 if nd < 25 { all_digits[nd] = rem64 as u8; }
7709 nd += 1;
7710 }
7711 }
7712
7713 if nd >= ndigits {
7714 for i in 0..ndigits { fbuf[ndigits - 1 - i] = all_digits[i]; }
7715 } else {
7716 for i in 0..nd { fbuf[ndigits - 1 - i] = all_digits[i]; }
7717 for i in nd..ndigits { fbuf[ndigits - 1 - i] = 0; }
7718 }
7719
7720 int_part = fbuf[0] as u64;
7721
7722 if p > 0 {
7724 let next_d = fbuf[p + 1];
7725 let last_d = fbuf[p];
7726 if next_d > 5 || (next_d == 5 && (has_rest || last_d & 1 != 0)) {
7727 let mut carry = true;
7728 for j in (1..=p).rev() {
7729 if !carry { break; }
7730 let d = fbuf[j] + 1;
7731 if d < 10 { fbuf[j] = d; carry = false; break; }
7732 fbuf[j] = 0;
7733 }
7734 if carry { int_part += 1; }
7735 }
7736 } else {
7737 let next_d = fbuf[1];
7738 if next_d > 5 || (next_d == 5 && (has_rest || int_part & 1 != 0)) {
7739 int_part += 1;
7740 }
7741 }
7742
7743 for i in 0..p { fbuf[i] = fbuf[i + 1]; }
7746 }
7747
7748 if !use_f && int_part >= 10 {
7749 exp += 1;
7750 int_part = 1;
7751 }
7752
7753 if use_f {
7755 let (ibuf, ilen) = format_u64(int_part);
7757 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), dst.add(pos), ilen);
7758 pos += ilen;
7759 if p > 0 || flags & FLAG_HASH != 0 {
7760 *dst.add(pos) = b'.'; pos += 1;
7761 for idx in 0..p { *dst.add(pos) = b'0' + fbuf[idx]; pos += 1; }
7762 }
7763 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7764 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7765 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7766 }
7767 } else {
7768 *dst.add(pos) = b'0' + int_part as u8; pos += 1;
7770 if p > 0 || flags & FLAG_HASH != 0 {
7771 *dst.add(pos) = b'.'; pos += 1;
7772 for idx in 0..p { *dst.add(pos) = b'0' + fbuf[idx]; pos += 1; }
7773 }
7774 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7775 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7776 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7777 }
7778 let ec = if uppercase { b'E' } else { b'e' };
7779 *dst.add(pos) = ec; pos += 1;
7780 *dst.add(pos) = if exp < 0 { b'-' } else { b'+' }; pos += 1;
7781 let eabs = if exp < 0 { (-exp) as u32 } else { exp as u32 };
7782 if eabs < 10 { *dst.add(pos) = b'0'; pos += 1; }
7783 let (ebuf, elen) = format_u64(eabs as u64);
7784 core::ptr::copy_nonoverlapping(ebuf.as_ptr(), dst.add(pos), elen);
7785 pos += elen;
7786 }
7787
7788 pos
7789}
7790
7791unsafe fn compute_exp10(v: f64) -> i32 {
7793 let e = libm::floor(libm::log10(v)) as i32;
7794 let probe = v / libm::pow(10.0, e as f64);
7795 if probe >= 10.0 { e + 1 }
7796 else if probe < 1.0 { e - 1 }
7797 else { e }
7798}
7799
7800unsafe fn fmt_hex_float(dst: *mut u8, val: f64, precision: i32, _flags: u8, uppercase: bool) -> usize {
7802 if val.to_bits() & 0x7FFFFFFFFFFFFFFF == 0 {
7804 let lc = !uppercase;
7805 let pfx: &[u8] = if lc { b"0x" } else { b"0X" };
7806 let p = if precision < 0 { 0usize } else { precision as usize };
7807 let mut pos = 0usize;
7808 core::ptr::copy_nonoverlapping(pfx.as_ptr(), dst.add(pos), 2); pos += 2;
7809 *dst.add(pos) = b'0'; pos += 1;
7810 if p > 0 {
7811 *dst.add(pos) = b'.'; pos += 1;
7812 for _ in 0..p { *dst.add(pos) = b'0'; pos += 1; }
7813 }
7814 let pc = if lc { b'p' } else { b'P' };
7815 *dst.add(pos) = pc; pos += 1;
7816 *dst.add(pos) = b'+'; pos += 1;
7817 *dst.add(pos) = b'0'; pos += 1;
7818 return pos;
7819 }
7820 let bits = val.to_bits();
7821 let exp_bits = ((bits >> 52) & 0x7FF) as i32;
7822 let mant_bits = bits & 0x000FFFFFFFFFFFFF;
7823 let (e, m) = if exp_bits == 0 { (1 - 1023, mant_bits) } else { (exp_bits - 1023, mant_bits | (1u64 << 52)) };
7824 let p = if precision < 0 { 13usize } else { precision as usize };
7825 let mut pos = 0usize;
7826 let lc = !uppercase;
7827 let pfx: &[u8] = if lc { b"0x" } else { b"0X" };
7828 core::ptr::copy_nonoverlapping(pfx.as_ptr(), dst.add(pos), 2); pos += 2;
7829
7830 let lead = ((m >> 52) & 0xF) as u8;
7832 *dst.add(pos) = hex_digit_char(lead, lc); pos += 1;
7833 if p > 0 {
7834 *dst.add(pos) = b'.'; pos += 1;
7835 }
7836
7837 let frac_start = pos;
7839 let mut rm = m << 4; for _ in 0..p {
7841 let nib = ((rm >> 48) & 0xF) as u8;
7842 *dst.add(pos) = hex_digit_char(nib, lc); pos += 1;
7843 rm <<= 4;
7844 }
7845
7846 if p > 0 {
7848 let round_nib = ((rm >> 48) & 0xF) as u8;
7849 let rest = rm & 0x0000FFFFFFFFFFFF;
7850 let last_nib = if p > 0 {
7851 let c = *dst.add(pos - 1);
7852 hex_char_val(c)
7853 } else { lead };
7854 let should_round = round_nib > 8 || (round_nib == 8 && (rest != 0 || (last_nib & 1) != 0));
7855 if should_round {
7856 let mut j = pos - 1;
7857 loop {
7858 if j < frac_start { break; }
7859 let v = hex_char_val(*dst.add(j));
7860 if v < 15 {
7861 *dst.add(j) = hex_digit_char(v + 1, lc);
7862 break;
7863 } else {
7864 *dst.add(j) = b'0';
7865 if j == frac_start { break; }
7866 j -= 1;
7867 }
7868 }
7869 }
7870 }
7871
7872 let pc = if lc { b'p' } else { b'P' };
7874 *dst.add(pos) = pc; pos += 1;
7875 *dst.add(pos) = if e < 0 { b'-' } else { b'+' }; pos += 1;
7876 let eabs = if e < 0 { (-e) as u32 } else { e as u32 };
7877 let (ebuf, elen) = format_u64(eabs as u64);
7878 core::ptr::copy_nonoverlapping(ebuf.as_ptr(), dst.add(pos), elen);
7879 pos += elen;
7880 pos
7881}
7882
7883#[inline]
7884fn hex_digit_char(v: u8, lowercase: bool) -> u8 {
7885 if v < 10 { b'0' + v }
7886 else if lowercase { b'a' + v - 10 }
7887 else { b'A' + v - 10 }
7888}
7889
7890#[inline]
7891fn hex_char_val(c: u8) -> u8 {
7892 if c >= b'0' && c <= b'9' { c - b'0' }
7893 else if c >= b'a' && c <= b'f' { c - b'a' + 10 }
7894 else if c >= b'A' && c <= b'F' { c - b'A' + 10 }
7895 else { 0 }
7896}
7897
7898unsafe fn apply_width_flags(
7901 dst: *mut u8, buf: *const u8, len: usize, width: usize, flags: u8,
7902) -> usize {
7903 if len >= width {
7904 core::ptr::copy_nonoverlapping(buf, dst, len);
7905 return len;
7906 }
7907 let pad = width - len;
7908 let pad_char = if flags & FLAG_ZERO != 0 && flags & FLAG_MINUS == 0 { b'0' } else { b' ' };
7909 if flags & FLAG_MINUS != 0 {
7910 core::ptr::copy_nonoverlapping(buf, dst, len);
7912 for i in 0..pad { *dst.add(len + i) = pad_char; }
7913 } else {
7914 if flags & FLAG_ZERO != 0 && len > 0 {
7917 let first = *buf;
7918 if first == b'-' || first == b'+' || first == b' ' {
7919 *dst = first;
7920 for i in 0..pad { *dst.add(1 + i) = pad_char; }
7921 core::ptr::copy_nonoverlapping(buf.add(1), dst.add(1 + pad), len - 1);
7922 return width;
7923 }
7924 }
7925 for i in 0..pad { *dst.add(i) = pad_char; }
7926 core::ptr::copy_nonoverlapping(buf, dst.add(pad), len);
7927 }
7928 width
7929}
7930
7931#[no_mangle]
7932pub unsafe extern "C" fn vprintf(fmt: *const c_char, mut args: VaList) -> c_int {
7933 impl_format!(fmt, args,
7934 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stdout); },
7935 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stdout); }
7936 )
7937}
7938
7939#[no_mangle]
7940pub unsafe extern "C" fn vfprintf(stream: *mut FILE, fmt: *const c_char, mut args: VaList) -> c_int {
7941 impl_format!(fmt, args,
7942 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stream); },
7943 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stream); }
7944 )
7945}
7946
7947#[no_mangle]
7948pub unsafe extern "C" fn printf(fmt: *const c_char, mut args: ...) -> c_int {
7949 impl_format!(fmt, args,
7950 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stdout); },
7951 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stdout); }
7952 )
7953}
7954
7955#[no_mangle]
7956pub unsafe extern "C" fn fprintf(stream: *mut FILE, fmt: *const c_char, mut args: ...) -> c_int {
7957 impl_format!(fmt, args,
7958 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stream); },
7959 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stream); }
7960 )
7961}
7962
7963#[no_mangle]
7964pub unsafe extern "C" fn dprintf(fd: c_int, fmt: *const c_char, mut args: ...) -> c_int {
7965 impl_format!(fmt, args,
7966 |c: u8| { write_str(fd, &c as *const u8, 1); },
7967 |s: *const u8, len: usize| { write_str(fd, s, len); }
7968 )
7969}
7970
7971#[no_mangle]
7972pub unsafe extern "C" fn vdprintf(fd: c_int, fmt: *const c_char, mut args: VaList) -> c_int {
7973 impl_format!(fmt, args,
7974 |c: u8| { write_str(fd, &c as *const u8, 1); },
7975 |s: *const u8, len: usize| { write_str(fd, s, len); }
7976 )
7977}
7978
7979unsafe fn format_to_buf(buf: *mut u8, cap: usize, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
7984 let mut pos = 0usize;
7985 let mut i = 0usize;
7986 let mut count = 0usize;
7987 macro_rules! wc {
7988 ($c:expr) => { if pos < cap { *buf.add(pos) = $c; } pos += 1; count += 1; }
7989 }
7990 macro_rules! ws {
7991 ($s:expr, $len:expr) => {{
7992 let __len = $len;
7993 for k in 0..__len { if pos + k < cap { *buf.add(pos + k) = *$s.add(k); } }
7994 pos += __len; count += __len;
7995 }}
7996 }
7997 macro_rules! ws_buf {
7999 ($src:expr, $len:expr) => {{
8000 let __len = $len;
8001 for k in 0..__len { if pos + k < cap { *buf.add(pos + k) = *$src.add(k); } }
8002 pos += __len; count += __len;
8003 }}
8004 }
8005 loop {
8006 let c = *fmt.add(i) as u8;
8007 if c == 0 { break; }
8008 if c != b'%' { wc!(c); i += 1; continue; }
8009 i += 1;
8010 let mut flags: u8 = 0;
8012 loop {
8013 let fc = *fmt.add(i) as u8;
8014 match fc {
8015 b'-' => { flags |= FLAG_MINUS; i += 1; }
8016 b'+' => { flags |= FLAG_PLUS; i += 1; }
8017 b' ' => { flags |= FLAG_SPACE; i += 1; }
8018 b'0' => { flags |= FLAG_ZERO; i += 1; }
8019 b'#' => { flags |= FLAG_HASH; i += 1; }
8020 _ => break,
8021 }
8022 }
8023 let mut width: usize = 0;
8025 if *fmt.add(i) as u8 == b'*' {
8026 width = args.next_arg::<c_int>() as usize; i += 1;
8027 } else {
8028 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
8029 width = width * 10 + ((*fmt.add(i) as u8) - b'0') as usize; i += 1;
8030 }
8031 }
8032 let mut precision: i32 = -1;
8034 if *fmt.add(i) as u8 == b'.' {
8035 i += 1;
8036 if *fmt.add(i) as u8 == b'*' {
8037 precision = args.next_arg::<c_int>(); i += 1;
8038 } else {
8039 precision = 0;
8040 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
8041 precision = precision * 10 + ((*fmt.add(i) as u8) - b'0') as i32; i += 1;
8042 }
8043 }
8044 }
8045 let len_mod = *fmt.add(i) as u8;
8047 let spec: u8;
8048 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' {
8049 i += 1;
8050 let len_mod2 = *fmt.add(i) as u8;
8051 if (len_mod == b'h' && len_mod2 == b'h') || (len_mod == b'l' && len_mod2 == b'l') {
8052 i += 1;
8053 spec = *fmt.add(i) as u8;
8054 match (len_mod, len_mod2, spec) {
8055 (b'h', b'h', b'n') => {
8056 let p = args.next_arg::<*mut c_void>();
8057 if !p.is_null() { *(p as *mut u8) = count as u8; }
8058 }
8059 (b'l', b'l', b'n') => {
8060 let p = args.next_arg::<*mut c_void>();
8061 if !p.is_null() { *(p as *mut c_longlong) = count as c_longlong; }
8062 }
8063 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
8064 let val = args.next_arg::<c_longlong>();
8065 let neg = val < 0;
8066 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
8067 let b = format_u64(abs);
8068 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8069 let mut fbuf = [0u8; 32];
8070 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8071 ws_buf!(fbuf.as_ptr(), len);
8072 }
8073 (b'l', b'l', b'u') => {
8074 let val = args.next_arg::<c_ulonglong>();
8075 let b = format_u64(val as u64);
8076 let mut fbuf = [0u8; 32];
8077 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8078 ws_buf!(fbuf.as_ptr(), len);
8079 }
8080 (b'l', b'l', b'o') => {
8081 let val = args.next_arg::<c_ulonglong>();
8082 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
8083 let mut fbuf = [0u8; 32];
8084 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8085 ws_buf!(fbuf.as_ptr(), len);
8086 }
8087 _ => { wc!(b'%'); wc!(len_mod); wc!(len_mod2); wc!(spec); }
8088 }
8089 } else {
8090 spec = len_mod2;
8091 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
8092 match (lm, spec) {
8093 (b'h', b'n') => {
8094 let p = args.next_arg::<*mut c_void>();
8095 if !p.is_null() { *(p as *mut u16) = count as u16; }
8096 }
8097 (b'l', b'n') => {
8098 let p = args.next_arg::<*mut c_void>();
8099 if !p.is_null() { *(p as *mut c_long) = count as c_long; }
8100 }
8101 (b'z', b'n') | (b't', b'n') => {
8102 let p = args.next_arg::<*mut c_void>();
8103 if !p.is_null() { *(p as *mut usize) = count; }
8104 }
8105 (b'j', b'n') => {
8106 let p = args.next_arg::<*mut c_void>();
8107 if !p.is_null() { *(p as *mut c_ulonglong) = count as c_ulonglong; }
8108 }
8109 (b'l', b'd') | (b'l', b'i') => {
8110 let val = args.next_arg::<c_long>();
8111 let neg = val < 0;
8112 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
8113 let b = format_u64(abs);
8114 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8115 let mut fbuf = [0u8; 32];
8116 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8117 ws_buf!(fbuf.as_ptr(), len);
8118 }
8119 (b'l', b'u') => {
8120 let val = args.next_arg::<c_ulong>();
8121 let b = format_u64(val as u64);
8122 let mut fbuf = [0u8; 32];
8123 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8124 ws_buf!(fbuf.as_ptr(), len);
8125 }
8126 (b'l', b's') => {
8127 let p = args.next_arg::<*const wchar_t>();
8128 if p.is_null() {
8129 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
8130 let pad = width.saturating_sub(slen);
8131 if flags & FLAG_MINUS != 0 { ws!(b"(null)".as_ptr(), slen); for _ in 0..pad { wc!(b' '); } }
8132 else { for _ in 0..pad { wc!(b' '); } ws!(b"(null)".as_ptr(), slen); }
8133 } else {
8134 let mut mb = [0u8; 4096];
8135 let mut n = wide_to_mb(mb.as_mut_ptr(), mb.len(), p);
8136 if precision >= 0 && (precision as usize) < n { n = precision as usize; }
8137 let pad = width.saturating_sub(n);
8138 if flags & FLAG_MINUS != 0 { ws!(mb.as_ptr(), n); for _ in 0..pad { wc!(b' '); } }
8139 else { for _ in 0..pad { wc!(b' '); } ws!(mb.as_ptr(), n); }
8140 }
8141 }
8142 (b'l', b'c') => {
8143 let ch = args.next_arg::<c_int>();
8144 let mut mb = [0u8; 8];
8145 let mut st: c_uint = 0;
8146 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, ch, &mut st);
8147 if n != !0usize { ws!(mb.as_ptr(), n); }
8148 }
8149 (b'l', b'x') => {
8150 let val = args.next_arg::<c_ulong>();
8151 let b = format_hex(val as u64, false);
8152 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
8153 let mut fbuf = [0u8; 32];
8154 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8155 ws_buf!(fbuf.as_ptr(), len);
8156 }
8157 (b'l', b'X') => {
8158 let val = args.next_arg::<c_ulong>();
8159 let b = format_hex(val as u64, true);
8160 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
8161 let mut fbuf = [0u8; 32];
8162 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8163 ws_buf!(fbuf.as_ptr(), len);
8164 }
8165 (b'l', b'o') => {
8166 let val = args.next_arg::<c_ulong>();
8167 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
8168 let mut fbuf = [0u8; 32];
8169 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8170 ws_buf!(fbuf.as_ptr(), len);
8171 }
8172 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
8173 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
8174 let val = args.next_arg::<f64>();
8175 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8176 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8177 let mut fbuf = [0u8; 4224];
8178 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8179 let mut wbuf = [0u8; 4224];
8180 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8181 ws_buf!(wbuf.as_ptr(), wlen);
8182 }
8183 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
8184 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
8185 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
8186 let val = {
8187 let lo: u64 = args.next_arg::<u64>();
8188 let hi: u64 = args.next_arg::<u64>();
8189 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
8190 f128::from_bits(combined) as f64
8191 };
8192 #[cfg(target_arch = "x86_64")]
8193 let val = args.next_arg::<f64>();
8194 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8195 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8196 let mut fbuf = [0u8; 4224];
8197 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8198 let mut wbuf = [0u8; 4224];
8199 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8200 ws_buf!(wbuf.as_ptr(), wlen);
8201 }
8202 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
8203 }
8204 }
8205 } else {
8206 spec = *fmt.add(i) as u8;
8207 match spec {
8208 b's' => {
8209 let s = args.next_arg::<*const c_char>();
8210 if s.is_null() {
8211 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
8212 let padded_len = if width > slen { width } else { slen };
8213 let pad = padded_len - slen;
8214 if flags & FLAG_MINUS != 0 {
8215 ws!(b"(null)".as_ptr(), slen);
8216 for _ in 0..pad { wc!(b' '); }
8217 } else {
8218 for _ in 0..pad { wc!(b' '); }
8219 ws!(b"(null)".as_ptr(), slen);
8220 }
8221 } else {
8222 let full_len = strlen(s as *const c_char);
8223 let slen = if precision >= 0 { (precision as usize).min(full_len) } else { full_len };
8224 let padded_len = if width > slen { width } else { slen };
8225 let pad = padded_len - slen;
8226 if flags & FLAG_MINUS != 0 {
8227 ws!(s as *const u8, slen);
8228 for _ in 0..pad { wc!(b' '); }
8229 } else {
8230 for _ in 0..pad { wc!(b' '); }
8231 ws!(s as *const u8, slen);
8232 }
8233 }
8234 }
8235 b'd' | b'i' => {
8236 let d = args.next_arg::<c_int>();
8237 let neg = d < 0;
8238 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
8239 let b = format_u64(abs);
8240 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8241 let mut fbuf = [0u8; 32];
8242 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8243 ws_buf!(fbuf.as_ptr(), len);
8244 }
8245 b'u' => {
8246 let u = args.next_arg::<c_uint>();
8247 let b = format_u64(u as u64);
8248 let mut fbuf = [0u8; 32];
8249 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8250 ws_buf!(fbuf.as_ptr(), len);
8251 }
8252 b'x' => {
8253 let x = args.next_arg::<c_uint>();
8254 let b = format_hex(x as u64, false);
8255 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
8256 let mut fbuf = [0u8; 32];
8257 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8258 ws_buf!(fbuf.as_ptr(), len);
8259 }
8260 b'X' => {
8261 let x = args.next_arg::<c_uint>();
8262 let b = format_hex(x as u64, true);
8263 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
8264 let mut fbuf = [0u8; 32];
8265 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8266 ws_buf!(fbuf.as_ptr(), len);
8267 }
8268 b'o' => {
8269 let o = args.next_arg::<c_uint>();
8270 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
8271 let mut fbuf = [0u8; 32];
8272 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8273 ws_buf!(fbuf.as_ptr(), len);
8274 }
8275 b'c' => {
8276 let ch = args.next_arg::<c_int>();
8277 if width > 1 {
8278 let pad = width - 1;
8279 if flags & FLAG_MINUS != 0 {
8280 wc!(ch as u8);
8281 for _ in 0..pad { wc!(b' '); }
8282 } else {
8283 for _ in 0..pad { wc!(b' '); }
8284 wc!(ch as u8);
8285 }
8286 } else {
8287 wc!(ch as u8);
8288 }
8289 }
8290 b'p' => {
8291 wc!(b'0'); wc!(b'x');
8292 let p = args.next_arg::<*const c_void>();
8293 let b = format_hex(p as u64, false);
8294 ws!(b.0.as_ptr(), b.1);
8295 }
8296 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
8297 let val = args.next_arg::<f64>();
8298 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8299 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8300 let mut fbuf = [0u8; 4224];
8301 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8302 let mut wbuf = [0u8; 4224];
8303 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8304 ws_buf!(wbuf.as_ptr(), wlen);
8305 }
8306 b'%' => { wc!(b'%'); }
8307 b'n' => {
8308 let p = args.next_arg::<*mut c_void>();
8309 if !p.is_null() { *(p as *mut c_int) = count as c_int; }
8310 }
8311 _ => { wc!(b'%'); wc!(spec); }
8312 }
8313 }
8314 i += 1;
8315 }
8316 if cap > 0 { let null_pos = if pos < cap { pos } else { cap - 1 }; *buf.add(null_pos) = 0; }
8317 count as c_int
8318}
8319
8320#[no_mangle]
8321pub unsafe extern "C" fn vsprintf(buf: *mut c_char, fmt: *const c_char, mut args: VaList) -> c_int {
8322 format_to_buf(buf as *mut u8, usize::MAX, fmt, &mut args)
8323}
8324
8325#[no_mangle]
8326pub unsafe extern "C" fn vsnprintf(buf: *mut c_char, size: usize, fmt: *const c_char, mut args: VaList) -> c_int {
8327 format_to_buf(buf as *mut u8, size, fmt, &mut args)
8328}
8329
8330#[no_mangle]
8331pub unsafe extern "C" fn sprintf(buf: *mut c_char, fmt: *const c_char, mut args: ...) -> c_int {
8332 format_to_buf(buf as *mut u8, usize::MAX, fmt, &mut args)
8333}
8334
8335#[no_mangle]
8336pub unsafe extern "C" fn snprintf(buf: *mut c_char, size: usize, fmt: *const c_char, mut args: ...) -> c_int {
8337 format_to_buf(buf as *mut u8, size, fmt, &mut args)
8338}
8339
8340#[no_mangle]
8341pub unsafe extern "C" fn vasprintf(strp: *mut *mut c_char, fmt: *const c_char, ap: VaList) -> c_int {
8342 let len = vsnprintf(core::ptr::null_mut(), 0, fmt, ap.clone());
8343 if len < 0 {
8344 *strp = core::ptr::null_mut();
8345 return -1;
8346 }
8347 let p = malloc((len as usize) + 1) as *mut c_char;
8348 if p.is_null() {
8349 *strp = core::ptr::null_mut();
8350 return -1;
8351 }
8352 let ret = vsnprintf(p, (len as usize) + 1, fmt, ap.clone());
8353 if ret < 0 {
8354 free(p as *mut c_void);
8355 *strp = core::ptr::null_mut();
8356 return -1;
8357 }
8358 *strp = p;
8359 ret
8360}
8361
8362#[no_mangle]
8363pub unsafe extern "C" fn asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int {
8364 vasprintf(strp, fmt, args)
8365}
8366
8367unsafe fn skip_ws(p: *const u8) -> *const u8 {
8372 let mut q = p;
8373 while *q == b' ' || *q == b'\t' || *q == b'\n' || *q == b'\r' { q = q.add(1); }
8374 q
8375}
8376
8377#[inline]
8378fn is_ws_byte(c: u8) -> bool {
8379 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0b || c == 0x0c
8380}
8381
8382unsafe fn scan_int_val(
8385 buf: *const u8, pos: &mut usize, buf_len: usize, base: u32, width: usize,
8386) -> (u64, bool, bool) {
8387 let start = *pos;
8388 let max = if width > 0 { (start + width).min(buf_len) } else { buf_len };
8389 let neg = if *pos < max && *buf.add(*pos) == b'-' { *pos += 1; true }
8390 else if *pos < max && *buf.add(*pos) == b'+' { *pos += 1; false }
8391 else { false };
8392 if *pos >= max { *pos = start; return (0, false, false); }
8393 let mut base = base;
8394 let mut val: u64 = 0;
8395 if (base == 0 || base == 16) && *pos < max && *buf.add(*pos) == b'0' {
8397 *pos += 1;
8398 if *pos < max && (*buf.add(*pos) == b'x' || *buf.add(*pos) == b'X') {
8399 *pos += 1;
8400 if *pos < max {
8401 if let Some(d) = hex_val(*buf.add(*pos)) {
8402 val = d as u64; *pos += 1;
8403 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; } }
8404 return (val, neg, true);
8405 }
8406 }
8407 return (0, neg, false);
8408 } else if base == 0 {
8409 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; } }
8410 return (val, neg, true);
8411 } else {
8412 return (0, neg, true); }
8414 }
8415 if base == 0 { base = 10; }
8416 let mut found = false;
8417 while *pos < max {
8418 let c = *buf.add(*pos);
8419 let d: Option<u64> = match base {
8420 8 => if c >= b'0' && c <= b'7' { Some((c - b'0') as u64) } else { None },
8421 10 => if c >= b'0' && c <= b'9' { Some((c - b'0') as u64) } else { None },
8422 16 => hex_val(c).map(|v| v as u64),
8423 _ => None,
8424 };
8425 match d { Some(digit) => { val = val.wrapping_mul(base as u64).wrapping_add(digit); *pos += 1; found = true; } None => break }
8426 }
8427 if !found { *pos = start; return (0, false, false); }
8428 (val, neg, true)
8429}
8430
8431unsafe fn scan_float_val(
8433 buf: *const u8, pos: &mut usize, buf_len: usize, width: usize,
8434) -> (f64, bool) {
8435 let start = *pos;
8436 let max = if width > 0 { (start + width).min(buf_len) } else { buf_len };
8437 let neg = if *pos < max && *buf.add(*pos) == b'-' { *pos += 1; true }
8438 else if *pos < max && *buf.add(*pos) == b'+' { *pos += 1; false }
8439 else { false };
8440 if *pos + 2 < max {
8442 let (c0,c1,c2) = (*buf.add(*pos), *buf.add(*pos+1), *buf.add(*pos+2));
8443 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); }
8444 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); }
8445 }
8446 if *pos+1 < max && *buf.add(*pos)==b'0' && (*buf.add(*pos+1)==b'x'||*buf.add(*pos+1)==b'X') {
8448 *pos += 2;
8449 let mut val: f64 = 0.0; let mut found = false; let mut frac_scale = 1.0f64; let mut in_frac = false;
8450 while *pos < max {
8451 if let Some(d) = hex_val(*buf.add(*pos)) {
8452 if in_frac { frac_scale /= 16.0; val += d as f64 * frac_scale; } else { val = val * 16.0 + d as f64; }
8453 *pos += 1; found = true;
8454 } else if *buf.add(*pos)==b'.' && !in_frac { in_frac = true; *pos += 1; } else { break; }
8455 }
8456 if !found { *pos = start; return (0.0, false); }
8457 if *pos < max && (*buf.add(*pos)==b'p'||*buf.add(*pos)==b'P') {
8459 *pos += 1;
8460 let mut eneg = false;
8461 if *pos<max && *buf.add(*pos)==b'-' { eneg=true; *pos+=1; }
8462 else if *pos<max && *buf.add(*pos)==b'+' { *pos+=1; }
8463 let mut ev: i32 = 0; let mut ef = false;
8464 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; }
8465 if !ef { return (0.0, false); }
8466 if eneg { ev = -ev; }
8467 val *= libm::pow(2.0, ev as f64);
8468 }
8469 return (if neg{-val}else{val}, true);
8470 }
8471 let token_start = start;
8472 let mut i = start;
8473 let mut saw_digit = false;
8474 let mut saw_dot = false;
8475 let mut saw_exp = false;
8476 let mut first = true;
8477 while i < max {
8478 let c = *buf.add(i);
8479 if (c == b'+' || c == b'-') && first {
8480 i += 1; first = false; continue;
8481 }
8482 if c >= b'0' && c <= b'9' {
8483 saw_digit = true; i += 1; first = false; continue;
8484 }
8485 if c == b'.' && !saw_dot && !saw_exp {
8486 saw_dot = true; i += 1; first = false; continue;
8487 }
8488 if (c == b'e' || c == b'E') && !saw_exp && saw_digit {
8489 saw_exp = true; i += 1; first = true; continue;
8490 }
8491 break;
8492 }
8493 if !saw_digit { return (0.0, false); }
8494 let s = core::str::from_utf8_unchecked(core::slice::from_raw_parts(buf.add(token_start), i - token_start));
8495 match <f64 as core::str::FromStr>::from_str(s) {
8496 Ok(v) => { *pos = i; return (v, true); }
8497 Err(_) => { return (0.0, false); }
8498 }
8499}
8500
8501unsafe fn do_vsscanf(
8504 buf: *const u8, buf_len: usize, fmt: *const c_char, args: &mut VaList<'_>, consumed: *mut usize,
8505) -> c_int {
8506 let mut p = 0usize;
8507 let mut fi = 0usize;
8508 let mut assigned = 0i32;
8509 let mut input_eof = false;
8510 loop {
8511 let fc = *fmt.add(fi) as u8;
8512 if fc == 0 { break; }
8513 if is_ws_byte(fc) {
8514 while is_ws_byte(*fmt.add(fi) as u8) { fi += 1; }
8515 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8516 continue;
8517 }
8518 if fc != b'%' {
8519 if p >= buf_len { input_eof = true; break; }
8520 if *buf.add(p) != fc { break; }
8521 p += 1; fi += 1; continue;
8522 }
8523 fi += 1;
8524 if *fmt.add(fi) as u8 == b'%' {
8526 if p >= buf_len { input_eof = true; break; }
8527 if *buf.add(p) != b'%' { break; }
8528 p += 1; fi += 1; continue;
8529 }
8530 let suppress = if *fmt.add(fi) as u8 == b'*' { fi += 1; true } else { false };
8531 let mut width: usize = 0;
8532 while (*fmt.add(fi) as u8) >= b'0' && (*fmt.add(fi) as u8) <= b'9' {
8533 width = width * 10 + ((*fmt.add(fi) as u8) - b'0') as usize; fi += 1;
8534 }
8535 if *fmt.add(fi) as u8 == b'm' { fi += 1; }
8536 let mut len_mod = 0u8;
8537 match *fmt.add(fi) as u8 {
8538 b'h' => { fi += 1; if *fmt.add(fi) as u8 == b'h' { fi += 1; len_mod = 2; } else { len_mod = 1; } }
8539 b'l' => { fi += 1; if *fmt.add(fi) as u8 == b'l' { fi += 1; len_mod = 4; } else { len_mod = 3; } }
8540 b'j' => { fi += 1; len_mod = 4; }
8541 b'z' | b't' => { fi += 1; len_mod = 3; }
8542 b'L' => { fi += 1; len_mod = 5; }
8543 _ => {}
8544 }
8545 let spec = *fmt.add(fi) as u8;
8546 let (real_spec, _real_len) = if spec==b'C' {(b'c',3u8)} else if spec==b'S' {(b's',3u8)} else {(spec,len_mod)};
8547 match real_spec {
8548 b'n' => {
8549 if !suppress { let out = args.next_arg::<*mut c_int>(); if !out.is_null() { *out = p as c_int; } }
8550 }
8551 b'd' | b'u' => {
8552 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8553 if p >= buf_len { input_eof = true; break; }
8554 let dest = if !suppress { Some(args.next_arg::<*mut c_int>()) } else { None };
8555 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 10, width);
8556 if !ok { break; }
8557 if let Some(out) = dest { if !out.is_null() {
8558 *out = if real_spec==b'd' && neg { -(val as i64) as c_int } else { val as c_int };
8559 }}
8560 if !suppress { assigned += 1; }
8561 }
8562 b'i' => {
8563 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8564 if p >= buf_len { input_eof = true; break; }
8565 let dest = if !suppress { Some(args.next_arg::<*mut c_int>()) } else { None };
8566 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 0, width);
8567 if !ok { break; }
8568 if let Some(out) = dest { if !out.is_null() { *out = if neg { -(val as i64) as c_int } else { val as c_int }; } }
8569 if !suppress { assigned += 1; }
8570 }
8571 b'o' => {
8572 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8573 if p >= buf_len { input_eof = true; break; }
8574 let dest = if !suppress { Some(args.next_arg::<*mut c_int>()) } else { None };
8575 let (val, _, ok) = scan_int_val(buf, &mut p, buf_len, 8, width);
8576 if !ok { break; }
8577 if let Some(out) = dest { if !out.is_null() { *out = val as c_int; } }
8578 if !suppress { assigned += 1; }
8579 }
8580 b'x' | b'X' => {
8581 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8582 if p >= buf_len { input_eof = true; break; }
8583 let dest = if !suppress { Some(args.next_arg::<*mut c_int>()) } else { None };
8584 let (val, _, ok) = scan_int_val(buf, &mut p, buf_len, 16, width);
8585 if !ok { break; }
8586 if let Some(out) = dest { if !out.is_null() { *out = val as c_int; } }
8587 if !suppress { assigned += 1; }
8588 }
8589 b'p' => {
8590 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8591 if p >= buf_len { input_eof = true; break; }
8592 let dest = if !suppress { Some(args.next_arg::<*mut *mut c_void>()) } else { None };
8593 let (val, _, ok) = scan_int_val(buf, &mut p, buf_len, 16, width);
8594 if !ok { break; }
8595 if let Some(out) = dest { if !out.is_null() { *out = val as usize as *mut c_void; } }
8596 if !suppress { assigned += 1; }
8597 }
8598 b'a' | b'e' | b'f' | b'g' | b'A' | b'E' | b'F' | b'G' => {
8599 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8600 if p >= buf_len { input_eof = true; break; }
8601 let (val, ok) = scan_float_val(buf, &mut p, buf_len, width);
8602 if !ok { break; }
8603 if !suppress {
8604 if _real_len == 3 {
8605 let out = args.next_arg::<*mut f64>(); if !out.is_null() { *out = val; }
8606 } else if _real_len == 5 {
8607 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
8608 { let out = args.next_arg::<*mut f128>(); if !out.is_null() { *out = val as f128; } }
8609 #[cfg(target_arch = "x86_64")]
8610 { let out = args.next_arg::<*mut f64>(); if !out.is_null() { *out = val; } }
8611 } else {
8612 let out = args.next_arg::<*mut f32>(); if !out.is_null() { *out = val as f32; }
8613 }
8614 }
8615 if !suppress { assigned += 1; }
8616 }
8617 b'c' => {
8618 let w = if width > 0 { width } else { 1 };
8619 if p >= buf_len { input_eof = true; break; }
8620 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8621 let start_p = p;
8622 let mut j = 0usize;
8623 while j < w && p < buf_len {
8624 if !dest_ptr.is_null() { *dest_ptr.add(j) = *buf.add(p) as c_char; }
8625 p += 1; j += 1;
8626 }
8627 if j != w { p = start_p; input_eof = true; break; }
8628 if !suppress { assigned += 1; }
8629 }
8630 b's' => {
8631 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8632 if p >= buf_len { input_eof = true; break; }
8633 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8634 let w = if width > 0 { width } else { usize::MAX };
8635 let mut j = 0usize;
8636 while p < buf_len && *buf.add(p) != 0 && !is_ws_byte(*buf.add(p)) && j < w {
8637 if !dest_ptr.is_null() { *dest_ptr.add(j) = *buf.add(p) as c_char; }
8638 p += 1; j += 1;
8639 }
8640 if j == 0 { break; }
8641 if !dest_ptr.is_null() { *dest_ptr.add(j) = 0; }
8642 if !suppress { assigned += 1; }
8643 }
8644 b'[' => {
8645 fi += 1;
8646 let negate = if *fmt.add(fi) as u8 == b'^' { fi += 1; true } else { false };
8647 let mut charset = [0u8; 256];
8648 if *fmt.add(fi) as u8 == b']' { charset[b']' as usize] = 1; fi += 1; }
8649 loop { let c = *fmt.add(fi) as u8; if c == b']' || c == 0 { break; } charset[c as usize] = 1; fi += 1; }
8650 if *fmt.add(fi) as u8 == b']' { fi += 1; }
8651 fi -= 1; if p >= buf_len { input_eof = true; break; }
8653 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8654 let w = if width > 0 { width } else { usize::MAX };
8655 let mut j = 0usize;
8656 while p < buf_len && *buf.add(p) != 0 && j < w {
8657 let c = *buf.add(p);
8658 let in_set = charset[c as usize] != 0;
8659 if negate { if in_set { break; } } else { if !in_set { break; } }
8660 if !dest_ptr.is_null() { *dest_ptr.add(j) = c as c_char; }
8661 p += 1; j += 1;
8662 }
8663 if j == 0 { break; }
8664 if !dest_ptr.is_null() { *dest_ptr.add(j) = 0; }
8665 if !suppress { assigned += 1; }
8666 }
8667 _ => break,
8668 }
8669 fi += 1;
8670 }
8671 if !consumed.is_null() { *consumed = p; }
8672 if assigned == 0 && input_eof { -1 } else { assigned }
8673}
8674
8675unsafe fn vsscanf_inner(buf: *const u8, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
8676 let len = strlen(buf as *const c_char);
8677 do_vsscanf(buf, len, fmt, args, core::ptr::null_mut())
8678}
8679
8680#[no_mangle]
8681pub unsafe extern "C" fn vsscanf(buf: *const c_char, fmt: *const c_char, mut args: VaList) -> c_int {
8682 vsscanf_inner(buf as *const u8, fmt, &mut args)
8683}
8684
8685#[no_mangle]
8686pub unsafe extern "C" fn vfscanf(stream: *mut FILE, fmt: *const c_char, mut args: VaList) -> c_int {
8687 let f = &mut *stream;
8688 let start_ungotten_count = f.ungotten_count as usize;
8689 let sfunc = f.seek_fn;
8690 let start_pos = sfunc.map(|s| s(stream, 0, SEEK_CUR)).unwrap_or(-1);
8691
8692 let mut line = [0u8; 4096];
8693 let mut pos = 0usize;
8694
8695 if start_pos >= 0 {
8696 while pos < line.len() - 1 {
8698 let c = fgetc(stream);
8699 if c == -1 { break; }
8700 line[pos] = c as u8;
8701 pos += 1;
8702 if c == b'\n' as c_int { break; }
8703 }
8704 } else {
8705 while f.ungotten_count > 0 && pos < line.len() - 1 {
8710 f.ungotten_count -= 1;
8711 line[pos] = f.ungotten[f.ungotten_count as usize] as u8;
8712 pos += 1;
8713 }
8714 while !f.rpos.is_null() && f.rpos < f.rend && pos < line.len() - 1 {
8716 line[pos] = *f.rpos;
8717 f.rpos = f.rpos.add(1);
8718 pos += 1;
8719 }
8720 let fd = f.fd;
8722 let old_flags = sys_fcntl(fd, F_GETFL, 0);
8723 if old_flags >= 0 {
8724 let _ = sys_fcntl(fd, F_SETFL, old_flags | O_NONBLOCK as i64);
8725 }
8726 while pos < line.len() - 1 {
8727 let n = sys_read(fd as i64, line.as_mut_ptr().add(pos), line.len() - 1 - pos);
8728 if n <= 0 { break; }
8729 pos += n as usize;
8730 }
8731 if old_flags >= 0 {
8732 let _ = sys_fcntl(fd, F_SETFL, old_flags);
8733 }
8734 f._eof = 0;
8736 f._err = 0;
8737 f.flags &= !(F_EOF | F_ERR);
8738 }
8739
8740 line[pos] = 0;
8741 if pos == 0 { return 0; }
8742
8743 let mut consumed = 0usize;
8744 let assigned = do_vsscanf(line.as_ptr(), pos, fmt, &mut args, &mut consumed);
8745
8746 if start_pos >= 0 {
8747 let file_consumed = consumed.saturating_sub(start_ungotten_count);
8749 let target = start_pos + file_consumed as i64;
8750 if let Some(sfunc) = sfunc {
8751 sfunc(stream, target, SEEK_SET);
8752 }
8753 f.rpos = core::ptr::null_mut();
8754 f.rend = core::ptr::null_mut();
8755 if consumed < pos { f._eof = 0; }
8756 let remaining = start_ungotten_count.saturating_sub(consumed);
8757 f.ungotten_count = remaining as c_int;
8758 } else {
8759 let unconsumed = pos.saturating_sub(consumed);
8761 if unconsumed > 0 && !f.buf.is_null() {
8762 let copy_count = core::cmp::min(unconsumed, f.buf_size);
8763 core::ptr::copy(
8764 line.as_ptr().add(consumed),
8765 f.buf,
8766 copy_count,
8767 );
8768 f.rpos = f.buf;
8769 f.rend = f.buf.add(copy_count);
8770 }
8771 f.ungotten_count = 0;
8772 f._eof = 0;
8773 f.flags &= !F_EOF;
8774 }
8775 assigned
8776}
8777
8778#[no_mangle]
8779pub unsafe extern "C" fn vscanf(fmt: *const c_char, args: VaList) -> c_int {
8780 vfscanf(stdin, fmt, args)
8781}
8782
8783#[no_mangle]
8784pub unsafe extern "C" fn sscanf(buf: *const c_char, fmt: *const c_char, mut args: ...) -> c_int {
8785 vsscanf_inner(buf as *const u8, fmt, &mut args)
8786}
8787
8788#[no_mangle]
8789pub unsafe extern "C" fn fscanf(stream: *mut FILE, fmt: *const c_char, args: ...) -> c_int {
8790 vfscanf(stream, fmt, args)
8791}
8792
8793#[no_mangle]
8794pub unsafe extern "C" fn scanf(fmt: *const c_char, args: ...) -> c_int {
8795 vfscanf(stdin, fmt, args)
8796}
8797
8798#[no_mangle]
8803pub unsafe extern "C" fn getdelim(
8804 lineptr: *mut *mut c_char, n: *mut usize, delim: c_int, stream: *mut FILE,
8805) -> isize {
8806 if lineptr.is_null() || n.is_null() { return -1; }
8807 let mut cap = *n;
8808 let mut buf = *lineptr;
8809 if buf.is_null() || cap == 0 {
8810 cap = 128;
8811 buf = realloc(buf as *mut c_void, cap) as *mut c_char;
8812 if buf.is_null() { return -1; }
8813 *lineptr = buf;
8814 *n = cap;
8815 }
8816 let mut len = 0usize;
8817 loop {
8818 let c = fgetc(stream);
8819 if c == -1 { if len == 0 { return -1; } break; }
8820 if len + 1 >= cap {
8821 let new_cap = cap.wrapping_mul(2);
8822 let new_buf = realloc(buf as *mut c_void, new_cap) as *mut c_char;
8823 if new_buf.is_null() { return -1; }
8824 buf = new_buf; cap = new_cap;
8825 *lineptr = buf; *n = cap;
8826 }
8827 *buf.add(len) = c as c_char;
8828 len += 1;
8829 if c == delim { break; }
8830 }
8831 *buf.add(len) = 0;
8832 len as isize
8833}
8834
8835#[no_mangle]
8836pub unsafe extern "C" fn getline(lineptr: *mut *mut c_char, n: *mut usize, stream: *mut FILE) -> isize {
8837 getdelim(lineptr, n, b'\n' as c_int, stream)
8838}
8839
8840#[no_mangle]
8845pub unsafe extern "C" fn popen(cmd: *const c_char, mode: *const c_char) -> *mut FILE {
8846 if cmd.is_null() || mode.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
8847 let m = *mode;
8848 if m != b'r' as c_char && m != b'w' as c_char { ERRNO = EINVAL; return core::ptr::null_mut(); }
8849 let mut p: [c_int; 2] = [0; 2];
8850 if sys_pipe2(p.as_mut_ptr(), O_CLOEXEC) < 0 { return core::ptr::null_mut(); }
8851 let op = if m == b'r' as c_char { 0 } else { 1 };
8852 let child_fd = p[1 - op];
8853 let f = fdopen(p[op], mode);
8854 if f.is_null() { sys_close(p[0] as i64); sys_close(p[1] as i64); return core::ptr::null_mut(); }
8855 let pid = sys_fork();
8856 if pid < 0 { fclose(f); sys_close(child_fd as i64); return core::ptr::null_mut(); }
8857 if pid == 0 {
8858 sys_close(p[op] as i64);
8859 if child_fd != (1 - op) as c_int { sys_dup3(child_fd, (1 - op) as c_int, 0); sys_close(child_fd as i64); }
8860 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
8861 let argv = [b"sh\0".as_ptr() as *const c_char, b"-c\0".as_ptr() as *const c_char, cmd, core::ptr::null()];
8862 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
8863 _exit(127);
8864 }
8865 sys_close(child_fd as i64);
8866 (*f).pipe_pid = pid as c_int;
8867 f
8868}
8869
8870#[no_mangle]
8871pub unsafe extern "C" fn pclose(f: *mut FILE) -> c_int {
8872 let pid = (*f).pipe_pid;
8873 let r = fclose(f);
8874 if pid <= 0 { return -1; }
8875 let mut status: c_int = 0;
8876 let mut w: c_int;
8877 loop {
8878 w = waitpid(pid, &mut status, 0);
8879 if w >= 0 || w != -EINTR { break; }
8880 }
8881 if w < 0 || r != 0 { return -1; }
8882 status
8883}
8884
8885const L_TMPNAM: usize = 20;
8890static mut TMPNAM_COUNTER: c_uint = 0;
8891
8892unsafe fn fill_tmpname(out: *mut c_char, seed: c_uint) {
8893 let prefix = b"/tmp/tmp\0";
8894 let mut k = 0;
8895 while k < prefix.len() - 1 { *out.add(k) = prefix[k] as c_char; k += 1; }
8896 let (buf, len) = format_hex(seed as u64, false);
8897 for j in 0..len.min(L_TMPNAM - k - 1) { *out.add(k + j) = buf[j] as c_char; k += 1; }
8898 *out.add(k) = 0;
8899}
8900
8901#[no_mangle]
8902pub unsafe extern "C" fn tmpfile() -> *mut FILE {
8903 let mut name = [0u8; L_TMPNAM];
8904 let mut ctr: c_uint = 0;
8905 loop {
8906 ctr = ctr.wrapping_add(1);
8907 let mut ts: timespec = core::mem::zeroed();
8908 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
8909 let seed = (ts.tv_nsec as c_uint).wrapping_add(ctr);
8910 fill_tmpname(name.as_mut_ptr() as *mut c_char, seed);
8911 let fd = sys_open(name.as_ptr(), (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
8912 if fd >= 0 {
8913 sys_unlinkat(AT_FDCWD, name.as_ptr(), 0);
8914 let f = fdopen(fd as c_int, b"w+\0".as_ptr() as *const c_char);
8915 if f.is_null() { sys_close(fd); }
8916 return f;
8917 }
8918 if ctr > 100 { return core::ptr::null_mut(); }
8919 }
8920}
8921
8922#[no_mangle]
8923pub unsafe extern "C" fn tmpnam(s: *mut c_char) -> *mut c_char {
8924 static mut BUF: [c_char; L_TMPNAM] = [0; L_TMPNAM];
8925 let out = if s.is_null() { core::ptr::addr_of_mut!(BUF) as *mut c_char } else { s };
8926 TMPNAM_COUNTER = TMPNAM_COUNTER.wrapping_add(1);
8927 let mut ts: timespec = core::mem::zeroed();
8928 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
8929 let seed = (ts.tv_nsec as c_uint).wrapping_add(TMPNAM_COUNTER);
8930 fill_tmpname(out, seed);
8931 out
8932}
8933
8934#[no_mangle]
8935pub unsafe extern "C" fn remove(path: *const c_char) -> c_int {
8936 if path.is_null() { ERRNO = EINVAL; return -1; }
8937 let r = sys_unlinkat(AT_FDCWD, path as *const u8, 0);
8938 if r == 0 { 0 } else { ERRNO = (-r) as c_int; -1 }
8939}
8940
8941#[no_mangle]
8942pub unsafe extern "C" fn rename(old: *const c_char, new_: *const c_char) -> c_int {
8943 if old.is_null() || new_.is_null() { ERRNO = EINVAL; return -1; }
8944 let r = sys_renameat2(AT_FDCWD, old as *const u8, AT_FDCWD, new_ as *const u8, 0);
8945 if r == 0 { 0 } else { ERRNO = (-r) as c_int; -1 }
8946}
8947
8948const MMAP_FAILED: *mut u8 = !0usize as *mut u8;
8954const PAGE: usize = 4096;
8955
8956#[no_mangle]
8957pub unsafe extern "C" fn malloc(size: SizeT) -> *mut c_void {
8958 let alloc_size = if size == 0 { 1 } else { size };
8961 let total = alloc_size + core::mem::size_of::<usize>();
8963 let pages = (total + PAGE - 1) & !(PAGE - 1);
8964 let ptr = sys_mmap(
8965 null_mut(),
8966 pages,
8967 PROT_READ | PROT_WRITE,
8968 MAP_PRIVATE | MAP_ANONYMOUS,
8969 -1,
8970 0,
8971 );
8972 if ptr == MMAP_FAILED {
8973 return null_mut();
8974 }
8975 *(ptr as *mut usize) = pages;
8976 ptr.add(core::mem::size_of::<usize>()) as *mut c_void
8977}
8978
8979#[no_mangle]
8980pub unsafe extern "C" fn free(ptr: *mut c_void) {
8981 if ptr.is_null() {
8982 return;
8983 }
8984 let header = (ptr as *mut u8).sub(core::mem::size_of::<usize>());
8985 let pages = *(header as *const usize);
8986 sys_munmap(header, pages);
8987}
8988
8989#[no_mangle]
8990pub unsafe extern "C" fn calloc(count: SizeT, size: SizeT) -> *mut c_void {
8991 let total = count.saturating_mul(size);
8992 let ptr = malloc(total);
8993 if !ptr.is_null() {
8994 core::ptr::write_bytes(ptr as *mut u8, 0, total);
8995 }
8996 ptr
8997}
8998
8999#[no_mangle]
9000pub unsafe extern "C" fn realloc(ptr: *mut c_void, new_size: SizeT) -> *mut c_void {
9001 if ptr.is_null() {
9002 return malloc(new_size);
9003 }
9004 if new_size == 0 {
9005 free(ptr);
9006 return null_mut();
9007 }
9008 let header = (ptr as *mut u8).sub(core::mem::size_of::<usize>());
9009 let old_pages = *(header as *const usize);
9010 let old_data_size = old_pages - core::mem::size_of::<usize>();
9011 let new_ptr = malloc(new_size);
9012 if new_ptr.is_null() {
9013 return null_mut();
9014 }
9015 let copy_size = if old_data_size < new_size {
9016 old_data_size
9017 } else {
9018 new_size
9019 };
9020 core::ptr::copy_nonoverlapping(ptr as *const u8, new_ptr as *mut u8, copy_size);
9021 free(ptr);
9022 new_ptr
9023}
9024
9025#[no_mangle]
9030pub unsafe extern "C" fn _exit(code: c_int) -> ! {
9031 sys_exit_group(code)
9032}
9033
9034#[inline]
9035unsafe fn sys_exit_group(code: c_int) -> ! {
9036 <Arch as Syscalls>::syscall_noreturn1(SYS_EXIT_GROUP, code as i64)
9037}
9038
9039#[inline]
9040unsafe fn sys_exit_thread(code: c_int) -> ! {
9041 <Arch as Syscalls>::syscall_noreturn1(SYS_EXIT, code as i64)
9042}
9043
9044#[no_mangle]
9045pub unsafe extern "C" fn _Exit(code: c_int) -> ! {
9046 _exit(code);
9047}
9048
9049#[no_mangle]
9050pub unsafe extern "C" fn exit(code: c_int) -> ! {
9051 fflush(core::ptr::null_mut());
9052 __funcs_on_exit();
9053 _exit(code);
9054}
9055
9056#[no_mangle]
9057pub unsafe extern "C" fn abort() -> ! {
9058 raise(6); _exit(128 + 6);
9060}
9061
9062#[no_mangle]
9065pub static mut __stack_chk_guard: usize = 0;
9066
9067#[no_mangle]
9068pub unsafe extern "C" fn __stack_chk_fail() -> ! {
9069 const MSG: &[u8] = b"*** stack smashing detected ***: terminated\n";
9070 let _ = sys_write(2, MSG.as_ptr(), MSG.len());
9071 abort();
9072}
9073
9074type CmpRfn = unsafe extern "C" fn(*const c_void, *const c_void, *mut c_void) -> c_int;
9079
9080const AR_LEN: usize = 16 * core::mem::size_of::<usize>();
9081const AR_MASK: usize = AR_LEN - 1;
9082
9083unsafe fn qsort_pntz(p: &[usize; 2]) -> i32 {
9084 if p[0] != 1 {
9085 p[0].wrapping_sub(1).trailing_zeros() as i32
9086 } else if p[1] != 0 {
9087 (8 * core::mem::size_of::<usize>()) as i32 + p[1].trailing_zeros() as i32
9088 } else {
9089 0
9090 }
9091}
9092
9093unsafe fn qsort_cycle(width: usize, ar: &mut [*mut u8; AR_LEN], n: usize) {
9094 if n < 2 { return; }
9095 let mut tmp = [0u8; 256];
9096 ar[n] = tmp.as_mut_ptr();
9097 let mut w = width;
9098 while w > 0 {
9099 let l = if 256 < w { 256 } else { w };
9100 core::ptr::copy_nonoverlapping(ar[0], ar[n], l);
9101 for i in 0..n {
9102 core::ptr::copy_nonoverlapping(ar[i + 1], ar[i], l);
9103 ar[i] = ar[i].add(l);
9104 }
9105 w -= l;
9106 }
9107}
9108
9109unsafe fn qsort_shl(p: &mut [usize; 2], n: i32) {
9110 let bits = (8 * core::mem::size_of::<usize>()) as i32;
9111 if n >= bits {
9112 p[1] = p[0];
9113 p[0] = 0;
9114 let n = n - bits;
9115 if n == 0 { return; }
9116 }
9117 p[1] = (p[1] << n) | (p[0] >> (bits - n));
9118 p[0] <<= n;
9119}
9120
9121unsafe fn qsort_shr(p: &mut [usize; 2], n: i32) {
9122 let bits = (8 * core::mem::size_of::<usize>()) as i32;
9123 if n >= bits {
9124 p[0] = p[1];
9125 p[1] = 0;
9126 let n = n - bits;
9127 if n == 0 { return; }
9128 }
9129 p[0] = (p[0] >> n) | (p[1] << (bits - n));
9130 p[1] >>= n;
9131}
9132
9133unsafe fn qsort_sift(
9134 head: *mut u8, width: usize,
9135 cmp: CmpRfn, arg: *mut c_void,
9136 pshift: i32, lp: &[usize],
9137) {
9138 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
9139 ar[0] = head;
9140 let mut i = 1usize;
9141 let mut h = head;
9142 let mut ps = pshift;
9143
9144 while ps > 1 {
9145 let rt = h.sub(width);
9146 let lf = h.sub(width + lp[(ps - 2) as usize]);
9147
9148 if cmp(ar[0] as *const c_void, lf as *const c_void, arg) >= 0
9149 && cmp(ar[0] as *const c_void, rt as *const c_void, arg) >= 0
9150 {
9151 break;
9152 }
9153 if cmp(lf as *const c_void, rt as *const c_void, arg) >= 0 {
9154 ar[i & AR_MASK] = lf;
9155 i += 1;
9156 h = lf;
9157 ps -= 1;
9158 } else {
9159 ar[i & AR_MASK] = rt;
9160 i += 1;
9161 h = rt;
9162 ps -= 2;
9163 }
9164 }
9165 qsort_cycle(width, &mut ar, i & AR_MASK);
9166}
9167
9168unsafe fn qsort_trinkle(
9169 head: *mut u8, width: usize,
9170 cmp: CmpRfn, arg: *mut c_void,
9171 pp: &[usize; 2], pshift: i32, trusty: i32,
9172 lp: &[usize],
9173) {
9174 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
9175 let mut p = *pp;
9176 ar[0] = head;
9177 let mut i = 1usize;
9178 let mut h = head;
9179 let mut ps = pshift;
9180 let mut t = trusty;
9181
9182 while p[0] != 1 || p[1] != 0 {
9183 let stepson = h.sub(lp[ps as usize]);
9184 if cmp(stepson as *const c_void, ar[0] as *const c_void, arg) <= 0 {
9185 break;
9186 }
9187 if t == 0 && ps > 1 {
9188 let rt = h.sub(width);
9189 let lf = h.sub(width + lp[(ps - 2) as usize]);
9190 if cmp(rt as *const c_void, stepson as *const c_void, arg) >= 0
9191 || cmp(lf as *const c_void, stepson as *const c_void, arg) >= 0
9192 {
9193 break;
9194 }
9195 }
9196
9197 ar[i & AR_MASK] = stepson;
9198 i += 1;
9199 h = stepson;
9200 let trail = qsort_pntz(&p);
9201 qsort_shr(&mut p, trail);
9202 ps += trail;
9203 t = 0;
9204 }
9205 if t == 0 {
9206 qsort_cycle(width, &mut ar, i & AR_MASK);
9207 qsort_sift(h, width, cmp, arg, ps, lp);
9208 }
9209}
9210
9211#[no_mangle]
9212pub unsafe extern "C" fn __qsort_r(
9213 base: *mut c_void,
9214 nel: usize,
9215 width: usize,
9216 cmp: CmpRfn,
9217 arg: *mut c_void,
9218) {
9219 let size = width * nel;
9220 if size == 0 { return; }
9221
9222 let mut lp = [0usize; 96];
9223 lp[0] = width;
9224 lp[1] = width;
9225 let mut li = 2;
9226 while {
9227 lp[li] = lp[li - 2] + lp[li - 1] + width;
9228 lp[li] < size
9229 } {
9230 li += 1;
9231 }
9232
9233 let mut head = base as *mut u8;
9234 let high = head.add(size - width);
9235 let mut p: [usize; 2] = [1, 0];
9236 let mut pshift: i32 = 1;
9237
9238 while head < high {
9239 if (p[0] & 3) == 3 {
9240 qsort_sift(head, width, cmp, arg, pshift, &lp);
9241 qsort_shr(&mut p, 2);
9242 pshift += 2;
9243 } else {
9244 if lp[(pshift - 1) as usize] >= (high as usize) - (head as usize) {
9245 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
9246 } else {
9247 qsort_sift(head, width, cmp, arg, pshift, &lp);
9248 }
9249
9250 if pshift == 1 {
9251 qsort_shl(&mut p, 1);
9252 pshift = 0;
9253 } else {
9254 qsort_shl(&mut p, pshift - 1);
9255 pshift = 1;
9256 }
9257 }
9258
9259 p[0] |= 1;
9260 head = head.add(width);
9261 }
9262
9263 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
9264
9265 while pshift != 1 || p[0] != 1 || p[1] != 0 {
9266 if pshift <= 1 {
9267 let trail = qsort_pntz(&p);
9268 qsort_shr(&mut p, trail);
9269 pshift += trail;
9270 } else {
9271 qsort_shl(&mut p, 2);
9272 pshift -= 2;
9273 p[0] ^= 7;
9274 qsort_shr(&mut p, 1);
9275 qsort_trinkle(
9276 head.sub(lp[pshift as usize] + width),
9277 width, cmp, arg, &p, pshift + 1, 1, &lp,
9278 );
9279 qsort_shl(&mut p, 1);
9280 p[0] |= 1;
9281 qsort_trinkle(head.sub(width), width, cmp, arg, &p, pshift, 1, &lp);
9282 }
9283 head = head.sub(width);
9284 }
9285}
9286
9287#[no_mangle]
9288pub unsafe extern "C" fn qsort_r(
9289 base: *mut c_void,
9290 nel: usize,
9291 width: usize,
9292 cmp: CmpRfn,
9293 arg: *mut c_void,
9294) {
9295 __qsort_r(base, nel, width, cmp, arg);
9296}
9297
9298unsafe extern "C" fn qsort_wrap_cmp(
9299 a: *const c_void,
9300 b: *const c_void,
9301 cmp_ctx: *mut c_void,
9302) -> c_int {
9303 let cmp: CmpFn = core::mem::transmute(cmp_ctx);
9304 cmp(a, b)
9305}
9306
9307#[no_mangle]
9308pub unsafe extern "C" fn qsort(
9309 base: *mut c_void,
9310 nel: usize,
9311 width: usize,
9312 cmp: CmpFn,
9313) {
9314 __qsort_r(base, nel, width, qsort_wrap_cmp, cmp as *mut c_void);
9315}
9316
9317const ATEXIT_COUNT: usize = 32;
9322
9323#[repr(C)]
9324struct AtExitBlock {
9325 next: *mut AtExitBlock,
9326 f: [Option<unsafe extern "C" fn(*mut c_void)>; ATEXIT_COUNT],
9327 a: [*mut c_void; ATEXIT_COUNT],
9328}
9329
9330static mut ATEXIT_BUILTIN: AtExitBlock = AtExitBlock {
9331 next: core::ptr::null_mut(),
9332 f: [None; ATEXIT_COUNT],
9333 a: [core::ptr::null_mut(); ATEXIT_COUNT],
9334};
9335static mut ATEXIT_HEAD: *mut AtExitBlock = core::ptr::null_mut();
9336static mut ATEXIT_SLOT: usize = 0;
9337static mut ATEXIT_FINISHED: bool = false;
9338
9339#[no_mangle]
9340pub unsafe extern "C" fn __funcs_on_exit() {
9341 while !ATEXIT_HEAD.is_null() {
9342 let head = ATEXIT_HEAD;
9343 while ATEXIT_SLOT > 0 {
9344 ATEXIT_SLOT -= 1;
9345 if let Some(f) = (*head).f[ATEXIT_SLOT] {
9346 let a = (*head).a[ATEXIT_SLOT];
9347 f(a);
9348 }
9349 }
9350 ATEXIT_HEAD = (*head).next;
9351 ATEXIT_SLOT = ATEXIT_COUNT;
9352 }
9353 ATEXIT_FINISHED = true;
9354}
9355
9356#[no_mangle]
9357pub unsafe extern "C" fn __cxa_atexit(
9358 func: unsafe extern "C" fn(*mut c_void),
9359 arg: *mut c_void,
9360 _dso: *mut c_void,
9361) -> c_int {
9362 if ATEXIT_FINISHED {
9363 return -1;
9364 }
9365 if ATEXIT_HEAD.is_null() {
9366 ATEXIT_HEAD = core::ptr::addr_of_mut!(ATEXIT_BUILTIN);
9367 }
9368 if ATEXIT_SLOT == ATEXIT_COUNT {
9369 let new = calloc(1, core::mem::size_of::<AtExitBlock>()) as *mut AtExitBlock;
9370 if new.is_null() {
9371 return -1;
9372 }
9373 (*new).next = ATEXIT_HEAD;
9374 ATEXIT_HEAD = new;
9375 ATEXIT_SLOT = 0;
9376 }
9377 (*ATEXIT_HEAD).f[ATEXIT_SLOT] = Some(func);
9378 (*ATEXIT_HEAD).a[ATEXIT_SLOT] = arg;
9379 ATEXIT_SLOT += 1;
9380 0
9381}
9382
9383unsafe extern "C" fn atexit_caller(arg: *mut c_void) {
9384 let func: unsafe extern "C" fn() = core::mem::transmute(arg);
9385 func();
9386}
9387
9388#[no_mangle]
9389pub unsafe extern "C" fn atexit(func: unsafe extern "C" fn()) -> c_int {
9390 __cxa_atexit(atexit_caller, func as *mut c_void, core::ptr::null_mut())
9391}
9392
9393#[no_mangle]
9394pub unsafe extern "C" fn __cxa_finalize(_dso: *mut c_void) {}
9395
9396#[no_mangle]
9401pub static mut __environ: *mut *mut c_char = core::ptr::null_mut();
9402
9403const ENV_MAX_ALLOCED: usize = 256;
9405static mut ENV_ALLOCED: [*mut c_char; ENV_MAX_ALLOCED] = [core::ptr::null_mut(); ENV_MAX_ALLOCED];
9406static mut ENV_ALLOCED_N: usize = 0;
9407
9408unsafe fn env_rm_add(old: *mut c_char, mut new: *mut c_char) {
9409 for i in 0..ENV_ALLOCED_N {
9410 if ENV_ALLOCED[i] == old {
9411 ENV_ALLOCED[i] = new;
9412 if !old.is_null() {
9413 free(old as *mut c_void);
9414 }
9415 return;
9416 } else if ENV_ALLOCED[i].is_null() && !new.is_null() {
9417 ENV_ALLOCED[i] = new;
9418 new = core::ptr::null_mut();
9419 }
9420 }
9421 if !new.is_null() && ENV_ALLOCED_N < ENV_MAX_ALLOCED {
9422 ENV_ALLOCED[ENV_ALLOCED_N] = new;
9423 ENV_ALLOCED_N += 1;
9424 }
9425}
9426
9427unsafe fn strchrnul_u8(s: *const u8, c: u8) -> *const u8 {
9428 let mut p = s;
9429 while *p != 0 && *p != c {
9430 p = p.add(1);
9431 }
9432 p
9433}
9434
9435#[no_mangle]
9436pub unsafe extern "C" fn getenv(name: *const c_char) -> *mut c_char {
9437 if __environ.is_null() || name.is_null() {
9438 return core::ptr::null_mut();
9439 }
9440 let name = name as *const u8;
9441 let l = strchrnul_u8(name, b'=') as usize - name as usize;
9442 if l == 0 || *name.add(l) != 0 {
9443 return core::ptr::null_mut();
9444 }
9445 let mut e = __environ;
9446 while !(*e).is_null() {
9447 let entry = *e as *const u8;
9448 if strncmp(entry, name, l) == 0 && *entry.add(l) == b'=' {
9449 return entry.add(l + 1) as *mut c_char;
9450 }
9451 e = e.add(1);
9452 }
9453 core::ptr::null_mut()
9454}
9455
9456#[no_mangle]
9457pub unsafe extern "C" fn setenv(
9458 var: *const c_char,
9459 value: *const c_char,
9460 overwrite: c_int,
9461) -> c_int {
9462 if var.is_null() || value.is_null() {
9463 ERRNO = EINVAL;
9464 return -1;
9465 }
9466 let var = var as *const u8;
9467 let l1 = strchrnul_u8(var, b'=') as usize - var as usize;
9468 if l1 == 0 || *var.add(l1) != 0 {
9469 ERRNO = EINVAL;
9470 return -1;
9471 }
9472 if overwrite == 0 && !getenv(var as *const c_char).is_null() {
9473 return 0;
9474 }
9475 let l2 = strlen(value as *const c_char);
9476 let s = malloc(l1 + l2 + 2) as *mut u8;
9477 if s.is_null() {
9478 return -1;
9479 }
9480 core::ptr::copy_nonoverlapping(var, s, l1);
9481 *s.add(l1) = b'=';
9482 core::ptr::copy_nonoverlapping(value as *const u8, s.add(l1 + 1), l2 + 1);
9483 putenv_internal(s as *mut c_char, l1, s as *mut c_char)
9484}
9485
9486unsafe fn putenv_internal(s: *mut c_char, l: usize, r: *mut c_char) -> c_int {
9487 let mut i = 0;
9488 if !__environ.is_null() {
9489 let mut e = __environ;
9490 while !(*e).is_null() {
9491 if strncmp(s as *const u8, *e as *const u8, l + 1) == 0 {
9492 let tmp = *e;
9493 *e = s;
9494 env_rm_add(tmp, r);
9495 return 0;
9496 }
9497 e = e.add(1);
9498 i += 1;
9499 }
9500 }
9501 let newenv = malloc(core::mem::size_of::<*mut c_char>() * (i + 2)) as *mut *mut c_char;
9502 if newenv.is_null() {
9503 if !r.is_null() { free(r as *mut c_void); }
9504 return -1;
9505 }
9506 if i > 0 && !__environ.is_null() {
9507 core::ptr::copy_nonoverlapping(__environ, newenv, i);
9508 }
9509 *newenv.add(i) = s;
9510 *newenv.add(i + 1) = core::ptr::null_mut();
9511 __environ = newenv;
9513 environ = __environ;
9514 if !r.is_null() {
9515 env_rm_add(core::ptr::null_mut(), r);
9516 }
9517 0
9518}
9519
9520#[no_mangle]
9521pub unsafe extern "C" fn putenv(s: *mut c_char) -> c_int {
9522 if s.is_null() { return -1; }
9523 let l = strchrnul_u8(s as *const u8, b'=') as usize - s as *const u8 as usize;
9524 if l == 0 || *s.add(l) as u8 == 0 {
9525 return unsetenv(s);
9526 }
9527 putenv_internal(s, l, core::ptr::null_mut())
9528}
9529
9530#[no_mangle]
9531pub unsafe extern "C" fn unsetenv(name: *const c_char) -> c_int {
9532 if name.is_null() {
9533 ERRNO = EINVAL;
9534 return -1;
9535 }
9536 let name = name as *const u8;
9537 let l = strchrnul_u8(name, b'=') as usize - name as usize;
9538 if l == 0 || *name.add(l) != 0 {
9539 ERRNO = EINVAL;
9540 return -1;
9541 }
9542 if __environ.is_null() {
9543 return 0;
9544 }
9545 let mut e = __environ;
9546 let mut eo = e;
9547 while !(*e).is_null() {
9548 if strncmp(name, *e as *const u8, l) == 0 && *(*e as *const u8).add(l) == b'=' {
9549 env_rm_add(*e, core::ptr::null_mut());
9550 } else {
9551 if eo != e {
9552 *eo = *e;
9553 }
9554 eo = eo.add(1);
9555 }
9556 e = e.add(1);
9557 }
9558 if eo != e {
9559 *eo = core::ptr::null_mut();
9560 }
9561 environ = __environ;
9562 0
9563}
9564
9565#[no_mangle]
9566pub unsafe extern "C" fn clearenv() -> c_int {
9567 let e = __environ;
9568 __environ = core::ptr::null_mut();
9569 environ = core::ptr::null_mut();
9570 if !e.is_null() {
9571 let mut p = e;
9572 while !(*p).is_null() {
9573 env_rm_add(*p, core::ptr::null_mut());
9574 p = p.add(1);
9575 }
9576 }
9577 0
9578}
9579
9580static mut RANDOM_INIT: [u32; 32] = [
9586 0x00000000,0x5851f42d,0xc0b18ccf,0xcbb5f646,
9587 0xc7033129,0x30705b04,0x20fd5db4,0x9a8b7f78,
9588 0x502959d8,0xab894868,0x6c0356a7,0x88cdb7ff,
9589 0xb477d43f,0x70a3a52b,0xa8e4baf1,0xfd8341fc,
9590 0x8ae16fd9,0x742d2f7a,0x0d1f0796,0x76035e09,
9591 0x40f7702c,0x6fa72ca5,0xaaa84157,0x58a0df74,
9592 0xc74a0364,0xae533cc4,0x04185faf,0x6de3b115,
9593 0x0cab8628,0xf043bfa4,0x398150e9,0x37521657,
9594];
9595
9596static mut RANDOM_N: i32 = 31;
9597static mut RANDOM_I: i32 = 3;
9598static mut RANDOM_J: i32 = 0;
9599static mut RANDOM_X: *mut u32 = unsafe { core::ptr::addr_of_mut!(RANDOM_INIT).cast::<u32>().add(1) };
9600
9601unsafe fn random_lcg31(x: u32) -> u32 {
9602 (1103515245u32.wrapping_mul(x).wrapping_add(12345)) & 0x7fffffff
9603}
9604
9605unsafe fn random_lcg64(x: u64) -> u64 {
9606 6364136223846793005u64.wrapping_mul(x).wrapping_add(1)
9607}
9608
9609unsafe fn random_savestate() -> *mut u8 {
9610 (*RANDOM_X.offset(-1)) = ((RANDOM_N as u32) << 16) | ((RANDOM_I as u32) << 8) | (RANDOM_J as u32);
9611 RANDOM_X.offset(-1) as *mut u8
9612}
9613
9614unsafe fn random_loadstate(state: *mut u32) {
9615 RANDOM_X = state.add(1);
9616 RANDOM_N = ((*RANDOM_X.offset(-1)) >> 16) as i32;
9617 RANDOM_I = (((*RANDOM_X.offset(-1)) >> 8) & 0xff) as i32;
9618 RANDOM_J = ((*RANDOM_X.offset(-1)) & 0xff) as i32;
9619}
9620
9621unsafe fn random_srandom_inner(seed: u32) {
9622 let mut s = seed as u64;
9623 if RANDOM_N == 0 {
9624 *RANDOM_X = s as u32;
9625 return;
9626 }
9627 RANDOM_I = if RANDOM_N == 31 || RANDOM_N == 7 { 3 } else { 1 };
9628 RANDOM_J = 0;
9629 for k in 0..RANDOM_N as usize {
9630 s = random_lcg64(s);
9631 *RANDOM_X.add(k) = (s >> 32) as u32;
9632 }
9633 *RANDOM_X |= 1;
9634}
9635
9636#[no_mangle]
9637pub unsafe extern "C" fn srandom(seed: c_uint) {
9638 random_srandom_inner(seed);
9639}
9640
9641#[no_mangle]
9642pub unsafe extern "C" fn initstate(seed: c_uint, state: *mut c_char, size: usize) -> *mut c_char {
9643 if size < 8 { return core::ptr::null_mut(); }
9644 let old = random_savestate();
9645 RANDOM_N = if size < 32 { 0 }
9646 else if size < 64 { 7 }
9647 else if size < 128 { 15 }
9648 else if size < 256 { 31 }
9649 else { 63 };
9650 RANDOM_X = (state as *mut u32).add(1);
9651 random_srandom_inner(seed);
9652 random_savestate();
9653 old as *mut c_char
9654}
9655
9656#[no_mangle]
9657pub unsafe extern "C" fn setstate(state: *mut c_char) -> *mut c_char {
9658 let old = random_savestate();
9659 random_loadstate(state as *mut u32);
9660 old as *mut c_char
9661}
9662
9663#[no_mangle]
9664pub unsafe extern "C" fn random() -> c_long {
9665 let k: c_long;
9666 if RANDOM_N == 0 {
9667 *RANDOM_X = random_lcg31(*RANDOM_X);
9668 k = *RANDOM_X as c_long;
9669 } else {
9670 *RANDOM_X.add(RANDOM_I as usize) = (*RANDOM_X.add(RANDOM_I as usize)).wrapping_add(*RANDOM_X.add(RANDOM_J as usize));
9671 k = (*RANDOM_X.add(RANDOM_I as usize) >> 1) as c_long;
9672 RANDOM_I += 1;
9673 if RANDOM_I == RANDOM_N { RANDOM_I = 0; }
9674 RANDOM_J += 1;
9675 if RANDOM_J == RANDOM_N { RANDOM_J = 0; }
9676 }
9677 k
9678}
9679
9680const SA: u8 = 0xC2;
9685const SB: u8 = 0xF4;
9686
9687const BITTAB: [u32; 51] = [
9688 0xC000_0002, 0xC000_0003, 0xC000_0004, 0xC000_0005, 0xC000_0006, 0xC000_0007,
9689 0xC000_0008, 0xC000_0009, 0xC000_000A, 0xC000_000B, 0xC000_000C, 0xC000_000D,
9690 0xC000_000E, 0xC000_000F, 0xC000_0010, 0xC000_0011, 0xC000_0012, 0xC000_0013,
9691 0xC000_0014, 0xC000_0015, 0xC000_0016, 0xC000_0017, 0xC000_0018, 0xC000_0019,
9692 0xC000_001A, 0xC000_001B, 0xC000_001C, 0xC000_001D, 0xC000_001E, 0xC000_001F,
9693 0xB300_0000, 0xC300_0001, 0xC300_0002, 0xC300_0003, 0xC300_0004, 0xC300_0005,
9694 0xC300_0006, 0xC300_0007, 0xC300_0008, 0xC300_0009, 0xC300_000A, 0xC300_000B,
9695 0xC300_000C, 0xD300_000D, 0xC300_000E, 0xC300_000F, 0xBB0C_0000, 0xC30C_0001,
9696 0xC30C_0002, 0xC30C_0003, 0xDB0C_0004,
9697];
9698
9699#[inline]
9700fn mb_oob(c: u32, b: u8) -> u32 {
9701 let b3 = (b >> 3) as u32;
9702 ((b3.wrapping_sub(0x10)) | (b3.wrapping_add((c as i32 >> 26) as u32))) & !7
9703}
9704
9705static mut MB_STATE: c_uint = 0;
9706
9707const MB_CUR_MAX_VAL_UTF8: usize = 4;
9708const MB_CUR_MAX_VAL_C: usize = 1;
9709
9710#[no_mangle]
9711pub extern "C" fn __ctype_get_mb_cur_max() -> usize {
9712 unsafe { if LOCALE_CTYPE_UTF8 { MB_CUR_MAX_VAL_UTF8 } else { MB_CUR_MAX_VAL_C } }
9713}
9714
9715#[no_mangle]
9716pub unsafe extern "C" fn mbrtowc(
9717 wc: *mut c_int,
9718 src: *const c_char,
9719 n: usize,
9720 st: *mut c_uint,
9721) -> usize {
9722 let s = src as *const u8;
9723 let n0 = n;
9724 let mut dummy: c_int = 0;
9725 let wc = if wc.is_null() { &mut dummy } else { &mut *wc };
9726 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
9727
9728 let mut c: u32 = *st;
9729 let mut s = s;
9730 let mut n = n;
9731
9732 if s.is_null() {
9733 if c != 0 { *st = 0; ERRNO = EILSEQ; return !0usize; }
9734 return 0;
9735 }
9736
9737 if n == 0 { return !1usize; }
9738
9739 if unsafe { !LOCALE_CTYPE_UTF8 } {
9740 let b = *s;
9741 *wc = b as c_int;
9742 return if b == 0 { 0 } else { 1 };
9743 }
9744
9745 if c == 0 {
9746 if *s < 0x80 {
9747 let r = if *s == 0 { 0 } else { 1 };
9748 *wc = *s as c_int;
9749 return r;
9750 }
9751 if (*s).wrapping_sub(SA) as u32 > (SB - SA) as u32 {
9752 *st = 0; ERRNO = EILSEQ; return !0usize;
9753 }
9754 c = BITTAB[*s as usize - SA as usize];
9755 s = s.add(1);
9756 n -= 1;
9757 }
9758
9759 if n > 0 {
9760 if mb_oob(c, *s) != 0 {
9761 *st = 0; ERRNO = EILSEQ; return !0usize;
9762 }
9763 loop {
9764 c = (c << 6) | (*s as u32).wrapping_sub(0x80);
9765 s = s.add(1);
9766 n -= 1;
9767 if c & (1u32 << 31) == 0 {
9768 *st = 0;
9769 *wc = c as c_int;
9770 return n0 - n;
9771 }
9772 if n == 0 { break; }
9773 if (*s).wrapping_sub(0x80) >= 0x40 {
9774 *st = 0; ERRNO = EILSEQ; return !0usize;
9775 }
9776 }
9777 }
9778
9779 *st = c;
9780 !1usize
9781}
9782
9783#[no_mangle]
9784pub unsafe extern "C" fn wcrtomb(
9785 s: *mut c_char,
9786 wc: c_int,
9787 _st: *mut c_uint,
9788) -> usize {
9789 if s.is_null() { return 1; }
9790 let wc_u = wc as u32;
9791 if unsafe { !LOCALE_CTYPE_UTF8 } {
9792 if wc_u > 0xFF {
9793 ERRNO = EILSEQ;
9794 return !0usize;
9795 }
9796 *s = wc as c_char;
9797 return 1;
9798 }
9799 if wc_u < 0x80 {
9800 *s = wc as c_char;
9801 return 1;
9802 }
9803 if wc_u < 0x800 {
9804 *s = (0xC0 | (wc_u >> 6)) as c_char;
9805 *s.add(1) = (0x80 | (wc_u & 0x3F)) as c_char;
9806 return 2;
9807 }
9808 if wc_u < 0xD800 || wc_u.wrapping_sub(0xE000) < 0x2000 {
9809 *s = (0xE0 | (wc_u >> 12)) as c_char;
9810 *s.add(1) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
9811 *s.add(2) = (0x80 | (wc_u & 0x3F)) as c_char;
9812 return 3;
9813 }
9814 if wc_u.wrapping_sub(0x10000) < 0x100000 {
9815 *s = (0xF0 | (wc_u >> 18)) as c_char;
9816 *s.add(1) = (0x80 | ((wc_u >> 12) & 0x3F)) as c_char;
9817 *s.add(2) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
9818 *s.add(3) = (0x80 | (wc_u & 0x3F)) as c_char;
9819 return 4;
9820 }
9821 ERRNO = EILSEQ;
9822 !0usize
9823}
9824
9825#[no_mangle]
9826pub unsafe extern "C" fn mblen(s: *const c_char, n: usize) -> c_int {
9827 if s.is_null() { return 0; }
9828 mbtowc(core::ptr::null_mut(), s, n)
9829}
9830
9831#[no_mangle]
9832pub unsafe extern "C" fn mbtowc(
9833 wc: *mut c_int,
9834 src: *const c_char,
9835 n: usize,
9836) -> c_int {
9837 if src.is_null() { return 0; }
9838 if n == 0 { ERRNO = EILSEQ; return -1; }
9839 let mut state: c_uint = 0;
9840 let mut w: c_int = 0;
9841 let r = mbrtowc(&mut w, src, n, &mut state);
9842 if r == !0usize { return -1; }
9843 if !wc.is_null() { *wc = w; }
9844 r as c_int
9845}
9846
9847#[no_mangle]
9848pub unsafe extern "C" fn wctomb(s: *mut c_char, wc: c_int) -> c_int {
9849 if s.is_null() { return 0; }
9850 wcrtomb(s, wc, core::ptr::null_mut()) as c_int
9851}
9852
9853#[no_mangle]
9854pub unsafe extern "C" fn mbsrtowcs(
9855 ws: *mut c_int,
9856 src: *mut *const c_char,
9857 wn: usize,
9858 st: *mut c_uint,
9859) -> usize {
9860 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
9861 let mut s = *src as *const u8;
9862 let wn0 = wn;
9863 let mut wn = wn;
9864
9865 if ws.is_null() {
9866 while *s != 0 {
9867 if *s < 0x80 {
9868 s = s.add(1);
9869 wn = wn.wrapping_sub(1);
9870 continue;
9871 }
9872 let mut wc: c_int = 0;
9873 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
9874 if r == !0usize { return !0usize; }
9875 if r == !1usize { return wn0 - wn; }
9876 s = s.add(r);
9877 wn = wn.wrapping_sub(1);
9878 }
9879 wn0 - wn
9880 } else {
9881 let mut w = ws;
9882 while wn > 0 {
9883 if *s < 0x80 {
9884 let c = *s as c_int;
9885 *w = c;
9886 if c == 0 {
9887 *src = core::ptr::null();
9888 return wn0 - wn;
9889 }
9890 w = w.add(1);
9891 s = s.add(1);
9892 wn -= 1;
9893 continue;
9894 }
9895 let mut wc: c_int = 0;
9896 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
9897 if r == !0usize {
9898 *src = s as *const c_char;
9899 return !0usize;
9900 }
9901 if r == !1usize {
9902 *src = s as *const c_char;
9903 return wn0 - wn;
9904 }
9905 *w = wc;
9906 w = w.add(1);
9907 s = s.add(r);
9908 wn -= 1;
9909 }
9910 *src = s as *const c_char;
9911 wn0 - wn
9912 }
9913}
9914
9915#[no_mangle]
9916pub unsafe extern "C" fn wcsrtombs(
9917 s: *mut c_char,
9918 ws: *mut *const c_int,
9919 n: usize,
9920 _st: *mut c_uint,
9921) -> usize {
9922 let mut w = *ws;
9923 let n0 = n;
9924 let mut n = n;
9925
9926 if s.is_null() {
9927 let mut count = 0usize;
9928 while *w != 0 {
9929 if (*w as u32) < 0x80 {
9930 count += 1;
9931 } else {
9932 let mut buf = [0u8; 4];
9933 let r = wcrtomb(buf.as_mut_ptr() as *mut c_char, *w, core::ptr::null_mut());
9934 if r == !0usize { return !0usize; }
9935 count += r;
9936 }
9937 w = w.add(1);
9938 }
9939 return count;
9940 }
9941
9942 let mut dst = s;
9943 while n > 0 {
9944 if (*w as u32) < 0x80 {
9945 *dst = *w as c_char;
9946 if *w == 0 {
9947 *ws = core::ptr::null();
9948 return n0 - n;
9949 }
9950 dst = dst.add(1);
9951 n -= 1;
9952 } else {
9953 let r = wcrtomb(dst, *w, core::ptr::null_mut());
9954 if r == !0usize {
9955 *ws = w;
9956 return !0usize;
9957 }
9958 if r > n {
9959 *ws = w;
9960 return n0 - n;
9961 }
9962 dst = dst.add(r);
9963 n -= r;
9964 }
9965 w = w.add(1);
9966 }
9967 *ws = w;
9968 n0
9969}
9970
9971#[no_mangle]
9972pub unsafe extern "C" fn mbstowcs(
9973 ws: *mut c_int,
9974 src: *const c_char,
9975 wn: usize,
9976) -> usize {
9977 let mut src_ptr = src;
9978 mbsrtowcs(ws, &mut src_ptr, wn, core::ptr::null_mut())
9979}
9980
9981#[no_mangle]
9982pub unsafe extern "C" fn wcstombs(
9983 s: *mut c_char,
9984 ws: *const c_int,
9985 n: usize,
9986) -> usize {
9987 let mut ws_ptr = ws;
9988 wcsrtombs(s, &mut ws_ptr, n, core::ptr::null_mut())
9989}
9990
9991#[no_mangle]
9996pub extern "C" fn btowc(c: c_int) -> wint_t {
9997 if c == -1 { return WEOF; }
9998 unsafe {
9999 if LOCALE_CTYPE_UTF8 {
10000 if (c as u32) < 128 { c as wint_t } else { WEOF }
10001 } else {
10002 (c as u8) as wint_t
10003 }
10004 }
10005}
10006
10007#[no_mangle]
10008pub extern "C" fn wctob(c: wint_t) -> c_int {
10009 unsafe {
10010 if LOCALE_CTYPE_UTF8 {
10011 if c < 128 { c as c_int } else { -1 }
10012 } else {
10013 if c <= 0xFF { c as c_int } else { -1 }
10014 }
10015 }
10016}
10017
10018#[no_mangle]
10019pub unsafe extern "C" fn mbsinit(s: *const c_uint) -> c_int {
10020 if s.is_null() || *s == 0 { 1 } else { 0 }
10021}
10022
10023#[no_mangle]
10024pub unsafe extern "C" fn mbrlen(s: *const c_char, n: usize, ps: *mut c_uint) -> usize {
10025 mbrtowc(core::ptr::null_mut(), s, n, ps)
10026}
10027
10028#[no_mangle]
10033pub unsafe extern "C" fn wcslen(s: *const wchar_t) -> usize {
10034 let mut len = 0;
10035 while *s.add(len) != 0 { len += 1; }
10036 len
10037}
10038
10039#[no_mangle]
10040pub unsafe extern "C" fn wcschr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
10041 let mut i = 0;
10042 loop {
10043 let ch = *s.add(i);
10044 if ch == c { return s.add(i) as *mut wchar_t; }
10045 if ch == 0 { return null_mut(); }
10046 i += 1;
10047 }
10048}
10049
10050#[no_mangle]
10051pub unsafe extern "C" fn wcsrchr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
10052 let mut i = 0;
10053 let mut last: *mut wchar_t = null_mut();
10054 loop {
10055 let ch = *s.add(i);
10056 if ch == c { last = s.add(i) as *mut wchar_t; }
10057 if ch == 0 { return last; }
10058 i += 1;
10059 }
10060}
10061
10062#[no_mangle]
10063pub unsafe extern "C" fn wcsstr(haystack: *const wchar_t, needle: *const wchar_t) -> *mut wchar_t {
10064 if *needle == 0 { return haystack as *mut wchar_t; }
10065 let mut i = 0;
10066 loop {
10067 let h = *haystack.add(i);
10068 if h == 0 { return null_mut(); }
10069 if h == *needle {
10070 let mut j = 0;
10071 loop {
10072 let n = *needle.add(j);
10073 if n == 0 { return haystack.add(i) as *mut wchar_t; }
10074 if *haystack.add(i + j) != n { break; }
10075 j += 1;
10076 }
10077 }
10078 i += 1;
10079 }
10080}
10081
10082#[no_mangle]
10083pub unsafe extern "C" fn wcscmp(s1: *const wchar_t, s2: *const wchar_t) -> c_int {
10084 let mut i = 0;
10085 loop {
10086 let a = *s1.add(i);
10087 let b = *s2.add(i);
10088 if a != b { return a - b; }
10089 if a == 0 { return 0; }
10090 i += 1;
10091 }
10092}
10093
10094#[no_mangle]
10095pub unsafe extern "C" fn wcsncmp(s1: *const wchar_t, s2: *const wchar_t, n: usize) -> c_int {
10096 let mut i = 0;
10097 while i < n {
10098 let a = *s1.add(i);
10099 let b = *s2.add(i);
10100 if a != b { return a - b; }
10101 if a == 0 { return 0; }
10102 i += 1;
10103 }
10104 0
10105}
10106
10107#[no_mangle]
10108pub unsafe extern "C" fn wcscpy(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
10109 let mut i = 0;
10110 loop {
10111 let c = *src.add(i);
10112 *dst.add(i) = c;
10113 if c == 0 { break; }
10114 i += 1;
10115 }
10116 dst
10117}
10118
10119#[no_mangle]
10120pub unsafe extern "C" fn wcsncpy(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
10121 let mut i = 0;
10122 while i < n && *src.add(i) != 0 { *dst.add(i) = *src.add(i); i += 1; }
10123 while i < n { *dst.add(i) = 0; i += 1; }
10124 dst
10125}
10126
10127#[no_mangle]
10128pub unsafe extern "C" fn wcscat(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
10129 let mut i = 0;
10130 while *dst.add(i) != 0 { i += 1; }
10131 let mut j = 0;
10132 loop {
10133 let c = *src.add(j);
10134 *dst.add(i + j) = c;
10135 if c == 0 { break; }
10136 j += 1;
10137 }
10138 dst
10139}
10140
10141#[no_mangle]
10142pub unsafe extern "C" fn wcsncat(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
10143 let mut i = 0;
10144 while *dst.add(i) != 0 { i += 1; }
10145 let mut j = 0;
10146 while j < n && *src.add(j) != 0 { *dst.add(i + j) = *src.add(j); j += 1; }
10147 *dst.add(i + j) = 0;
10148 dst
10149}
10150
10151#[no_mangle]
10152pub unsafe extern "C" fn wcsdup(s: *const wchar_t) -> *mut wchar_t {
10153 let len = wcslen(s);
10154 let p = malloc((len + 1) * core::mem::size_of::<wchar_t>()) as *mut wchar_t;
10155 if p.is_null() { return null_mut(); }
10156 core::ptr::copy_nonoverlapping(s, p, len + 1);
10157 p
10158}
10159
10160#[no_mangle]
10161pub unsafe extern "C" fn wcsnlen(s: *const wchar_t, maxlen: usize) -> usize {
10162 let mut i = 0;
10163 while i < maxlen && *s.add(i) != 0 { i += 1; }
10164 i
10165}
10166
10167#[no_mangle]
10168pub unsafe extern "C" fn wcsspn(s: *const wchar_t, accept: *const wchar_t) -> usize {
10169 let mut i = 0;
10170 loop {
10171 let c = *s.add(i);
10172 if c == 0 { return i; }
10173 let mut found = false;
10174 let mut j = 0;
10175 loop {
10176 let a = *accept.add(j);
10177 if a == 0 { break; }
10178 if c == a { found = true; break; }
10179 j += 1;
10180 }
10181 if !found { return i; }
10182 i += 1;
10183 }
10184}
10185
10186#[no_mangle]
10187pub unsafe extern "C" fn wcscspn(s: *const wchar_t, reject: *const wchar_t) -> usize {
10188 let mut i = 0;
10189 loop {
10190 let c = *s.add(i);
10191 if c == 0 { return i; }
10192 let mut j = 0;
10193 loop {
10194 let r = *reject.add(j);
10195 if r == 0 { break; }
10196 if c == r { return i; }
10197 j += 1;
10198 }
10199 i += 1;
10200 }
10201}
10202
10203#[no_mangle]
10204pub unsafe extern "C" fn wcspbrk(s: *const wchar_t, accept: *const wchar_t) -> *mut wchar_t {
10205 let mut i = 0;
10206 loop {
10207 let c = *s.add(i);
10208 if c == 0 { return null_mut(); }
10209 let mut j = 0;
10210 loop {
10211 let a = *accept.add(j);
10212 if a == 0 { break; }
10213 if c == a { return s.add(i) as *mut wchar_t; }
10214 j += 1;
10215 }
10216 i += 1;
10217 }
10218}
10219
10220#[no_mangle]
10221pub unsafe extern "C" fn wcsxfrm(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> usize {
10222 let len = wcslen(src);
10223 if !dst.is_null() {
10224 let copy = if len < n { len } else { if n > 0 { n - 1 } else { 0 } };
10225 for i in 0..copy { *dst.add(i) = *src.add(i); }
10226 if n > 0 { *dst.add(copy) = 0; }
10227 }
10228 len
10229}
10230
10231unsafe fn wcs_to_bytes(ws: *const wchar_t, buf: *mut u8, bufsz: usize) -> usize {
10236 let mut i = 0;
10237 while i < bufsz - 1 {
10238 let c = *ws.add(i);
10239 if c == 0 { break; }
10240 if (c as u32) > 127 { break; }
10241 *buf.add(i) = c as u8;
10242 i += 1;
10243 }
10244 *buf.add(i) = 0;
10245 i
10246}
10247
10248#[no_mangle]
10249pub unsafe extern "C" fn wcstol(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_long {
10250 let mut buf = [0u8; 256];
10251 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10252 let mut end: *mut c_char = core::ptr::null_mut();
10253 let r = strtol(buf.as_ptr() as *const c_char, &mut end, base);
10254 if !endptr.is_null() {
10255 let offset = end as usize - buf.as_ptr() as usize;
10256 *endptr = s.add(offset) as *mut wchar_t;
10257 }
10258 r
10259}
10260
10261#[no_mangle]
10262pub unsafe extern "C" fn wcstoul(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulong {
10263 let mut buf = [0u8; 256];
10264 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10265 let mut end: *mut c_char = core::ptr::null_mut();
10266 let r = strtoul(buf.as_ptr() as *const c_char, &mut end, base);
10267 if !endptr.is_null() {
10268 let offset = end as usize - buf.as_ptr() as usize;
10269 *endptr = s.add(offset) as *mut wchar_t;
10270 }
10271 r
10272}
10273
10274#[no_mangle]
10275pub unsafe extern "C" fn wcstoll(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong {
10276 let mut buf = [0u8; 256];
10277 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10278 let mut end: *mut c_char = core::ptr::null_mut();
10279 let r = strtoll(buf.as_ptr() as *const c_char, &mut end, base);
10280 if !endptr.is_null() {
10281 let offset = end as usize - buf.as_ptr() as usize;
10282 *endptr = s.add(offset) as *mut wchar_t;
10283 }
10284 r
10285}
10286
10287#[no_mangle]
10288pub unsafe extern "C" fn wcstoull(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong {
10289 let mut buf = [0u8; 256];
10290 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10291 let mut end: *mut c_char = core::ptr::null_mut();
10292 let r = strtoull(buf.as_ptr() as *const c_char, &mut end, base);
10293 if !endptr.is_null() {
10294 let offset = end as usize - buf.as_ptr() as usize;
10295 *endptr = s.add(offset) as *mut wchar_t;
10296 }
10297 r
10298}
10299
10300#[no_mangle]
10301pub unsafe extern "C" fn wcstod(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 {
10302 let mut buf = [0u8; 256];
10303 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10304 let mut end: *mut c_char = core::ptr::null_mut();
10305 let r = strtod(buf.as_ptr() as *const c_char, &mut end);
10306 if !endptr.is_null() {
10307 let offset = end as usize - buf.as_ptr() as usize;
10308 *endptr = s.add(offset) as *mut wchar_t;
10309 }
10310 r
10311}
10312
10313#[no_mangle]
10314pub unsafe extern "C" fn wcstof(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f32 { wcstod(s, endptr) as f32 }
10315
10316#[no_mangle]
10317#[cfg(target_arch = "x86_64")]
10318pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 { wcstod(s, endptr) }
10319
10320#[no_mangle]
10321#[cfg(target_arch = "aarch64")]
10322pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
10323
10324#[no_mangle]
10325#[cfg(target_arch = "riscv64")]
10326pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
10327
10328#[no_mangle]
10329pub unsafe extern "C" fn wcstoimax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong { wcstoll(s, endptr, base) }
10330
10331#[no_mangle]
10332pub unsafe extern "C" fn wcstoumax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong { wcstoull(s, endptr, base) }
10333
10334const WC_ALPHA: c_int = 1;
10339const WC_DIGIT: c_int = 2;
10340const WC_SPACE: c_int = 4;
10341const WC_UPPER: c_int = 8;
10342const WC_LOWER: c_int = 16;
10343const WC_ALNUM: c_int = WC_ALPHA | WC_DIGIT;
10344const WC_BLANK: c_int = 32;
10345const WC_CNTRL: c_int = 64;
10346const WC_PUNCT: c_int = 128;
10347const WC_GRAPH: c_int = WC_ALNUM | WC_PUNCT;
10348const WC_PRINT: c_int = WC_GRAPH | WC_BLANK;
10349const WC_XDIGIT: c_int = 256;
10350
10351fn wc_flags(c: wint_t) -> c_int {
10352 if c < 128 {
10353 let f = CT_TABLE[c as usize];
10354 let mut r = 0;
10355 if f & (CT_UPPER | CT_LOWER) != 0 { r |= WC_ALPHA; }
10356 if f & CT_DIGIT != 0 { r |= WC_DIGIT; }
10357 if f & CT_SPACE != 0 { r |= WC_SPACE; }
10358 if f & CT_UPPER != 0 { r |= WC_UPPER; }
10359 if f & CT_LOWER != 0 { r |= WC_LOWER; }
10360 if f & CT_BLANK != 0 { r |= WC_BLANK; }
10361 if f & CT_CNTRL != 0 { r |= WC_CNTRL; }
10362 if f & CT_PUNCT != 0 { r |= WC_PUNCT; }
10363 if f & CT_XDIGIT != 0 { r |= WC_XDIGIT; }
10364 r
10365 } else {
10366 if c < 0x100 { 0 }
10367 else { WC_PRINT | WC_ALPHA }
10368 }
10369}
10370
10371#[no_mangle]
10372pub extern "C" fn iswalnum(c: wint_t) -> c_int { (wc_flags(c) & WC_ALNUM != 0) as c_int }
10373#[no_mangle]
10374pub extern "C" fn iswalpha(c: wint_t) -> c_int { (wc_flags(c) & WC_ALPHA != 0) as c_int }
10375#[no_mangle]
10376pub extern "C" fn iswblank(c: wint_t) -> c_int { (wc_flags(c) & WC_BLANK != 0) as c_int }
10377#[no_mangle]
10378pub extern "C" fn iswcntrl(c: wint_t) -> c_int { (wc_flags(c) & WC_CNTRL != 0) as c_int }
10379#[no_mangle]
10380pub extern "C" fn iswdigit(c: wint_t) -> c_int { ((c >= b'0' as wint_t) && (c <= b'9' as wint_t)) as c_int }
10381#[no_mangle]
10382pub extern "C" fn iswgraph(c: wint_t) -> c_int { (wc_flags(c) & WC_GRAPH != 0) as c_int }
10383#[no_mangle]
10384pub extern "C" fn iswlower(c: wint_t) -> c_int { (wc_flags(c) & WC_LOWER != 0) as c_int }
10385#[no_mangle]
10386pub extern "C" fn iswprint(c: wint_t) -> c_int {
10387 if c < 128 { (wc_flags(c) & WC_PRINT != 0) as c_int }
10388 else if c >= 0x100 && c < 0x110000 { 1 }
10389 else { 0 }
10390}
10391#[no_mangle]
10392pub extern "C" fn iswpunct(c: wint_t) -> c_int { (wc_flags(c) & WC_PUNCT != 0) as c_int }
10393#[no_mangle]
10394pub extern "C" fn iswspace(c: wint_t) -> c_int {
10395 if c < 128 { (wc_flags(c) & WC_SPACE != 0) as c_int }
10396 else {
10397 match c {
10398 0x1680 | 0x2000..=0x200A | 0x2028 | 0x2029 | 0x202F | 0x205F | 0x3000 => 1,
10399 _ => 0,
10400 }
10401 }
10402}
10403#[no_mangle]
10404pub extern "C" fn iswupper(c: wint_t) -> c_int { (wc_flags(c) & WC_UPPER != 0) as c_int }
10405#[no_mangle]
10406pub extern "C" fn iswxdigit(c: wint_t) -> c_int { (wc_flags(c) & WC_XDIGIT != 0) as c_int }
10407
10408static WCTYPE_ALNUM: c_int = WC_ALNUM;
10409static WCTYPE_ALPHA: c_int = WC_ALPHA;
10410static WCTYPE_BLANK: c_int = WC_BLANK;
10411static WCTYPE_CNTRL: c_int = WC_CNTRL;
10412static WCTYPE_DIGIT: c_int = WC_DIGIT;
10413static WCTYPE_GRAPH: c_int = WC_GRAPH;
10414static WCTYPE_LOWER: c_int = WC_LOWER;
10415static WCTYPE_PRINT: c_int = WC_PRINT;
10416static WCTYPE_PUNCT: c_int = WC_PUNCT;
10417static WCTYPE_SPACE: c_int = WC_SPACE;
10418static WCTYPE_UPPER: c_int = WC_UPPER;
10419static WCTYPE_XDIGIT: c_int = WC_XDIGIT;
10420
10421#[no_mangle]
10422pub unsafe extern "C" fn wctype(name: *const c_char) -> wctype_t {
10423 if name.is_null() { return core::ptr::null(); }
10424 let n = name as *const u8;
10425 if strcmp(n, b"alnum\0".as_ptr()) == 0 { return &WCTYPE_ALNUM; }
10426 if strcmp(n, b"alpha\0".as_ptr()) == 0 { return &WCTYPE_ALPHA; }
10427 if strcmp(n, b"blank\0".as_ptr()) == 0 { return &WCTYPE_BLANK; }
10428 if strcmp(n, b"cntrl\0".as_ptr()) == 0 { return &WCTYPE_CNTRL; }
10429 if strcmp(n, b"digit\0".as_ptr()) == 0 { return &WCTYPE_DIGIT; }
10430 if strcmp(n, b"graph\0".as_ptr()) == 0 { return &WCTYPE_GRAPH; }
10431 if strcmp(n, b"lower\0".as_ptr()) == 0 { return &WCTYPE_LOWER; }
10432 if strcmp(n, b"print\0".as_ptr()) == 0 { return &WCTYPE_PRINT; }
10433 if strcmp(n, b"punct\0".as_ptr()) == 0 { return &WCTYPE_PUNCT; }
10434 if strcmp(n, b"space\0".as_ptr()) == 0 { return &WCTYPE_SPACE; }
10435 if strcmp(n, b"upper\0".as_ptr()) == 0 { return &WCTYPE_UPPER; }
10436 if strcmp(n, b"xdigit\0".as_ptr()) == 0 { return &WCTYPE_XDIGIT; }
10437 core::ptr::null()
10438}
10439
10440#[no_mangle]
10441pub unsafe extern "C" fn iswctype(c: wint_t, desc: wctype_t) -> c_int {
10442 if desc.is_null() { return 0; }
10443 (wc_flags(c) & *desc != 0) as c_int
10444}
10445
10446static WCTRANS_LOWER: c_int = 1;
10447static WCTRANS_UPPER: c_int = 2;
10448
10449#[no_mangle]
10450pub unsafe extern "C" fn towlower(c: wint_t) -> wint_t {
10451 if c < 128 { tolower(c as c_int) as wint_t } else { c }
10452}
10453
10454#[no_mangle]
10455pub unsafe extern "C" fn towupper(c: wint_t) -> wint_t {
10456 if c < 128 { toupper(c as c_int) as wint_t } else { c }
10457}
10458
10459#[no_mangle]
10460pub unsafe extern "C" fn wctrans(name: *const c_char) -> wctrans_t {
10461 if name.is_null() { return core::ptr::null(); }
10462 let n = name as *const u8;
10463 if strcmp(n, b"tolower\0".as_ptr()) == 0 { return &WCTRANS_LOWER; }
10464 if strcmp(n, b"toupper\0".as_ptr()) == 0 { return &WCTRANS_UPPER; }
10465 core::ptr::null()
10466}
10467
10468#[no_mangle]
10469pub unsafe extern "C" fn towctrans(c: wint_t, desc: wctrans_t) -> wint_t {
10470 if desc.is_null() { return c; }
10471 match *desc {
10472 1 => towlower(c),
10473 2 => towupper(c),
10474 _ => c,
10475 }
10476}
10477
10478#[no_mangle]
10483pub unsafe extern "C" fn fgetwc(f: *mut FILE) -> wint_t {
10484 let mut state: c_uint = 0;
10485 let mut wc: wchar_t = 0;
10486 let mut buf = [0u8; 4];
10487 let c = fgetc(f);
10488 if c == -1 { return WEOF; }
10489 buf[0] = c as u8;
10490 if buf[0] < 0x80 { return buf[0] as wint_t; }
10491 let len = if buf[0] < 0xE0 { 2 } else if buf[0] < 0xF0 { 3 } else { 4 };
10492 let mut n = 1usize;
10493 while n < len {
10494 let c2 = fgetc(f);
10495 if c2 == -1 { return WEOF; }
10496 buf[n] = c2 as u8;
10497 n += 1;
10498 }
10499 let r = mbrtowc(&mut wc, buf.as_ptr() as *const c_char, n, &mut state);
10500 if r == !0usize || r == !1usize { WEOF } else { wc as wint_t }
10501}
10502
10503#[no_mangle]
10504pub unsafe extern "C" fn fputwc(c: wchar_t, f: *mut FILE) -> wint_t {
10505 let mut buf = [0u8; 4];
10506 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c, core::ptr::null_mut());
10507 if n == !0usize || n == 0 { return WEOF; }
10508 if fwrite(buf.as_ptr() as *const c_void, 1, n, f) != n { return WEOF; }
10509 c as wint_t
10510}
10511
10512#[no_mangle]
10513pub unsafe extern "C" fn fputws(s: *const wchar_t, f: *mut FILE) -> c_int {
10514 let mut i = 0;
10515 while *s.add(i) != 0 {
10516 if fputwc(*s.add(i), f) == WEOF { return -1; }
10517 i += 1;
10518 }
10519 0
10520}
10521
10522#[no_mangle]
10523pub unsafe extern "C" fn ungetwc(c: wint_t, f: *mut FILE) -> wint_t {
10524 if c == WEOF { return WEOF; }
10525 let mut buf = [0u8; 4];
10526 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c as wchar_t, core::ptr::null_mut());
10527 if n == !0usize || n == 0 { return WEOF; }
10528 let mut i = n;
10529 while i > 0 {
10530 i -= 1;
10531 if ungetc(buf[i] as c_int, f) == -1 { return WEOF; }
10532 }
10533 c
10534}
10535
10536#[no_mangle]
10537pub unsafe extern "C" fn getwchar() -> wint_t { fgetwc(stdin) }
10538
10539#[no_mangle]
10540pub unsafe extern "C" fn putwchar(c: wchar_t) -> wint_t { fputwc(c, stdout) }
10541
10542unsafe fn wfmt_write_str(dst: *mut wchar_t, pos: usize, cap: usize, s: *const u8, len: usize) -> usize {
10547 let mut i = 0;
10548 while i < len {
10549 if pos + i < cap { *dst.add(pos + i) = *s.add(i) as wchar_t; }
10550 i += 1;
10551 }
10552 pos + len
10553}
10554
10555#[no_mangle]
10556pub unsafe extern "C" fn vswprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, mut args: VaList) -> c_int {
10557 if n == 0 { return -1; }
10558 let cap = n - 1;
10559 let mut pos = 0usize;
10560 let mut fmt_narrow = [0u8; 256];
10562 let mut flen = 0usize;
10563 loop {
10564 let ch = *fmt.add(flen) as u32;
10565 if ch == 0 || flen >= 255 { break; }
10566 fmt_narrow[flen] = if ch < 128 { ch as u8 } else { b'?' };
10567 flen += 1;
10568 }
10569 fmt_narrow[flen] = 0;
10570 let mut fi = 0usize;
10571 macro_rules! wc {
10572 ($c:expr) => { if pos < cap { *s.add(pos) = $c as wchar_t; } pos += 1; }
10573 }
10574 loop {
10575 let c = fmt_narrow[fi];
10576 if c == 0 { break; }
10577 if c != b'%' { wc!(c); fi += 1; continue; }
10578 fi += 1;
10579 let mut flags: u8 = 0;
10580 loop {
10581 match fmt_narrow[fi] {
10582 b'-' => { flags |= FLAG_MINUS; fi += 1; }
10583 b'+' => { flags |= FLAG_PLUS; fi += 1; }
10584 b' ' => { flags |= FLAG_SPACE; fi += 1; }
10585 b'0' => { flags |= FLAG_ZERO; fi += 1; }
10586 b'#' => { flags |= FLAG_HASH; fi += 1; }
10587 _ => break,
10588 }
10589 }
10590 let mut width: usize = 0;
10591 if fmt_narrow[fi] == b'*' {
10592 let w = args.next_arg::<c_int>();
10593 if w < 0 { flags |= FLAG_MINUS; width = (-w) as usize; } else { width = w as usize; }
10594 fi += 1;
10595 } else {
10596 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10597 width = width * 10 + (fmt_narrow[fi] - b'0') as usize; fi += 1;
10598 }
10599 }
10600 let mut precision: i32 = -1;
10601 if fmt_narrow[fi] == b'.' {
10602 fi += 1;
10603 if fmt_narrow[fi] == b'*' {
10604 let p = args.next_arg::<c_int>();
10605 precision = if p < 0 { -1 } else { p }; fi += 1;
10606 } else {
10607 precision = 0;
10608 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10609 precision = precision * 10 + (fmt_narrow[fi] - b'0') as i32; fi += 1;
10610 }
10611 }
10612 }
10613 let len_mod = fmt_narrow[fi];
10614 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' {
10615 fi += 1;
10616 let spec = fmt_narrow[fi];
10617 if (len_mod == b'h' && spec == b'h') || (len_mod == b'l' && spec == b'l') {
10618 fi += 1;
10619 let spec2 = fmt_narrow[fi];
10620 match (len_mod, spec, spec2) {
10621 (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; } }
10622 (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; } }
10623 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
10624 let val = args.next_arg::<c_longlong>();
10625 let neg = val < 0;
10626 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10627 let b = format_u64(abs);
10628 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10629 let mut fbuf = [0u8; 32];
10630 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10631 for k in 0..len { wc!(fbuf[k]); }
10632 }
10633 (b'l', b'l', b'u') => {
10634 let val = args.next_arg::<c_ulonglong>();
10635 let b = format_u64(val as u64);
10636 let mut fbuf = [0u8; 32];
10637 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10638 for k in 0..len { wc!(fbuf[k]); }
10639 }
10640 (b'l', b'l', b'x') => {
10641 let val = args.next_arg::<c_ulonglong>();
10642 let b = format_hex(val as u64, false);
10643 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10644 let mut fbuf = [0u8; 32];
10645 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10646 for k in 0..len { wc!(fbuf[k]); }
10647 }
10648 (b'l', b'l', b'X') => {
10649 let val = args.next_arg::<c_ulonglong>();
10650 let b = format_hex(val as u64, true);
10651 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10652 let mut fbuf = [0u8; 32];
10653 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10654 for k in 0..len { wc!(fbuf[k]); }
10655 }
10656 (b'l', b'l', b'o') => {
10657 let val = args.next_arg::<c_ulonglong>();
10658 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10659 let mut fbuf = [0u8; 32];
10660 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10661 for k in 0..len { wc!(fbuf[k]); }
10662 }
10663 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); wc!(spec2); }
10664 }
10665 } else {
10666 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
10667 match (lm, spec) {
10668 (b'h', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut u16) = pos as u16; } }
10669 (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; } }
10670 (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; } }
10671 (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; } }
10672 (b'l', b'd') | (b'l', b'i') => {
10673 let val = args.next_arg::<c_long>();
10674 let neg = val < 0;
10675 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10676 let b = format_u64(abs);
10677 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10678 let mut fbuf = [0u8; 32];
10679 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10680 for k in 0..len { wc!(fbuf[k]); }
10681 }
10682 (b'l', b'u') => {
10683 let val = args.next_arg::<c_ulong>();
10684 let b = format_u64(val as u64);
10685 let mut fbuf = [0u8; 32];
10686 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10687 for k in 0..len { wc!(fbuf[k]); }
10688 }
10689 (b'l', b'x') => {
10690 let val = args.next_arg::<c_ulong>();
10691 let b = format_hex(val as u64, false);
10692 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10693 let mut fbuf = [0u8; 32];
10694 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10695 for k in 0..len { wc!(fbuf[k]); }
10696 }
10697 (b'l', b'X') => {
10698 let val = args.next_arg::<c_ulong>();
10699 let b = format_hex(val as u64, true);
10700 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10701 let mut fbuf = [0u8; 32];
10702 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10703 for k in 0..len { wc!(fbuf[k]); }
10704 }
10705 (b'l', b'o') => {
10706 let val = args.next_arg::<c_ulong>();
10707 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10708 let mut fbuf = [0u8; 32];
10709 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10710 for k in 0..len { wc!(fbuf[k]); }
10711 }
10712 (b'l', b'c') => {
10713 let ch = args.next_arg::<wint_t>();
10714 wc!(ch);
10715 }
10716 (b'l', b's') => {
10717 let ws_arg = args.next_arg::<*const wchar_t>();
10718 if ws_arg.is_null() {
10719 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
10720 if flags & FLAG_MINUS != 0 {
10721 for k in 0..slen { wc!(b"(null)"[k]); }
10722 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10723 } else {
10724 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10725 for k in 0..slen { wc!(b"(null)"[k]); }
10726 }
10727 } else {
10728 let mut wlen = 0usize;
10729 loop {
10730 let ch = *ws_arg.add(wlen);
10731 if ch == 0 { break; }
10732 if precision >= 0 && wlen >= precision as usize { break; }
10733 wlen += 1;
10734 }
10735 if flags & FLAG_MINUS != 0 {
10736 for k in 0..wlen { wc!(*ws_arg.add(k)); }
10737 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
10738 } else {
10739 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
10740 for k in 0..wlen { wc!(*ws_arg.add(k)); }
10741 }
10742 }
10743 }
10744 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
10745 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
10746 let val = args.next_arg::<f64>();
10747 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
10748 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
10749 let mut fbuf = [0u8; 4224];
10750 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
10751 let mut wbuf = [0u8; 4224];
10752 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
10753 for k in 0..wlen { wc!(wbuf[k]); }
10754 }
10755 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
10756 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
10757 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
10758 let val = {
10759 let lo: u64 = args.next_arg::<u64>();
10760 let hi: u64 = args.next_arg::<u64>();
10761 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
10762 f128::from_bits(combined) as f64
10763 };
10764 #[cfg(target_arch = "x86_64")]
10765 let val = args.next_arg::<f64>();
10766 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
10767 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
10768 let mut fbuf = [0u8; 4224];
10769 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
10770 let mut wbuf = [0u8; 4224];
10771 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
10772 for k in 0..wlen { wc!(wbuf[k]); }
10773 }
10774 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
10775 }
10776 }
10777 } else {
10778 let spec = fmt_narrow[fi];
10779 match spec {
10780 b'd' | b'i' => {
10781 let d = args.next_arg::<c_int>();
10782 let neg = d < 0;
10783 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
10784 let b = format_u64(abs);
10785 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10786 let mut fbuf = [0u8; 32];
10787 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10788 for k in 0..len { wc!(fbuf[k]); }
10789 }
10790 b'u' => {
10791 let u = args.next_arg::<c_uint>();
10792 let b = format_u64(u as u64);
10793 let mut fbuf = [0u8; 32];
10794 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10795 for k in 0..len { wc!(fbuf[k]); }
10796 }
10797 b'x' => {
10798 let x = args.next_arg::<c_uint>();
10799 let b = format_hex(x as u64, false);
10800 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10801 let mut fbuf = [0u8; 32];
10802 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10803 for k in 0..len { wc!(fbuf[k]); }
10804 }
10805 b'X' => {
10806 let x = args.next_arg::<c_uint>();
10807 let b = format_hex(x as u64, true);
10808 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10809 let mut fbuf = [0u8; 32];
10810 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10811 for k in 0..len { wc!(fbuf[k]); }
10812 }
10813 b'o' => {
10814 let o = args.next_arg::<c_uint>();
10815 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
10816 let mut fbuf = [0u8; 32];
10817 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10818 for k in 0..len { wc!(fbuf[k]); }
10819 }
10820 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
10821 let val = args.next_arg::<f64>();
10822 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
10823 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
10824 let mut fbuf = [0u8; 4224];
10825 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
10826 let mut wbuf = [0u8; 4224];
10827 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
10828 for k in 0..wlen { wc!(wbuf[k]); }
10829 }
10830 b'c' => {
10831 let ch = args.next_arg::<c_int>();
10832 wc!(ch as u8);
10833 }
10834 b's' => {
10835 let p = args.next_arg::<*const c_char>();
10836 if p.is_null() {
10837 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
10838 if flags & FLAG_MINUS != 0 {
10839 for k in 0..slen { wc!(b"(null)"[k]); }
10840 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10841 } else {
10842 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10843 for k in 0..slen { wc!(b"(null)"[k]); }
10844 }
10845 } else {
10846 let mut wbuf_local = [0i32; 256];
10847 let mut wcount = 0usize;
10848 let mut byte_pos = 0usize;
10849 let pbytes = p as *const u8;
10850 loop {
10851 if precision >= 0 && wcount >= precision as usize { break; }
10852 if wcount >= 256 { break; }
10853 let mut wc_val: c_int = 0;
10854 let consumed = mbrtowc(&mut wc_val as *mut c_int, p.add(byte_pos) as *const c_char, 256, core::ptr::null_mut());
10855 if consumed == !0usize || consumed == !1usize {
10856 wbuf_local[wcount] = *pbytes.add(byte_pos) as c_int;
10857 byte_pos += 1;
10858 wcount += 1;
10859 } else if consumed == 0 {
10860 break;
10861 } else {
10862 wbuf_local[wcount] = wc_val;
10863 byte_pos += consumed;
10864 wcount += 1;
10865 }
10866 }
10867 if flags & FLAG_MINUS != 0 {
10868 for k in 0..wcount { wc!(wbuf_local[k]); }
10869 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
10870 } else {
10871 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
10872 for k in 0..wcount { wc!(wbuf_local[k]); }
10873 }
10874 }
10875 }
10876 b'p' => {
10877 wc!(b'0'); wc!(b'x');
10878 let p = args.next_arg::<*const c_void>();
10879 let b = format_hex(p as u64, false);
10880 for k in 0..b.1 { wc!(b.0[k]); }
10881 }
10882 b'n' => {
10883 let p = args.next_arg::<*mut c_void>();
10884 if !p.is_null() { *(p as *mut c_int) = pos as c_int; }
10885 }
10886 b'%' => { wc!(b'%'); }
10887 _ => { wc!(b'%'); wc!(spec); }
10888 }
10889 }
10890 fi += 1;
10891 }
10892 let null_pos = if pos < cap { pos } else { cap };
10893 *s.add(null_pos) = 0;
10894 if pos > cap { -1 } else { pos as c_int }
10895}
10896
10897#[no_mangle]
10898pub unsafe extern "C" fn swprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, args: ...) -> c_int {
10899 vswprintf(s, n, fmt, args)
10900}
10901
10902#[no_mangle]
10903pub unsafe extern "C" fn vfwprintf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int {
10904 let mut buf = [0i32; 4096];
10905 let r = vswprintf(buf.as_mut_ptr(), 4096, fmt, args);
10906 if r < 0 { return r; }
10907 let mut i = 0;
10908 while i < r as usize {
10909 let mut mb = [0u8; 4];
10910 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, buf[i], core::ptr::null_mut());
10911 if n == !0usize { return -1; }
10912 if fwrite(mb.as_ptr() as *const c_void, 1, n, f) != n { return -1; }
10913 i += 1;
10914 }
10915 r
10916}
10917
10918#[no_mangle]
10919pub unsafe extern "C" fn fwprintf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
10920 vfwprintf(f, fmt, args)
10921}
10922
10923unsafe fn wcsfmt_to_mbs(dst: *mut u8, dst_len: usize, src: *const wchar_t) {
10929 let mut i = 0usize;
10930 loop {
10931 let ch = *src.add(i) as u32;
10932 if ch == 0 || i >= dst_len - 1 { break; }
10933 *dst.add(i) = if ch < 128 { ch as u8 } else { b'?' };
10934 i += 1;
10935 }
10936 *dst.add(i) = 0;
10937}
10938
10939#[no_mangle]
10940pub unsafe extern "C" fn vswscanf(s: *const wchar_t, fmt: *const wchar_t, mut args: VaList) -> c_int {
10941 let mut mbs_buf = [0u8; 4096];
10942 let mut i = 0usize;
10943 let mut mb_pos = 0usize;
10944 loop {
10945 let wc = *s.add(i) as c_int;
10946 if wc == 0 { break; }
10947 let mut mb = [0u8; 4];
10948 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, wc, core::ptr::null_mut());
10949 if n == !0usize || n == 0 { break; }
10950 if mb_pos + n >= mbs_buf.len() { break; }
10951 let mut k = 0usize;
10952 while k < n { mbs_buf[mb_pos + k] = mb[k]; k += 1; }
10953 mb_pos += n;
10954 i += 1;
10955 }
10956 mbs_buf[mb_pos] = 0;
10957 let mut mbs_fmt = [0u8; 4096];
10958 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
10959 do_vsscanf(mbs_buf.as_ptr(), mb_pos, mbs_fmt.as_ptr() as *const c_char, &mut args, core::ptr::null_mut())
10960}
10961
10962#[no_mangle]
10963pub unsafe extern "C" fn swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int {
10964 vswscanf(s, fmt, args)
10965}
10966
10967#[no_mangle]
10968pub unsafe extern "C" fn vfwscanf(f: *mut FILE, fmt: *const wchar_t, mut args: VaList) -> c_int {
10969 let start_pos = ftello(f);
10970 if start_pos < 0 { return -1; }
10971 let mut buf = [0u8; 4096];
10972 let mut n = 0usize;
10973 loop {
10974 if n >= buf.len() - 1 { break; }
10975 let c = fgetc(f);
10976 if c == -1 { break; }
10977 buf[n] = c as u8;
10978 n += 1;
10979 }
10980 buf[n] = 0;
10981 let mut mbs_fmt = [0u8; 4096];
10982 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
10983 let mut consumed = 0usize;
10984 let hit_eof = (*f)._eof != 0;
10985 let result = do_vsscanf(buf.as_ptr(), n, mbs_fmt.as_ptr() as *const c_char, &mut args, &mut consumed);
10986 let _ = fseeko(f, start_pos + consumed as i64, SEEK_SET);
10987 if hit_eof && consumed == n {
10988 (*f)._eof = 1;
10989 }
10990 result
10991}
10992
10993#[no_mangle]
10994pub unsafe extern "C" fn fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
10995 vfwscanf(f, fmt, args)
10996}
10997
10998#[no_mangle]
10999pub unsafe extern "C" fn vwscanf(fmt: *const wchar_t, args: VaList) -> c_int {
11000 vfwscanf(stdin, fmt, args)
11001}
11002
11003#[no_mangle]
11004pub unsafe extern "C" fn wscanf(fmt: *const wchar_t, args: ...) -> c_int {
11005 vfwscanf(stdin, fmt, args)
11006}
11007
11008const LEAPOCH: i64 = 946684800 + 86400 * (31 + 29);
11013const DAYS_PER_400Y: i64 = 365 * 400 + 97;
11014const DAYS_PER_100Y: i64 = 365 * 100 + 24;
11015const DAYS_PER_4Y: i64 = 365 * 4 + 1;
11016
11017const SECS_THROUGH_MONTH: [i32; 12] = [
11018 0, 31*86400, 59*86400, 90*86400, 120*86400, 151*86400,
11019 181*86400, 212*86400, 243*86400, 273*86400, 304*86400, 334*86400,
11020];
11021
11022const DAYS_IN_MONTH: [i32; 12] = [31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29];
11023
11024unsafe fn year_to_secs(year: i64, is_leap: &mut bool) -> i64 {
11025 if year - 2 <= 136 {
11026 let y = year as i32;
11027 let mut leaps = (y - 68) >> 2;
11028 if (y - 68) & 3 == 0 { leaps -= 1; *is_leap = true; } else { *is_leap = false; }
11029 return 31536000 * (y as i64 - 70) + 86400 * leaps as i64;
11030 }
11031 let mut cycles = ((year - 100) / 400) as i32;
11032 let mut rem = ((year - 100) % 400) as i32;
11033 if rem < 0 { cycles -= 1; rem += 400; }
11034 let (centuries, leaps);
11035 if rem == 0 { *is_leap = true; centuries = 0; leaps = 0; }
11036 else {
11037 let c;
11038 if rem >= 200 { if rem >= 300 { c = 3; rem -= 300; } else { c = 2; rem -= 200; } }
11039 else { if rem >= 100 { c = 1; rem -= 100; } else { c = 0; } }
11040 centuries = c;
11041 if rem == 0 { *is_leap = false; leaps = 0; }
11042 else { leaps = rem / 4; rem %= 4; *is_leap = rem == 0; }
11043 }
11044 let total_leaps = leaps + 97 * cycles + 24 * centuries - (*is_leap as i32);
11045 (year - 100) * 31536000 + total_leaps as i64 * 86400 + 946684800 + 86400
11046}
11047
11048fn month_to_secs(month: i32, is_leap: bool) -> i32 {
11049 let mut t = SECS_THROUGH_MONTH[month as usize];
11050 if is_leap && month >= 2 { t += 86400; }
11051 t
11052}
11053
11054unsafe fn secs_to_tm(t: i64, tm: &mut tm) -> bool {
11055 if t < (i32::MIN as i64) * 31622400 || t > (i32::MAX as i64) * 31622400 { return false; }
11056 let secs = t - LEAPOCH;
11057 let mut days = secs / 86400;
11058 let mut remsecs = (secs % 86400) as i32;
11059 if remsecs < 0 { remsecs += 86400; days -= 1; }
11060 let mut wday = ((3 + days) % 7) as i32;
11061 if wday < 0 { wday += 7; }
11062 let mut qc_cycles = (days / DAYS_PER_400Y) as i32;
11063 let mut remdays = (days % DAYS_PER_400Y) as i32;
11064 if remdays < 0 { remdays += DAYS_PER_400Y as i32; qc_cycles -= 1; }
11065 let mut c_cycles = remdays / DAYS_PER_100Y as i32;
11066 if c_cycles == 4 { c_cycles -= 1; }
11067 remdays -= c_cycles * DAYS_PER_100Y as i32;
11068 let mut q_cycles = remdays / DAYS_PER_4Y as i32;
11069 if q_cycles == 25 { q_cycles -= 1; }
11070 remdays -= q_cycles * DAYS_PER_4Y as i32;
11071 let mut remyears = remdays / 365;
11072 if remyears == 4 { remyears -= 1; }
11073 remdays -= remyears * 365;
11074 let leap = remyears == 0 && (q_cycles != 0 || c_cycles == 0);
11075 let mut yday = remdays + 31 + 28 + leap as i32;
11076 if yday >= 365 + leap as i32 { yday -= 365 + leap as i32; }
11077 let years = remyears as i64 + 4 * q_cycles as i64 + 100 * c_cycles as i64 + 400 * qc_cycles as i64;
11078 let mut months = 0i32;
11079 let mut rd = remdays;
11080 for m in 0..12 {
11081 if DAYS_IN_MONTH[m] <= rd { rd -= DAYS_IN_MONTH[m]; } else { months = m as i32; break; }
11082 }
11083 let mut adj_years = years;
11084 if months >= 10 { months -= 12; adj_years += 1; }
11085 if adj_years + 100 > i32::MAX as i64 || adj_years + 100 < i32::MIN as i64 { return false; }
11086 tm.tm_year = (adj_years + 100) as c_int;
11087 tm.tm_mon = months + 2;
11088 tm.tm_mday = rd + 1;
11089 tm.tm_wday = wday;
11090 tm.tm_yday = yday;
11091 tm.tm_hour = remsecs / 3600;
11092 tm.tm_min = remsecs / 60 % 60;
11093 tm.tm_sec = remsecs % 60;
11094 true
11095}
11096
11097unsafe fn tm_to_secs(tm: *const tm) -> i64 {
11098 let mut year = (*tm).tm_year as i64;
11099 let mut month = (*tm).tm_mon;
11100 if month >= 12 || month < 0 {
11101 let adj = month / 12;
11102 month %= 12;
11103 if month < 0 { month += 12; }
11104 year += adj as i64;
11105 }
11106 let mut is_leap = false;
11107 let mut t = year_to_secs(year, &mut is_leap);
11108 t += month_to_secs(month, is_leap) as i64;
11109 t += 86400 * ((*tm).tm_mday - 1) as i64;
11110 t += 3600 * (*tm).tm_hour as i64;
11111 t += 60 * (*tm).tm_min as i64;
11112 t += (*tm).tm_sec as i64;
11113 t
11114}
11115
11116static mut TM_BUF: tm = tm {
11117 tm_sec: 0, tm_min: 0, tm_hour: 0, tm_mday: 0, tm_mon: 0,
11118 tm_year: 0, tm_wday: 0, tm_yday: 0, tm_isdst: 0,
11119 tm_gmtoff: 0, tm_zone: core::ptr::null(),
11120};
11121
11122static mut UTC_STR: [c_char; 4] = [b'U' as c_char, b'T' as c_char, b'C' as c_char, 0];
11123
11124const CLOCK_PROCESS_CPUTIME_ID: c_int = 2;
11125
11126#[no_mangle]
11131pub unsafe extern "C" fn time(t: *mut TimeT) -> TimeT {
11132 let mut ts: timespec = core::mem::zeroed();
11133 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
11134 if !t.is_null() { *t = ts.tv_sec; }
11135 ts.tv_sec
11136}
11137
11138#[no_mangle]
11139pub unsafe extern "C" fn difftime(t1: TimeT, t0: TimeT) -> f64 {
11140 (t1 as i64 - t0 as i64) as f64
11141}
11142
11143#[no_mangle]
11144pub unsafe extern "C" fn clock() -> ClockT {
11145 let mut ts: timespec = core::mem::zeroed();
11146 let _ = sys_clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &mut ts);
11147 ts.tv_sec * 1000000 + ts.tv_nsec / 1000
11148}
11149
11150#[no_mangle]
11151pub unsafe extern "C" fn gmtime(t: *const TimeT) -> *mut tm {
11152 gmtime_r(t, &raw mut TM_BUF)
11153}
11154
11155#[no_mangle]
11156pub unsafe extern "C" fn gmtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm {
11157 if !secs_to_tm(*t as i64, &mut *tm) { ERRNO = EOVERFLOW; return core::ptr::null_mut(); }
11158 (*tm).tm_isdst = 0;
11159 (*tm).tm_gmtoff = 0;
11160 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11161 tm
11162}
11163
11164#[no_mangle]
11165pub unsafe extern "C" fn localtime(t: *const TimeT) -> *mut tm { gmtime(t) }
11166
11167#[no_mangle]
11168pub unsafe extern "C" fn localtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm { gmtime_r(t, tm) }
11169
11170#[no_mangle]
11171pub unsafe extern "C" fn mktime(tm: *mut tm) -> TimeT {
11172 let t = tm_to_secs(tm as *const tm);
11173 if !secs_to_tm(t, &mut *tm) { ERRNO = EOVERFLOW; return -1; }
11174 (*tm).tm_isdst = 0;
11175 (*tm).tm_gmtoff = 0;
11176 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11177 t as TimeT
11178}
11179
11180#[no_mangle]
11181pub unsafe extern "C" fn timegm(tm: *mut tm) -> TimeT {
11182 let t = tm_to_secs(tm as *const tm);
11183 if !secs_to_tm(t, &mut *tm) { ERRNO = EOVERFLOW; return -1; }
11184 (*tm).tm_isdst = 0;
11185 (*tm).tm_gmtoff = 0;
11186 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11187 t as TimeT
11188}
11189
11190static mut ASCTIME_BUF: [c_char; 26] = [0; 26];
11191
11192const 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"];
11193const 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"];
11194
11195#[no_mangle]
11196pub unsafe extern "C" fn asctime(tm: *const tm) -> *mut c_char {
11197 asctime_r(tm, core::ptr::addr_of_mut!(ASCTIME_BUF).cast::<c_char>())
11198}
11199
11200#[no_mangle]
11201pub unsafe extern "C" fn asctime_r(tm: *const tm, buf: *mut c_char) -> *mut c_char {
11202 let wday = if (*tm).tm_wday >= 0 && (*tm).tm_wday < 7 { (*tm).tm_wday as usize } else { 0 };
11203 let mon = if (*tm).tm_mon >= 0 && (*tm).tm_mon < 12 { (*tm).tm_mon as usize } else { 0 };
11204 let dn = DAY_NAMES[wday];
11205 let mn = MON_NAMES[mon];
11206 let mut p = 0;
11207 for k in 0..3 { *buf.add(p) = *dn.as_ptr().add(k) as c_char; p += 1; }
11208 *buf.add(p) = b' ' as c_char; p += 1;
11209 for k in 0..3 { *buf.add(p) = *mn.as_ptr().add(k) as c_char; p += 1; }
11210 *buf.add(p) = b' ' as c_char; p += 1;
11211 let v = (*tm).tm_mday;
11212 *buf.add(p) = (b'0' + (v / 10) as u8) as c_char; p += 1;
11213 *buf.add(p) = (b'0' + (v % 10) as u8) as c_char; p += 1;
11214 *buf.add(p) = b' ' as c_char; p += 1;
11215 let hh = (*tm).tm_hour;
11216 *buf.add(p) = (b'0' + (hh / 10) as u8) as c_char; p += 1;
11217 *buf.add(p) = (b'0' + (hh % 10) as u8) as c_char; p += 1;
11218 *buf.add(p) = b':' as c_char; p += 1;
11219 let mm = (*tm).tm_min;
11220 *buf.add(p) = (b'0' + (mm / 10) as u8) as c_char; p += 1;
11221 *buf.add(p) = (b'0' + (mm % 10) as u8) as c_char; p += 1;
11222 *buf.add(p) = b':' as c_char; p += 1;
11223 let ss = (*tm).tm_sec;
11224 *buf.add(p) = (b'0' + (ss / 10) as u8) as c_char; p += 1;
11225 *buf.add(p) = (b'0' + (ss % 10) as u8) as c_char; p += 1;
11226 *buf.add(p) = b' ' as c_char; p += 1;
11227 let yr = (*tm).tm_year + 1900;
11228 let mut tmp = [0u8; 4];
11229 let mut v2 = yr;
11230 for k in (0..4).rev() { tmp[k] = b'0' + (v2 % 10) as u8; v2 /= 10; }
11231 for k in 0..4 { *buf.add(p) = tmp[k] as c_char; p += 1; }
11232 *buf.add(p) = b'\n' as c_char; p += 1;
11233 *buf.add(p) = 0;
11234 buf
11235}
11236
11237#[no_mangle]
11238pub unsafe extern "C" fn ctime(t: *const TimeT) -> *mut c_char { asctime(gmtime(t)) }
11239
11240#[no_mangle]
11241pub unsafe extern "C" fn ctime_r(t: *const TimeT, buf: *mut c_char) -> *mut c_char {
11242 let mut tmp: tm = core::mem::zeroed();
11243 gmtime_r(t, &mut tmp);
11244 asctime_r(&tmp, buf)
11245}
11246
11247unsafe fn sys_clock_getres(clockid: c_int, ts: *mut timespec) -> i64 {
11252 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, clockid as i64, ts as i64)
11253}
11254
11255unsafe fn sys_clock_settime(clockid: c_int, ts: *const timespec) -> i64 {
11256 <Arch as Syscalls>::syscall2(SYS_CLOCK_SETTIME, clockid as i64, ts as i64)
11257}
11258
11259unsafe fn sys_clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> i64 {
11260 <Arch as Syscalls>::syscall4(SYS_CLOCK_NANOSLEEP, clockid as i64, flags as i64, req as i64, rem as i64)
11261}
11262
11263#[no_mangle]
11264pub unsafe extern "C" fn clock_getres(clockid: c_int, ts: *mut timespec) -> c_int { if sys_clock_getres(clockid, ts) < 0 { -1 } else { 0 } }
11265
11266#[no_mangle]
11267pub unsafe extern "C" fn clock_settime(clockid: c_int, ts: *const timespec) -> c_int { if sys_clock_settime(clockid, ts) < 0 { -1 } else { 0 } }
11268
11269#[no_mangle]
11270pub unsafe extern "C" fn clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> c_int {
11271 let r = sys_clock_nanosleep(clockid, flags, req, rem);
11272 if r < 0 { (-r) as c_int } else { 0 }
11273}
11274
11275#[no_mangle]
11276pub unsafe extern "C" fn gettimeofday(tv: *mut timeval, _tz: *mut c_void) -> c_int {
11277 if tv.is_null() { return 0; }
11278 let mut ts: timespec = core::mem::zeroed();
11279 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
11280 (*tv).tv_sec = ts.tv_sec;
11281 (*tv).tv_usec = ts.tv_nsec / 1000;
11282 0
11283}
11284
11285fn is_leap_year(y: i32) -> bool {
11290 let yr = if y > i32::MAX - 1900 { y - 2000 } else { y + 1900 };
11291 yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0)
11292}
11293
11294fn week_num(tm: &tm) -> i32 {
11295 let mut val = (tm.tm_yday + 7 - ((tm.tm_wday + 6) % 7)) / 7;
11296 if (tm.tm_wday + 371 - tm.tm_yday - 2).rem_euclid(7) <= 2 { val += 1; }
11297 if val == 0 {
11298 val = 52;
11299 let dec31 = (tm.tm_wday + 7 - tm.tm_yday - 1).rem_euclid(7);
11300 if dec31 == 4 || (dec31 == 5 && is_leap_year(tm.tm_year % 400 - 1)) { val += 1; }
11301 } else if val == 53 {
11302 let jan1 = (tm.tm_wday + 371 - tm.tm_yday).rem_euclid(7);
11303 if jan1 != 4 && (jan1 != 3 || !is_leap_year(tm.tm_year)) { val = 1; }
11304 }
11305 val
11306}
11307
11308const ABDAY_1: c_int = 0x20000;
11310const DAY_1: c_int = 0x20007;
11311const ABMON_1: c_int = 0x2000E;
11312const MON_1: c_int = 0x2001A;
11313const AM_STR_LI: c_int = 0x20026;
11314const PM_STR_LI: c_int = 0x20027;
11315const D_T_FMT: c_int = 0x20028;
11316const D_FMT: c_int = 0x20029;
11317const T_FMT: c_int = 0x2002A;
11318const T_FMT_AMPM: c_int = 0x2002B;
11319
11320unsafe fn num_fmt(buf: &mut [u8; 100], val: i64, pad: u8, width: usize) -> (*const u8, usize) {
11323 let negative = val < 0;
11324 let mut v = if negative { -val as u64 } else { val as u64 };
11325 let mut tmp = [0u8; 24];
11326 let mut pos = 24usize;
11327 if v == 0 { pos -= 1; tmp[pos] = b'0'; }
11328 while v > 0 { pos -= 1; tmp[pos] = b'0' + (v % 10) as u8; v /= 10; }
11329 let digits = 24 - pos;
11330 let sign_chars = if negative { 1 } else { 0 };
11331 let needed = sign_chars + digits;
11332 let fill = if width > needed { width - needed } else { 0 };
11333 let total = fill + needed;
11334 let mut p = 0usize;
11335 match pad {
11336 b'-' => { }
11337 b'_' => {
11338 for _ in 0..fill { buf[p] = b' '; p += 1; }
11339 if negative { buf[p] = b'-'; p += 1; }
11340 }
11341 _ => {
11342 if negative { buf[p] = b'-'; p += 1; }
11343 for _ in 0..fill { buf[p] = b'0'; p += 1; }
11344 }
11345 }
11346 for i in 0..digits { buf[p] = tmp[pos + i]; p += 1; }
11347 (buf.as_ptr(), total)
11348}
11349
11350unsafe fn str_to_buf(buf: &mut [u8; 100], s: *const c_char) -> (*const u8, usize) {
11352 let mut k = 0usize;
11353 while *s.add(k) != 0 {
11354 buf[k] = *s.add(k) as u8;
11355 k += 1;
11356 }
11357 (buf.as_ptr(), k)
11358}
11359
11360unsafe fn __strftime_fmt_1(buf: &mut [u8; 100], f: u8, tm: *const tm, pad: u8) -> (*const u8, usize) {
11363 let mut val: i64;
11364 let mut width: usize = 2;
11365 let mut def_pad: u8 = b'0';
11366 let fmt: *const c_char;
11367
11368 match f {
11369 b'a' => {
11370 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
11371 let p = nl_langinfo(ABDAY_1 + (*tm).tm_wday);
11372 return str_to_buf(buf, p);
11373 }
11374 b'A' => {
11375 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
11376 let p = nl_langinfo(DAY_1 + (*tm).tm_wday);
11377 return str_to_buf(buf, p);
11378 }
11379 b'h' | b'b' => {
11380 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11381 let p = nl_langinfo(ABMON_1 + (*tm).tm_mon);
11382 return str_to_buf(buf, p);
11383 }
11384 b'B' => {
11385 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11386 let p = nl_langinfo(MON_1 + (*tm).tm_mon);
11387 return str_to_buf(buf, p);
11388 }
11389 b'c' => {
11390 let p = nl_langinfo(D_T_FMT);
11391 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11392 return (buf.as_ptr(), l);
11393 }
11394 b'C' => {
11395 val = (1900i64 + (*tm).tm_year as i64) / 100;
11396 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11397 }
11398 b'e' => { def_pad = b'_'; }
11399 b'd' => {
11400 val = (*tm).tm_mday as i64;
11401 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11402 }
11403 b'D' => {
11404 fmt = b"%m/%d/%y\0".as_ptr() as *const c_char;
11405 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11406 return (buf.as_ptr(), l);
11407 }
11408 b'F' => {
11409 fmt = b"%Y-%m-%d\0".as_ptr() as *const c_char;
11410 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11411 return (buf.as_ptr(), l);
11412 }
11413 b'g' | b'G' => {
11414 val = (*tm).tm_year as i64 + 1900;
11415 if (*tm).tm_yday < 3 && week_num(&*tm) != 1 { val -= 1; }
11416 else if (*tm).tm_yday > 360 && week_num(&*tm) == 1 { val += 1; }
11417 if f == b'g' { val %= 100; }
11418 else { width = 4; }
11419 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11420 }
11421 b'H' => {
11422 val = (*tm).tm_hour as i64;
11423 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11424 }
11425 b'I' => {
11426 val = (*tm).tm_hour as i64;
11427 if val == 0 { val = 12; }
11428 else if val > 12 { val -= 12; }
11429 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11430 }
11431 b'j' => {
11432 val = (*tm).tm_yday as i64 + 1;
11433 width = 3;
11434 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11435 }
11436 b'm' => {
11437 val = (*tm).tm_mon as i64 + 1;
11438 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11439 }
11440 b'M' => {
11441 val = (*tm).tm_min as i64;
11442 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11443 }
11444 b'n' => { buf[0] = b'\n'; return (buf.as_ptr(), 1); }
11445 b'p' => {
11446 let p = if (*tm).tm_hour >= 12 { nl_langinfo(PM_STR_LI) } else { nl_langinfo(AM_STR_LI) };
11447 return str_to_buf(buf, p);
11448 }
11449 b'r' => {
11450 let p = nl_langinfo(T_FMT_AMPM);
11451 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11452 return (buf.as_ptr(), l);
11453 }
11454 b'R' => {
11455 fmt = b"%H:%M\0".as_ptr() as *const c_char;
11456 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11457 return (buf.as_ptr(), l);
11458 }
11459 b's' => {
11460 val = tm_to_secs(tm) - (*tm).tm_gmtoff as i64;
11461 width = 1;
11462 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11463 }
11464 b'S' => {
11465 val = (*tm).tm_sec as i64;
11466 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11467 }
11468 b't' => { buf[0] = b'\t'; return (buf.as_ptr(), 1); }
11469 b'T' => {
11470 fmt = b"%H:%M:%S\0".as_ptr() as *const c_char;
11471 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11472 return (buf.as_ptr(), l);
11473 }
11474 b'u' => {
11475 val = if (*tm).tm_wday != 0 { (*tm).tm_wday as i64 } else { 7 };
11476 width = 1;
11477 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11478 }
11479 b'U' => {
11480 val = ((*tm).tm_yday as u64 + 7 - (*tm).tm_wday as u64) as i64 / 7;
11481 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11482 }
11483 b'W' => {
11484 val = ((*tm).tm_yday as u64 + 7 - ((*tm).tm_wday as u64 + 6) % 7) as i64 / 7;
11485 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11486 }
11487 b'V' => {
11488 val = week_num(&*tm) as i64;
11489 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11490 }
11491 b'w' => {
11492 val = (*tm).tm_wday as i64;
11493 width = 1;
11494 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11495 }
11496 b'x' => {
11497 let p = nl_langinfo(D_FMT);
11498 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11499 return (buf.as_ptr(), l);
11500 }
11501 b'X' => {
11502 let p = nl_langinfo(T_FMT);
11503 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11504 return (buf.as_ptr(), l);
11505 }
11506 b'y' => {
11507 val = (1900i64 + (*tm).tm_year as i64) % 100;
11508 if val < 0 { val = -val; }
11509 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11510 }
11511 b'Y' => {
11512 val = (*tm).tm_year as i64 + 1900;
11513 if val >= 10000 {
11514 let mut tmp = [0u8; 100];
11515 let (_, k) = num_fmt(&mut tmp, val, b'-', 1);
11516 buf[0] = b'+';
11517 for i in 0..k { buf[1 + i] = tmp[i]; }
11518 return (buf.as_ptr(), 1 + k);
11519 }
11520 width = 4;
11521 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11522 }
11523 b'z' => {
11524 if (*tm).tm_isdst < 0 { return (b"\0".as_ptr(), 0); }
11525 let gmtoff = (*tm).tm_gmtoff as i64;
11526 let sign = if gmtoff >= 0 { b'+' } else { b'-' };
11527 let off = if gmtoff < 0 { -gmtoff } else { gmtoff };
11528 let hh = (off / 3600) as i32;
11529 let mm = ((off % 3600) / 60) as i32;
11530 buf[0] = sign;
11531 buf[1] = b'0' + (hh / 10) as u8;
11532 buf[2] = b'0' + (hh % 10) as u8;
11533 buf[3] = b'0' + (mm / 10) as u8;
11534 buf[4] = b'0' + (mm % 10) as u8;
11535 return (buf.as_ptr(), 5);
11536 }
11537 b'Z' => {
11538 if (*tm).tm_isdst < 0 || (*tm).tm_zone.is_null() { return (b"\0".as_ptr(), 0); }
11539 return str_to_buf(buf, (*tm).tm_zone);
11540 }
11541 b'%' => { buf[0] = b'%'; return (buf.as_ptr(), 1); }
11542 _ => { return (core::ptr::null(), 0); }
11543 }
11544 val = (*tm).tm_mday as i64;
11546 num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width)
11547}
11548
11549unsafe fn __strftime_l(s: *mut c_char, n: usize, f: *const c_char, tm: *const tm) -> usize {
11550 let mut l: usize = 0;
11551 let mut fi: usize = 0;
11552 while l < n {
11553 let ch = *f.add(fi) as u8;
11554 if ch == 0 {
11555 *s.add(l) = 0;
11556 return l;
11557 }
11558 if ch != b'%' {
11559 *s.add(l) = ch as c_char;
11560 l += 1;
11561 fi += 1;
11562 continue;
11563 }
11564 fi += 1;
11565 let mut pad: u8 = 0;
11567 let fc = *f.add(fi) as u8;
11568 if fc == b'-' || fc == b'_' || fc == b'0' { pad = fc; fi += 1; }
11569 let plus = *f.add(fi) as u8 == b'+';
11570 if plus { fi += 1; }
11571 let mut width: usize = 0;
11573 let mut p_idx = fi;
11574 {
11575 let fc2 = *f.add(fi) as u8;
11576 if fc2 >= b'0' && fc2 <= b'9' {
11577 let mut w: usize = 0;
11578 while { let c = *f.add(p_idx) as u8; c >= b'0' && c <= b'9' } {
11579 w = w * 10 + (*f.add(p_idx) as usize - b'0' as usize);
11580 p_idx += 1;
11581 }
11582 width = w;
11583 }
11584 }
11585 let spec_ch = *f.add(p_idx) as u8;
11586 if spec_ch == b'C' || spec_ch == b'F' || spec_ch == b'G' || spec_ch == b'Y' {
11587 if width == 0 && p_idx != fi { width = 1; }
11588 } else {
11589 width = 0;
11590 }
11591 fi = p_idx;
11592 let fc3 = *f.add(fi) as u8;
11594 if fc3 == b'E' || fc3 == b'O' { fi += 1; }
11595 let fch = *f.add(fi) as u8;
11596 let mut buf = [0u8; 100];
11598 let (t, k) = __strftime_fmt_1(&mut buf, fch, tm, pad);
11599 if t.is_null() { break; }
11600 let mut k = k;
11601 let mut t = t;
11602 if width != 0 {
11603 if *t == b'+' || *t == b'-' { t = t.add(1); k -= 1; }
11605 while k > 0 && *t == b'0' && k > 1 && *t.add(1) >= b'0' && *t.add(1) <= b'9' {
11606 t = t.add(1); k -= 1;
11607 }
11608 if width < k { width = k; }
11609 let mut d: usize = 0;
11610 while d < k && *t.add(d) >= b'0' && *t.add(d) <= b'9' { d += 1; }
11611 if (*tm).tm_year < -1900 {
11612 if l < n { *s.add(l) = b'-' as c_char; }
11613 l += 1;
11614 width -= 1;
11615 } else if plus && d + (width - k) >= (if spec_ch == b'C' { 3 } else { 5 }) {
11616 if l < n { *s.add(l) = b'+' as c_char; }
11617 l += 1;
11618 width -= 1;
11619 }
11620 while width > k && l < n {
11621 *s.add(l) = b'0' as c_char;
11622 l += 1;
11623 width -= 1;
11624 }
11625 }
11626 let copy = if k > n - l { n - l } else { k };
11627 core::ptr::copy_nonoverlapping(t, s.add(l) as *mut u8, copy);
11628 l += copy;
11629 fi += 1;
11630 }
11631 if n > 0 {
11632 if l == n { l = n - 1; }
11633 *s.add(l) = 0;
11634 }
11635 0
11636}
11637
11638#[no_mangle]
11639pub unsafe extern "C" fn strftime(s: *mut c_char, maxsize: usize, fmt: *const c_char, tm: *const tm) -> usize {
11640 __strftime_l(s, maxsize, fmt, tm)
11641}
11642
11643unsafe fn match_prefix(s: *const u8, prefix: &[u8]) -> bool {
11648 for i in 0..prefix.len() {
11649 if *s.add(i) == 0 || *s.add(i) != prefix[i] { return false; }
11650 }
11651 true
11652}
11653
11654unsafe fn match_ci_prefix(s: *const u8, prefix: &[u8]) -> bool {
11655 for i in 0..prefix.len() {
11656 let c = *s.add(i);
11657 if c == 0 { return false; }
11658 if c.to_ascii_lowercase() != prefix[i].to_ascii_lowercase() { return false; }
11659 }
11660 true
11661}
11662
11663unsafe fn parse_int(p: *const u8, max_digits: usize) -> (i32, *const u8) {
11664 let mut val = 0i32;
11665 let mut np = p;
11666 let mut count = 0;
11667 while *np >= b'0' && *np <= b'9' && count < max_digits {
11668 val = val * 10 + (*np - b'0') as i32;
11669 np = np.add(1);
11670 count += 1;
11671 }
11672 if count == 0 { (0, p) } else { (val, np) }
11673}
11674
11675unsafe fn parse_range(p: *const u8, min: i32, max: i32) -> (i32, *const u8) {
11676 let (val, np) = parse_int(p, 4);
11677 if np == p || val < min || val > max { (0, p) } else { (val, np) }
11678}
11679
11680fn is_ascii_space(c: u8) -> bool {
11681 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0c || c == 0x0b
11682}
11683
11684#[no_mangle]
11685pub unsafe extern "C" fn strptime(s: *const c_char, fmt: *const c_char, tm: *mut tm) -> *mut c_char {
11686 let mut p = s as *const u8;
11687 let mut f = fmt as *const u8;
11688 let mut want_century = 0i32;
11689 let mut century = 0i32;
11690 let mut relyear = 0i32;
11691 while *f != 0 {
11692 if *f != b'%' {
11693 if is_ascii_space(*f) {
11694 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
11695 } else {
11696 if *p != *f { return core::ptr::null_mut(); }
11697 p = p.add(1);
11698 }
11699 f = f.add(1);
11700 continue;
11701 }
11702 f = f.add(1);
11703 if *f == b'+' { f = f.add(1); }
11704 while *f >= b'0' && *f <= b'9' { f = f.add(1); }
11705 if *f == b'E' || *f == b'O' { f = f.add(1); }
11706 match *f {
11707 b'a' | b'A' => {
11708 let mut found = false;
11709 for i in 0..7 {
11710 let names: [&[u8]; 7] = [b"Sunday", b"Monday", b"Tuesday", b"Wednesday", b"Thursday", b"Friday", b"Saturday"];
11711 let snames: [&[u8]; 7] = [b"Sun", b"Mon", b"Tue", b"Wed", b"Thu", b"Fri", b"Sat"];
11712 if match_prefix(p, names[i]) { (*tm).tm_wday = i as c_int; p = p.add(names[i].len()); found = true; break; }
11713 if match_prefix(p, snames[i]) { (*tm).tm_wday = i as c_int; p = p.add(snames[i].len()); found = true; break; }
11714 }
11715 if !found { return core::ptr::null_mut(); }
11716 }
11717 b'b' | b'B' | b'h' => {
11718 let mut found = false;
11719 for i in 0..12 {
11720 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"];
11721 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"];
11722 if match_prefix(p, names[i]) { (*tm).tm_mon = i as c_int; p = p.add(names[i].len()); found = true; break; }
11723 if match_prefix(p, snames[i]) { (*tm).tm_mon = i as c_int; p = p.add(snames[i].len()); found = true; break; }
11724 }
11725 if !found { return core::ptr::null_mut(); }
11726 }
11727 b'C' => {
11728 let (v, np) = parse_int(p, 2);
11729 if np == p { return core::ptr::null_mut(); }
11730 century = v;
11731 want_century |= 2;
11732 p = np;
11733 }
11734 b'd' | b'e' => {
11735 let (v, np) = parse_range(p, 1, 31);
11736 if np == p { return core::ptr::null_mut(); }
11737 (*tm).tm_mday = v;
11738 p = np;
11739 }
11740 b'D' => {
11741 let r = strptime(p as *const c_char, b"%m/%d/%y\0".as_ptr() as *const c_char, tm);
11742 if r.is_null() { return core::ptr::null_mut(); }
11743 p = r as *const u8;
11744 }
11745 b'F' => {
11746 let (yv, ynp) = parse_int(p, 4);
11747 if ynp == p { return core::ptr::null_mut(); }
11748 (*tm).tm_year = yv - 1900;
11749 p = ynp;
11750 if *p != b'-' { return core::ptr::null_mut(); }
11751 p = p.add(1);
11752 let (mv, mnp) = parse_range(p, 1, 12);
11753 if mnp == p { return core::ptr::null_mut(); }
11754 (*tm).tm_mon = mv - 1;
11755 p = mnp;
11756 if *p != b'-' { return core::ptr::null_mut(); }
11757 p = p.add(1);
11758 let (dv, dnp) = parse_range(p, 1, 31);
11759 if dnp == p { return core::ptr::null_mut(); }
11760 (*tm).tm_mday = dv;
11761 p = dnp;
11762 }
11763 b'H' | b'I' => {
11764 let (v, np) = parse_range(p, 0, 23);
11765 if np == p { return core::ptr::null_mut(); }
11766 (*tm).tm_hour = v;
11767 p = np;
11768 }
11769 b'j' => {
11770 let (v, np) = parse_range(p, 1, 366);
11771 if np == p { return core::ptr::null_mut(); }
11772 (*tm).tm_yday = v - 1;
11773 p = np;
11774 }
11775 b'm' => {
11776 let (v, np) = parse_range(p, 1, 12);
11777 if np == p { return core::ptr::null_mut(); }
11778 (*tm).tm_mon = v - 1;
11779 p = np;
11780 }
11781 b'M' => {
11782 let (v, np) = parse_range(p, 0, 59);
11783 if np == p { return core::ptr::null_mut(); }
11784 (*tm).tm_min = v;
11785 p = np;
11786 }
11787 b'n' | b't' => {
11788 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
11789 }
11790 b'p' => {
11791 if match_ci_prefix(p, b"AM") {
11792 if (*tm).tm_hour == 12 { (*tm).tm_hour = 0; }
11793 p = p.add(2);
11794 } else if match_ci_prefix(p, b"PM") {
11795 if (*tm).tm_hour < 12 { (*tm).tm_hour += 12; }
11796 p = p.add(2);
11797 } else { return core::ptr::null_mut(); }
11798 }
11799 b'r' => {
11800 let r = strptime(p as *const c_char, b"%I:%M:%S %p\0".as_ptr() as *const c_char, tm);
11801 if r.is_null() { return core::ptr::null_mut(); }
11802 p = r as *const u8;
11803 }
11804 b'R' => {
11805 let r = strptime(p as *const c_char, b"%H:%M\0".as_ptr() as *const c_char, tm);
11806 if r.is_null() { return core::ptr::null_mut(); }
11807 p = r as *const u8;
11808 }
11809 b's' => {
11810 let neg = if *p == b'-' { p = p.add(1); true } else { false };
11811 if *p < b'0' || *p > b'9' { return core::ptr::null_mut(); }
11812 let mut val = 0i64;
11813 while *p >= b'0' && *p <= b'9' {
11814 val = val * 10 + (*p - b'0') as i64;
11815 p = p.add(1);
11816 }
11817 if neg { val = -val; }
11818 secs_to_tm(val, &mut *tm);
11819 }
11820 b'S' => {
11821 let (v, np) = parse_range(p, 0, 60);
11822 if np == p { return core::ptr::null_mut(); }
11823 (*tm).tm_sec = v;
11824 p = np;
11825 }
11826 b'T' => {
11827 let r = strptime(p as *const c_char, b"%H:%M:%S\0".as_ptr() as *const c_char, tm);
11828 if r.is_null() { return core::ptr::null_mut(); }
11829 p = r as *const u8;
11830 }
11831 b'U' | b'W' => {
11832 let (_, np) = parse_range(p, 0, 53);
11833 if np == p { return core::ptr::null_mut(); }
11834 p = np;
11835 }
11836 b'V' => {
11837 let (_, np) = parse_range(p, 1, 53);
11838 if np == p { return core::ptr::null_mut(); }
11839 p = np;
11840 }
11841 b'w' => {
11842 let (v, np) = parse_range(p, 0, 6);
11843 if np == p { return core::ptr::null_mut(); }
11844 (*tm).tm_wday = v;
11845 p = np;
11846 }
11847 b'y' => {
11848 let (v, np) = parse_int(p, 2);
11849 if np == p { return core::ptr::null_mut(); }
11850 relyear = v;
11851 want_century |= 1;
11852 p = np;
11853 }
11854 b'Y' => {
11855 let neg = if *p == b'-' { p = p.add(1); true } else { false };
11856 let (v, np) = parse_int(p, 4);
11857 if np == p { return core::ptr::null_mut(); }
11858 (*tm).tm_year = if neg { -(v + 1900) } else { v - 1900 };
11859 want_century = 0;
11860 p = np;
11861 }
11862 b'z' => {
11863 if *p != b'+' && *p != b'-' { return core::ptr::null_mut(); }
11864 let neg = *p == b'-';
11865 p = p.add(1);
11866 let mut off = 0i64;
11867 let mut digits = 0;
11868 while digits < 4 && *p >= b'0' && *p <= b'9' {
11869 off = off * 10 + (*p - b'0') as i64;
11870 p = p.add(1);
11871 digits += 1;
11872 }
11873 if digits == 0 { return core::ptr::null_mut(); }
11874 let (hh, mm) = if digits <= 2 { (off, 0i64) } else { (off / 100, off % 100) };
11875 (*tm).tm_gmtoff = (hh * 3600 + mm * 60) * if neg { -1 } else { 1 };
11876 }
11877 b'%' => {
11878 if *p != b'%' { return core::ptr::null_mut(); }
11879 p = p.add(1);
11880 }
11881 _ => { return core::ptr::null_mut(); }
11882 }
11883 f = f.add(1);
11884 }
11885 if want_century != 0 {
11886 (*tm).tm_year = relyear;
11887 if want_century & 2 != 0 { (*tm).tm_year += century * 100 - 1900; }
11888 else if (*tm).tm_year <= 68 { (*tm).tm_year += 100; }
11889 }
11890 p as *mut c_char
11891}
11892
11893#[no_mangle]
11898pub static mut daylight: c_int = 0;
11899#[no_mangle]
11900pub static mut timezone: c_long = 0;
11901#[no_mangle]
11902pub 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];
11903
11904#[no_mangle]
11905pub unsafe extern "C" fn tzset() {
11906 daylight = 0;
11907 timezone = 0;
11908}
11909
11910#[no_mangle]
11915pub unsafe extern "C" fn system(cmd: *const c_char) -> c_int {
11916 if cmd.is_null() {
11917 let pid = sys_fork();
11919 if pid == 0 {
11920 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
11921 let dash_c = b"-c\0".as_ptr() as *const c_char;
11922 let exit0 = b"exit 0\0".as_ptr() as *const c_char;
11923 let argv = [b"sh\0".as_ptr() as *const c_char, dash_c, exit0, core::ptr::null()];
11924 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
11925 _exit(127);
11926 }
11927 if pid < 0 { return -1; }
11928 let mut status: c_int = 0;
11929 loop {
11930 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
11931 if r >= 0 { return status; }
11932 if r != -4 { return -1; } }
11934 }
11935
11936 let sa_ignore = sigaction {
11937 sa_handler: SIG_IGN,
11938 sa_flags: SA_RESTORER,
11939 sa_restorer: sig_restorer as *const () as usize,
11940 sa_mask: [0],
11941 };
11942 let mut oldint: sigaction = core::mem::zeroed();
11943 let mut oldquit: sigaction = core::mem::zeroed();
11944
11945 sys_rt_sigaction(SIGINT, &sa_ignore, &mut oldint, 8);
11946 sys_rt_sigaction(SIGQUIT, &sa_ignore, &mut oldquit, 8);
11947
11948 let mut block_set: SigSetT = 0;
11949 block_set |= 1u64 << (SIGCHLD - 1);
11950 let mut oldmask: SigSetT = 0;
11951 sys_rt_sigprocmask(SIG_BLOCK, &block_set, &mut oldmask, 8);
11952
11953 let pid = sys_fork();
11954
11955 if pid == 0 {
11956 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
11957 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
11958 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
11959
11960 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
11961 let argv = [
11962 b"sh\0".as_ptr() as *const c_char,
11963 b"-c\0".as_ptr() as *const c_char,
11964 cmd,
11965 core::ptr::null(),
11966 ];
11967 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
11968 _exit(127);
11969 }
11970
11971 let mut status: c_int = -1;
11972 if pid > 0 {
11973 loop {
11974 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
11975 if r >= 0 { break; }
11976 if r != -4 { break; } }
11978 }
11979
11980 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
11981 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
11982 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
11983
11984 status
11985}
11986
11987const EPERM_VAL: c_int = 1;
11992const ENOENT_VAL: c_int = 2;
11993const ESRCH_VAL: c_int = 3;
11994const EINTR_VAL: c_int = 4;
11995const EIO_VAL: c_int = 5;
11996const ENXIO_VAL: c_int = 6;
11997const E2BIG_VAL: c_int = 7;
11998const ENOEXEC_VAL: c_int = 8;
11999const EBADF_VAL: c_int = 9;
12000const ECHILD_VAL: c_int = 10;
12001const EAGAIN_VAL: c_int = 11;
12002const ENOMEM_VAL: c_int = 12;
12003const EACCES_VAL: c_int = 13;
12004const EFAULT_VAL: c_int = 14;
12005const ENOTBLK_VAL: c_int = 15;
12006const EBUSY_VAL: c_int = 16;
12007const EEXIST_VAL: c_int = 17;
12008const EXDEV_VAL: c_int = 18;
12009const ENODEV_VAL: c_int = 19;
12010const ENOTDIR_VAL: c_int = 20;
12011const EISDIR_VAL: c_int = 21;
12012const EINVAL_VAL: c_int = 22;
12013const ENFILE_VAL: c_int = 23;
12014const EMFILE_VAL: c_int = 24;
12015const ENOTTY_VAL: c_int = 25;
12016const ETXTBSY_VAL: c_int = 26;
12017const EFBIG_VAL: c_int = 27;
12018const ENOSPC_VAL: c_int = 28;
12019const ESPIPE_VAL: c_int = 29;
12020const EROFS_VAL: c_int = 30;
12021const EMLINK_VAL: c_int = 31;
12022const EPIPE_VAL: c_int = 32;
12023const EDOM_VAL: c_int = 33;
12024const ERANGE_VAL: c_int = 34;
12025const EDEADLK_VAL: c_int = 35;
12026const ENAMETOOLONG_VAL: c_int = 36;
12027const ENOLCK_VAL: c_int = 37;
12028const ENOSYS_VAL: c_int = 38;
12029const ENOTEMPTY_VAL: c_int = 39;
12030const ELOOP_VAL: c_int = 40;
12031const EWOULDBLOCK_VAL: c_int = 11;
12032const ENOMSG_VAL: c_int = 42;
12033const EIDRM_VAL: c_int = 43;
12034const ECHRNG_VAL: c_int = 44;
12035const EL2NSYNC_VAL: c_int = 45;
12036const EL3HLT_VAL: c_int = 46;
12037const EL3RST_VAL: c_int = 47;
12038const ELNRNG_VAL: c_int = 48;
12039const EUNATCH_VAL: c_int = 49;
12040const ENOCSI_VAL: c_int = 50;
12041const EL2HLT_VAL: c_int = 51;
12042const EBADE_VAL: c_int = 52;
12043const EBADR_VAL: c_int = 53;
12044const EXFULL_VAL: c_int = 54;
12045const ENOANO_VAL: c_int = 55;
12046const EBADRQC_VAL: c_int = 56;
12047const EBADSLT_VAL: c_int = 57;
12048const EBFONT_VAL: c_int = 59;
12049const ENOSTR_VAL: c_int = 60;
12050const ENODATA_VAL: c_int = 61;
12051const ETIME_VAL: c_int = 62;
12052const ENOSR_VAL: c_int = 63;
12053const ENONET_VAL: c_int = 64;
12054const ENOPKG_VAL: c_int = 65;
12055const EREMOTE_VAL: c_int = 66;
12056const ENOLINK_VAL: c_int = 67;
12057const EADV_VAL: c_int = 68;
12058const ESRMNT_VAL: c_int = 69;
12059const ECOMM_VAL: c_int = 70;
12060const EPROTO_VAL: c_int = 71;
12061const EMULTIHOP_VAL: c_int = 72;
12062const EDOTDOT_VAL: c_int = 73;
12063const EBADMSG_VAL: c_int = 74;
12064const EOVERFLOW_VAL: c_int = 75;
12065const ENOTUNIQ_VAL: c_int = 76;
12066const EBADFD_VAL: c_int = 77;
12067const EREMCHG_VAL: c_int = 78;
12068const ELIBACC_VAL: c_int = 79;
12069const ELIBBAD_VAL: c_int = 80;
12070const ELIBSCN_VAL: c_int = 81;
12071const ELIBMAX_VAL: c_int = 82;
12072const ELIBEXEC_VAL: c_int = 83;
12073const EILSEQ_VAL: c_int = 84;
12074const ERESTART_VAL: c_int = 85;
12075const ESTRPIPE_VAL: c_int = 86;
12076const EUSERS_VAL: c_int = 87;
12077const ENOTSOCK_VAL: c_int = 88;
12078const EDESTADDRREQ_VAL: c_int = 89;
12079const EMSGSIZE_VAL: c_int = 90;
12080const EPROTOTYPE_VAL: c_int = 91;
12081const ENOPROTOOPT_VAL: c_int = 92;
12082const EPROTONOSUPPORT_VAL: c_int = 93;
12083const ESOCKTNOSUPPORT_VAL: c_int = 94;
12084const EOPNOTSUPP_VAL: c_int = 95;
12085const ENOTSUP_VAL: c_int = 95;
12086const EPFNOSUPPORT_VAL: c_int = 96;
12087const EAFNOSUPPORT_VAL: c_int = 97;
12088const EADDRINUSE_VAL: c_int = 98;
12089const EADDRNOTAVAIL_VAL: c_int = 99;
12090const ENETDOWN_VAL: c_int = 100;
12091const ENETUNREACH_VAL: c_int = 101;
12092const ENETRESET_VAL: c_int = 102;
12093const ECONNABORTED_VAL: c_int = 103;
12094const ECONNRESET_VAL: c_int = 104;
12095const ENOBUFS_VAL: c_int = 105;
12096const EISCONN_VAL: c_int = 106;
12097const ENOTCONN_VAL: c_int = 107;
12098const ESHUTDOWN_VAL: c_int = 108;
12099const ETOOMANYREFS_VAL: c_int = 109;
12100const ETIMEDOUT_VAL: c_int = 110;
12101const ECONNREFUSED_VAL: c_int = 111;
12102const EHOSTDOWN_VAL: c_int = 112;
12103const EHOSTUNREACH_VAL: c_int = 113;
12104const EALREADY_VAL: c_int = 114;
12105const EINPROGRESS_VAL: c_int = 115;
12106const ESTALE_VAL: c_int = 116;
12107const EUCLEAN_VAL: c_int = 117;
12108const ENOTNAM_VAL: c_int = 118;
12109const ENAVAIL_VAL: c_int = 119;
12110const EISNAM_VAL: c_int = 120;
12111const EREMOTEIO_VAL: c_int = 121;
12112const EDQUOT_VAL: c_int = 122;
12113const ENOMEDIUM_VAL: c_int = 123;
12114const EMEDIUMTYPE_VAL: c_int = 124;
12115const ECANCELED_VAL: c_int = 125;
12116const ENOKEY_VAL: c_int = 126;
12117const EKEYEXPIRED_VAL: c_int = 127;
12118const EKEYREVOKED_VAL: c_int = 128;
12119const EKEYREJECTED_VAL: c_int = 129;
12120const EOWNERDEAD_VAL: c_int = 130;
12121const ENOTRECOVERABLE_VAL: c_int = 131;
12122const ERFKILL_VAL: c_int = 132;
12123const EHWPOISON_VAL: c_int = 133;
12124
12125static ERR_STRS: [&[u8]; 134] = [
12127 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", ];
12262
12263#[no_mangle]
12264pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char {
12265 if errnum < 0 || errnum as usize >= ERR_STRS.len() {
12266 static mut UNKNOWN_BUF: [c_char; 32] = [0; 32];
12268 let prefix = b"Unknown error \0";
12269 let mut i = 0;
12270 while prefix[i] != 0 {
12271 UNKNOWN_BUF[i] = prefix[i] as c_char;
12272 i += 1;
12273 }
12274 let (buf, len) = format_u64(errnum as u64);
12275 for j in 0..len {
12276 UNKNOWN_BUF[i] = buf[20 - len + j] as c_char;
12277 i += 1;
12278 }
12279 UNKNOWN_BUF[i] = 0;
12280 return core::ptr::addr_of_mut!(UNKNOWN_BUF).cast::<c_char>();
12281 }
12282 ERR_STRS[errnum as usize].as_ptr() as *mut c_char
12283}
12284
12285#[no_mangle]
12286pub unsafe extern "C" fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: usize) -> c_int {
12287 let s = strerror(errnum);
12288 let slen = strlen(s as *const c_char);
12289 if slen >= buflen {
12290 if buflen > 0 {
12291 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, buflen - 1);
12292 *buf.add(buflen - 1) = 0;
12293 }
12294 return 34; }
12296 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, slen + 1);
12297 0
12298}
12299
12300#[no_mangle]
12302pub static mut environ: *mut *mut c_char = core::ptr::null_mut();
12303
12304unsafe fn sync_environ() {
12306 environ = __environ;
12307}
12308
12309#[inline]
12314unsafe fn sys_dup(oldfd: i32) -> i64 {
12315 <Arch as Syscalls>::syscall1(SYS_DUP, oldfd as i64)
12316}
12317
12318#[inline]unsafe fn sys_dup2(oldfd: i32, newfd: i32) -> i64 {
12319 sys_dup3(oldfd, newfd, 0)
12321}
12322
12323#[inline]
12324unsafe fn sys_access(path: *const u8, mode: i32) -> i64 {
12325 <Arch as Syscalls>::syscall4(SYS_FACCESSAT, AT_FDCWD as i64, path as i64, mode as i64, 0)
12326}
12327
12328#[inline]unsafe fn sys_unlink(path: *const u8) -> i64 {
12329 sys_unlinkat(AT_FDCWD, path, 0)
12330}
12331
12332#[inline]unsafe fn sys_rmdir(path: *const u8) -> i64 {
12333 sys_unlinkat(AT_FDCWD, path, 512) }
12335
12336#[inline]
12337unsafe fn sys_chdir(path: *const u8) -> i64 {
12338 <Arch as Syscalls>::syscall1(SYS_CHDIR, path as i64)
12339}
12340
12341#[inline]
12342unsafe fn sys_getcwd(buf: *mut u8, size: usize) -> i64 {
12343 <Arch as Syscalls>::syscall2(SYS_GETCWD, buf as i64, size as i64)
12344}
12345
12346#[inline]
12347unsafe fn sys_sethostname(name: *const u8, len: usize) -> i64 {
12348 <Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64)
12349}
12350
12351#[inline]
12352unsafe fn sys_gethostname(buf: *mut u8, len: usize) -> i64 {
12353 #[repr(C)]
12354 struct UtsName {
12355 sysname: [u8; 65],
12356 nodename: [u8; 65],
12357 release: [u8; 65],
12358 version: [u8; 65],
12359 machine: [u8; 65],
12360 domainname: [u8; 65],
12361 }
12362 let mut uts: UtsName = core::mem::zeroed();
12363 let result = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
12364 if result < 0 {
12365 return result;
12366 }
12367 let nlen = strlen(uts.nodename.as_ptr() as *const c_char);
12368 let copylen = if nlen < len { nlen } else { if len > 0 { len - 1 } else { 0 } };
12369 core::ptr::copy_nonoverlapping(uts.nodename.as_ptr(), buf, copylen);
12370 if len > 0 { *buf.add(copylen) = 0; }
12371 0
12372}
12373
12374unsafe fn sys_truncate(path: *const u8, length: i64) -> i64 {
12375 <Arch as Syscalls>::syscall2(SYS_TRUNCATE, path as i64, length as i64)
12376}
12377
12378unsafe fn sys_ftruncate(fd: i32, length: i64) -> i64 {
12379 <Arch as Syscalls>::syscall2(SYS_FTRUNCATE, fd as i64, length as i64)
12380}
12381
12382unsafe fn sys_nanosleep(req: *const timespec, rem: *mut timespec) -> i64 {
12383 <Arch as Syscalls>::syscall2(SYS_NANOSLEEP, req as i64, rem as i64)
12384}
12385
12386const ITIMER_REAL: i32 = 0;
12387
12388#[repr(C)]
12389struct itimerval {
12390 it_interval: timeval,
12391 it_value: timeval,
12392}
12393
12394unsafe fn sys_alarm(seconds: c_uint) -> i64 {
12395 let mut new: itimerval = core::mem::zeroed();
12396 new.it_value.tv_sec = seconds as c_long;
12397 let mut old: itimerval = core::mem::zeroed();
12398 let r = <Arch as Syscalls>::syscall3(
12399 SYS_SETITIMER,
12400 ITIMER_REAL as i64,
12401 &new as *const _ as i64,
12402 &mut old as *mut _ as i64,
12403 );
12404 if r < 0 {
12405 return r;
12406 }
12407 old.it_value.tv_sec as i64
12408}
12409
12410unsafe fn sys_pause() -> i64 {
12411 #[cfg(target_arch = "x86_64")]
12412 { <Arch as Syscalls>::syscall0(SYS_PAUSE) }
12413 #[cfg(target_arch = "aarch64")]
12414 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12415 #[cfg(target_arch = "riscv64")]
12416 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12417}
12418
12419unsafe fn sys_fsync(fd: i32) -> i64 {
12420 <Arch as Syscalls>::syscall1(SYS_FSYNC, fd as i64)
12421}
12422
12423unsafe fn sys_fdatasync(fd: i32) -> i64 {
12424 <Arch as Syscalls>::syscall1(SYS_FDATASYNC, fd as i64)
12425}
12426
12427unsafe fn sys_sync() {
12428 let _ = <Arch as Syscalls>::syscall0(SYS_SYNC);
12429}
12430
12431unsafe fn sys_symlink(target: *const u8, linkpath: *const u8) -> i64 {
12432 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, AT_FDCWD as i64, linkpath as i64)
12433}
12434
12435unsafe fn sys_symlinkat(target: *const u8, newdirfd: i32, linkpath: *const u8) -> i64 {
12436 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64)
12437}
12438
12439unsafe fn sys_readlinkat(dirfd: i32, path: *const u8, buf: *mut u8, bufsiz: usize) -> i64 {
12440 <Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, path as i64, buf as i64, bufsiz as i64)
12441}
12442
12443unsafe fn sys_linkat(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: i32) -> i64 {
12444 <Arch as Syscalls>::syscall5(SYS_LINKAT, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
12445}
12446
12447unsafe fn sys_fchmod(fd: i32, mode: u32) -> i64 {
12448 <Arch as Syscalls>::syscall2(SYS_FCHMOD, fd as i64, mode as i64)
12449}
12450
12451unsafe fn sys_fchmodat(dirfd: i32, path: *const u8, mode: u32, flags: i32) -> i64 {
12452 <Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, path as i64, mode as i64, flags as i64)
12453}
12454
12455unsafe fn sys_umask(mask: u32) -> u32 {
12456 <Arch as Syscalls>::syscall1(SYS_UMASK, mask as i64) as u32
12457}
12458
12459unsafe fn sys_getgroups(size: i32, list: *mut c_uint) -> i64 {
12460 <Arch as Syscalls>::syscall2(SYS_GETGROUPS, size as i64, list as i64)
12461}
12462
12463unsafe fn sys_setuid(uid: c_uint) -> i64 {
12464 <Arch as Syscalls>::syscall1(SYS_SETUID, uid as i64)
12465}
12466
12467unsafe fn sys_setgid(gid: c_uint) -> i64 {
12468 <Arch as Syscalls>::syscall1(SYS_SETGID, gid as i64)
12469}
12470
12471unsafe fn sys_setsid() -> i64 {
12472 <Arch as Syscalls>::syscall0(SYS_SETSID)
12473}
12474
12475unsafe fn sys_setpgid(pid: c_int, pgid: c_int) -> i64 {
12476 <Arch as Syscalls>::syscall2(SYS_SETPGID, pid as i64, pgid as i64)
12477}
12478
12479unsafe fn sys_getpgid(pid: c_int) -> i64 {
12480 <Arch as Syscalls>::syscall1(SYS_GETPGID, pid as i64)
12481}
12482
12483unsafe fn sys_getsid(pid: c_int) -> i64 {
12484 <Arch as Syscalls>::syscall1(SYS_GETSID, pid as i64)
12485}
12486
12487unsafe fn sys_mkdirat(dirfd: i32, path: *const u8, mode: u32) -> i64 {
12488 <Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, path as i64, mode as i64)
12489}
12490
12491#[no_mangle]
12494pub unsafe extern "C" fn pipe(fds: *mut c_int) -> c_int {
12495 let r = sys_pipe2(fds, 0);
12496 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12497 0
12498}
12499
12500#[no_mangle]
12501pub unsafe extern "C" fn pipe2(fds: *mut c_int, flags: c_int) -> c_int {
12502 let r = sys_pipe2(fds, flags);
12503 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12504 0
12505}
12506
12507#[no_mangle]
12508pub unsafe extern "C" fn dup(oldfd: c_int) -> c_int {
12509 let r = sys_dup(oldfd);
12510 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12511 r as c_int
12512}
12513
12514#[no_mangle]
12515pub unsafe extern "C" fn dup2(oldfd: c_int, newfd: c_int) -> c_int {
12516 let r = sys_dup2(oldfd, newfd);
12517 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12518 r as c_int
12519}
12520
12521#[no_mangle]
12522pub unsafe extern "C" fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int {
12523 let r = sys_dup3(oldfd, newfd, flags);
12524 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12525 r as c_int
12526}
12527
12528#[no_mangle]
12529pub unsafe extern "C" fn fcntl(fd: c_int, cmd: c_int, mut args: ...) -> c_int {
12530 let r = match cmd {
12531 F_GETFD | F_GETFL => sys_fcntl(fd, cmd, 0),
12532 F_SETFD | F_SETFL | F_DUPFD | F_DUPFD_CLOEXEC => {
12533 let arg = args.next_arg::<c_int>();
12534 sys_fcntl(fd, cmd, arg as i64)
12535 }
12536 F_GETLK | F_SETLK | F_SETLKW => {
12537 let arg = args.next_arg::<*mut c_void>();
12538 sys_fcntl(fd, cmd, arg as i64)
12539 }
12540 _ => sys_fcntl(fd, cmd, 0),
12541 };
12542 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12543 r as c_int
12544}
12545
12546#[no_mangle]
12547pub unsafe extern "C" fn access(path: *const c_char, mode: c_int) -> c_int {
12548 let r = sys_access(path as *const u8, mode);
12549 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12550 0
12551}
12552
12553#[no_mangle]
12554pub unsafe extern "C" fn unlink(path: *const c_char) -> c_int {
12555 let r = sys_unlink(path as *const u8);
12556 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12557 0
12558}
12559
12560#[no_mangle]
12561pub unsafe extern "C" fn rmdir(path: *const c_char) -> c_int {
12562 let r = sys_rmdir(path as *const u8);
12563 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12564 0
12565}
12566
12567#[no_mangle]
12568pub unsafe extern "C" fn chdir(path: *const c_char) -> c_int {
12569 let r = sys_chdir(path as *const u8);
12570 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12571 0
12572}
12573
12574#[no_mangle]
12575pub unsafe extern "C" fn getcwd(buf: *mut c_char, size: usize) -> *mut c_char {
12576 if buf.is_null() {
12577 let alloc_size = if size == 0 { 256 } else { size };
12579 let p = malloc(alloc_size) as *mut c_char;
12580 if p.is_null() { ERRNO = ENOMEM; return core::ptr::null_mut(); }
12581 let r = sys_getcwd(p as *mut u8, alloc_size);
12582 if r < 0 { free(p as *mut c_void); ERRNO = (-r) as c_int; return core::ptr::null_mut(); }
12583 return p;
12584 }
12585 if size == 0 { ERRNO = EINVAL; return core::ptr::null_mut(); }
12586 let r = sys_getcwd(buf as *mut u8, size);
12587 if r < 0 { ERRNO = (-r) as c_int; return core::ptr::null_mut(); }
12588 buf
12589}
12590
12591#[no_mangle]
12592pub unsafe extern "C" fn gethostname(name: *mut c_char, len: usize) -> c_int {
12593 let r = sys_gethostname(name as *mut u8, len);
12594 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12595 0
12596}
12597
12598#[no_mangle]
12600pub extern "C" fn getpagesize() -> c_int {
12601 4096
12602}
12603
12604#[no_mangle]
12605pub unsafe extern "C" fn truncate(path: *const c_char, length: i64) -> c_int {
12606 let r = sys_truncate(path as *const u8, length);
12607 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12608 0
12609}
12610
12611#[no_mangle]
12612pub unsafe extern "C" fn ftruncate(fd: c_int, length: i64) -> c_int {
12613 let r = sys_ftruncate(fd, length);
12614 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12615 0
12616}
12617
12618#[no_mangle]
12619pub unsafe extern "C" fn nanosleep(req: *const timespec, rem: *mut timespec) -> c_int {
12620 pthread_testcancel();
12621 let r = sys_nanosleep(req, rem);
12622 pthread_testcancel();
12623 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12624 0
12625}
12626
12627#[no_mangle]
12628pub unsafe extern "C" fn sleep(seconds: c_uint) -> c_uint {
12629 let req = timespec { tv_sec: seconds as c_long, tv_nsec: 0 };
12630 let mut rem: timespec = core::mem::zeroed();
12631 pthread_testcancel();
12632 let r = sys_nanosleep(&req, &mut rem);
12633 pthread_testcancel();
12634 if r < 0 {
12635 let e = (-r) as c_int;
12636 if e == EINTR { return rem.tv_sec as c_uint; }
12637 }
12638 0
12639}
12640
12641#[no_mangle]
12642pub unsafe extern "C" fn usleep(usec: c_uint) -> c_int {
12643 let req = timespec { tv_sec: (usec / 1000000) as c_long, tv_nsec: ((usec % 1000000) * 1000) as c_long };
12644 pthread_testcancel();
12645 let r = sys_nanosleep(&req, core::ptr::null_mut());
12646 pthread_testcancel();
12647 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12648 0
12649}
12650
12651#[no_mangle]
12652pub unsafe extern "C" fn alarm(seconds: c_uint) -> c_uint {
12653 sys_alarm(seconds) as c_uint
12654}
12655
12656#[no_mangle]
12657pub unsafe extern "C" fn pause() -> c_int {
12658 pthread_testcancel();
12659 sys_pause();
12660 pthread_testcancel();
12661 ERRNO = EINTR;
12662 -1
12663}
12664
12665#[no_mangle]
12666pub unsafe extern "C" fn fsync(fd: c_int) -> c_int {
12667 let r = sys_fsync(fd);
12668 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12669 0
12670}
12671
12672#[no_mangle]
12673pub unsafe extern "C" fn fdatasync(fd: c_int) -> c_int {
12674 let r = sys_fdatasync(fd);
12675 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12676 0
12677}
12678
12679#[no_mangle]
12680pub unsafe extern "C" fn sync() {
12681 sys_sync();
12682}
12683
12684#[no_mangle]
12685pub unsafe extern "C" fn symlink(target: *const c_char, linkpath: *const c_char) -> c_int {
12686 let r = sys_symlinkat(target as *const u8, AT_FDCWD, linkpath as *const u8);
12687 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12688 0
12689}
12690
12691#[no_mangle]
12692pub unsafe extern "C" fn readlink(path: *const c_char, buf: *mut c_char, bufsiz: usize) -> isize {
12693 let r = sys_readlinkat(AT_FDCWD, path as *const u8, buf as *mut u8, bufsiz);
12694 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12695 r as isize
12696}
12697
12698#[no_mangle]
12699pub unsafe extern "C" fn link(oldpath: *const c_char, newpath: *const c_char) -> c_int {
12700 let r = sys_linkat(AT_FDCWD, oldpath as *const u8, AT_FDCWD, newpath as *const u8, 0);
12701 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12702 0
12703}
12704
12705#[no_mangle]
12706pub unsafe extern "C" fn chmod(path: *const c_char, mode: c_uint) -> c_int {
12707 let r = sys_fchmodat(AT_FDCWD, path as *const u8, mode, 0);
12708 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12709 0
12710}
12711
12712#[no_mangle]
12713pub unsafe extern "C" fn fchmod(fd: c_int, mode: c_uint) -> c_int {
12714 let r = sys_fchmod(fd, mode);
12715 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12716 0
12717}
12718
12719#[no_mangle]
12720pub unsafe extern "C" fn umask(mask: c_uint) -> c_uint {
12721 sys_umask(mask) as c_uint
12722}
12723
12724#[no_mangle]
12725pub unsafe extern "C" fn isatty(fd: c_int) -> c_int {
12726 let mut ws: winsize = core::mem::zeroed();
12727 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 { 1 } else { 0 }
12728}
12729
12730#[no_mangle]
12731pub unsafe extern "C" fn getlogin() -> *mut c_char {
12732 static mut LOGIN_BUF: [c_char; 32] = [0; 32];
12733 let pw = getpwuid(crate::getuid());
12734 if pw.is_null() { return core::ptr::null_mut(); }
12735 let n = crate::strlen((*pw).pw_name);
12736 if n + 1 > LOGIN_BUF.len() { return core::ptr::null_mut(); }
12737 core::ptr::copy_nonoverlapping((*pw).pw_name, LOGIN_BUF.as_mut_ptr(), n + 1);
12738 LOGIN_BUF.as_mut_ptr()
12739}
12740
12741#[no_mangle]
12742pub unsafe extern "C" fn getgroups(size: c_int, list: *mut c_uint) -> c_int {
12743 let r = sys_getgroups(size, list);
12744 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12745 r as c_int
12746}
12747
12748#[no_mangle]
12749pub unsafe extern "C" fn setuid(uid: c_uint) -> c_int {
12750 let r = sys_setuid(uid);
12751 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12752 0
12753}
12754
12755#[no_mangle]
12756pub unsafe extern "C" fn setgid(gid: c_uint) -> c_int {
12757 let r = sys_setgid(gid);
12758 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12759 0
12760}
12761
12762#[no_mangle]
12763pub unsafe extern "C" fn seteuid(euid: c_uint) -> c_int {
12764 let r = sys_setuid(euid);
12766 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12767 0
12768}
12769
12770#[no_mangle]
12771pub unsafe extern "C" fn setegid(egid: c_uint) -> c_int {
12772 let r = sys_setgid(egid);
12773 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12774 0
12775}
12776
12777#[no_mangle]
12778pub unsafe extern "C" fn setreuid(ruid: c_uint, euid: c_uint) -> c_int {
12779 let r = <Arch as Syscalls>::syscall2(sysno(113, 145), ruid as i64, euid as i64);
12780 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
12781}
12782
12783
12784
12785#[no_mangle]
12786pub unsafe extern "C" fn setsid() -> c_int {
12787 let r = sys_setsid();
12788 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12789 r as c_int
12790}
12791
12792#[no_mangle]
12793pub unsafe extern "C" fn setpgid(pid: c_int, pgid: c_int) -> c_int {
12794 let r = sys_setpgid(pid, pgid);
12795 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12796 0
12797}
12798
12799#[no_mangle]
12800pub unsafe extern "C" fn getpgid(pid: c_int) -> c_int {
12801 let r = sys_getpgid(pid);
12802 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12803 r as c_int
12804}
12805
12806#[no_mangle]
12807pub unsafe extern "C" fn getsid(pid: c_int) -> c_int {
12808 let r = sys_getsid(pid);
12809 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12810 r as c_int
12811}
12812
12813#[no_mangle]
12814pub unsafe extern "C" fn getpgrp() -> c_int {
12815 sys_getpgid(0) as c_int
12816}
12817
12818#[no_mangle]
12819pub unsafe extern "C" fn setpgrp() -> c_int {
12820 setpgid(0, 0)
12821}
12822
12823#[no_mangle]
12824pub unsafe extern "C" fn mkstemp(template: *mut c_char) -> c_int {
12825 if template.is_null() { ERRNO = EINVAL; return -1; }
12826 let len = strlen(template as *const c_char);
12827 if len < 6 { ERRNO = EINVAL; return -1; }
12828 let x_start = len - 6;
12829 for i in x_start..len {
12831 if *template.add(i) != b'X' as c_char { ERRNO = EINVAL; return -1; }
12832 }
12833 let mut ts: timespec = core::mem::zeroed();
12834 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
12835 let mut ctr: u32 = ts.tv_nsec as u32;
12836 for _ in 0..100 {
12837 ctr = ctr.wrapping_mul(1103515245).wrapping_add(12345);
12838 let seed = ctr;
12839 let hex = b"0123456789abcdef";
12841 let mut s = seed;
12842 for i in x_start..len {
12843 *template.add(i) = hex[(s & 0xf) as usize] as c_char;
12844 s >>= 4;
12845 }
12846 let fd = sys_open(template as *const u8, (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
12847 if fd >= 0 { return fd as c_int; }
12848 let e = (-fd) as c_int;
12849 if e != EEXIST_VAL { ERRNO = e; return -1; }
12850 }
12851 ERRNO = EEXIST_VAL;
12852 -1
12853}
12854
12855#[no_mangle]
12856pub unsafe extern "C" fn mkdir(path: *const c_char, mode: c_uint) -> c_int {
12857 let r = sys_mkdirat(AT_FDCWD, path as *const u8, mode);
12858 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12859 0
12860}
12861
12862#[no_mangle]
12867pub unsafe extern "C" fn dirname(s: *mut c_char) -> *mut c_char {
12868 if s.is_null() || *s == 0 {
12869 return b".\0".as_ptr() as *mut c_char;
12870 }
12871 let mut i = strlen(s as *const c_char);
12872 i = i.wrapping_sub(1);
12873 while i > 0 && *s.add(i) == b'/' as c_char {
12875 i = i.wrapping_sub(1);
12876 }
12877 if i == 0 && *s.add(0) == b'/' as c_char {
12878 return b"/\0".as_ptr() as *mut c_char;
12879 }
12880 while i > 0 && *s.add(i) != b'/' as c_char {
12882 i = i.wrapping_sub(1);
12883 }
12884 if i == 0 {
12885 if *s.add(0) == b'/' as c_char {
12886 return b"/\0".as_ptr() as *mut c_char;
12887 }
12888 return b".\0".as_ptr() as *mut c_char;
12889 }
12890 while i > 0 && *s.add(i - 1) == b'/' as c_char {
12892 i = i.wrapping_sub(1);
12893 }
12894 if i == 0 {
12895 return b"/\0".as_ptr() as *mut c_char;
12896 }
12897 *s.add(i) = 0;
12898 s
12899}
12900
12901#[no_mangle]
12902pub unsafe extern "C" fn basename(s: *mut c_char) -> *mut c_char {
12903 if s.is_null() || *s == 0 {
12904 return b".\0".as_ptr() as *mut c_char;
12905 }
12906 let mut i = strlen(s as *const c_char);
12907 i = i.wrapping_sub(1);
12908 while i > 0 && *s.add(i) == b'/' as c_char {
12910 *s.add(i) = 0;
12911 i = i.wrapping_sub(1);
12912 }
12913 while i > 0 && *s.add(i - 1) != b'/' as c_char {
12915 i = i.wrapping_sub(1);
12916 }
12917 s.add(i)
12918}
12919
12920const AF_INET_VAL: c_int = 2;
12925const AF_INET6_VAL: c_int = 10;
12926const EAFNOSUPPORT: c_int = 97;
12927const ENOSPC_VAL2: c_int = 28;
12928
12929unsafe fn inet_pton_v4(s: *const u8, a: *mut u8) -> c_int {
12930 let mut p = s;
12931 let mut i = 0;
12932 while i < 4 {
12933 let oct_start = p;
12934 let mut v: u32 = 0;
12935 let mut j: u32 = 0;
12936 while j < 3 && *p >= b'0' && *p <= b'9' {
12937 v = v * 10 + (*p - b'0') as u32;
12938 p = p.add(1);
12939 j += 1;
12940 }
12941 if j == 0 || (j > 1 && *oct_start == b'0') || v > 255 { return 0; }
12942 *a.add(i) = v as u8;
12943 if *p == 0 && i == 3 { return 1; }
12944 if *p != b'.' { return 0; }
12945 p = p.add(1);
12946 i += 1;
12947 }
12948 0
12949}
12950
12951unsafe fn inet_pton_v6(s: *const u8, a: *mut u8) -> c_int {
12952 let mut ip = [0u16; 8];
12953 let mut p = s;
12954 let mut i: usize = 0;
12955 let mut brk: isize = -1;
12956 let mut need_v4 = false;
12957 let mut v4_start: *const u8 = core::ptr::null();
12958
12959 if *p == b':' {
12960 p = p.add(1);
12961 if *p != b':' { return 0; }
12962 }
12963
12964 loop {
12965 if *p == b':' && brk < 0 {
12966 brk = i as isize;
12967 ip[i & 7] = 0;
12968 p = p.add(1);
12969 if *p == 0 { break; }
12970 if i == 7 { return 0; }
12971 i += 1;
12972 continue;
12973 }
12974 v4_start = p;
12975 let mut v: u16 = 0;
12976 let mut j = 0;
12977 while j < 4 {
12978 let d = hex_digit(*p);
12979 if d < 0 { break; }
12980 v = v * 16 + d as u16;
12981 p = p.add(1);
12982 j += 1;
12983 }
12984 if j == 0 { return 0; }
12985 ip[i & 7] = v;
12986 if *p == 0 && (brk >= 0 || i == 7) { break; }
12987 if i == 7 { return 0; }
12988 if *p != b':' {
12989 if *p != b'.' || (i < 6 && brk < 0) { return 0; }
12990 need_v4 = true;
12991 i += 1;
12992 ip[i & 7] = 0;
12993 break;
12994 }
12995 p = p.add(1);
12996 i += 1;
12997 }
12998
12999 if brk >= 0 {
13000 let trail_count = i + 1 - brk as usize;
13002 let dest_start = brk as usize + 7 - i;
13003 for j in (0..trail_count).rev() {
13005 ip[dest_start + j] = ip[brk as usize + j];
13006 }
13007 for j in 0..(7 - i) {
13008 ip[brk as usize + j] = 0;
13009 }
13010 }
13011
13012 for k in 0..8 {
13013 *a.add(k * 2) = (ip[k] >> 8) as u8;
13014 *a.add(k * 2 + 1) = (ip[k] & 0xff) as u8;
13015 }
13016
13017 if need_v4 {
13018 if inet_pton_v4(v4_start, a.add(12)) <= 0 { return 0; }
13019 }
13020 1
13021}
13022
13023unsafe fn hex_digit(c: u8) -> i32 {
13024 if c >= b'0' && c <= b'9' { (c - b'0') as i32 }
13025 else if c >= b'a' && c <= b'f' { (c - b'a' + 10) as i32 }
13026 else if c >= b'A' && c <= b'F' { (c - b'A' + 10) as i32 }
13027 else { -1 }
13028}
13029
13030#[no_mangle]
13031pub unsafe extern "C" fn inet_pton(af: c_int, s: *const c_char, a: *mut c_void) -> c_int {
13032 if af == AF_INET_VAL {
13033 inet_pton_v4(s as *const u8, a as *mut u8)
13034 } else if af == AF_INET6_VAL {
13035 inet_pton_v6(s as *const u8, a as *mut u8)
13036 } else {
13037 ERRNO = EAFNOSUPPORT;
13038 -1
13039 }
13040}
13041
13042#[no_mangle]
13043pub unsafe extern "C" fn inet_ntop(af: c_int, a: *const c_void, s: *mut c_char, size: u32) -> *mut c_char {
13044 if af == AF_INET_VAL {
13045 let b = a as *const u8;
13046 let needed = 16; if size < needed as u32 { ERRNO = ENOSPC_VAL2; return core::ptr::null_mut(); }
13048 let mut pos = 0;
13049 for i in 0..4 {
13050 if i > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
13051 let (buf, len) = format_u64(*b.add(i) as u64);
13052 for j in 0..len { *s.add(pos) = buf[j] as c_char; pos += 1; }
13053 }
13054 *s.add(pos) = 0;
13055 s
13056 } else if af == AF_INET6_VAL {
13057 let b = a as *const u8;
13058 let needed = 46; if size < needed as u32 { ERRNO = ENOSPC_VAL2; return core::ptr::null_mut(); }
13060 let mut words = [0u16; 8];
13061 for i in 0..8 {
13062 words[i] = ((*b.add(i * 2) as u16) << 8) | (*b.add(i * 2 + 1) as u16);
13063 }
13064 let mut pos = 0usize;
13066 if words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0
13067 && words[4] == 0 && words[5] == 0xffff
13068 {
13069 let prefix = b"::ffff:";
13070 for k in 0..prefix.len() { *s.add(pos) = prefix[k] as c_char; pos += 1; }
13071 for idx in 0..4 {
13072 if idx > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
13073 let octet = *b.add(12 + idx);
13074 if octet >= 100 {
13075 *s.add(pos) = (b'0' + octet / 100) as c_char; pos += 1;
13076 *s.add(pos) = (b'0' + (octet / 10) % 10) as c_char; pos += 1;
13077 } else if octet >= 10 {
13078 *s.add(pos) = (b'0' + octet / 10) as c_char; pos += 1;
13079 }
13080 *s.add(pos) = (b'0' + octet % 10) as c_char; pos += 1;
13081 }
13082 *s.add(pos) = 0;
13083 return s;
13084 }
13085 let mut best_start: isize = -1;
13087 let mut best_len: usize = 0;
13088 let mut j: usize = 0;
13089 while j < 8 {
13090 if words[j] == 0 {
13091 let mut k = j;
13092 while k < 8 && words[k] == 0 { k += 1; }
13093 let run = k - j;
13094 if run > best_len { best_start = j as isize; best_len = run; }
13095 j = k;
13096 } else {
13097 j += 1;
13098 }
13099 }
13100 let mut i: usize = 0;
13101 let mut prev_in_run = false;
13102 while i < 8 {
13103 let in_run = best_len >= 2 && i >= best_start as usize && i < best_start as usize + best_len;
13104 if in_run {
13105 if i == best_start as usize {
13106 *s.add(pos) = b':' as c_char; pos += 1;
13107 *s.add(pos) = b':' as c_char; pos += 1;
13108 }
13109 i += 1;
13110 prev_in_run = true;
13111 continue;
13112 }
13113 if i > 0 && !prev_in_run {
13114 *s.add(pos) = b':' as c_char; pos += 1;
13115 }
13116 let (buf, len) = format_hex(words[i] as u64, false);
13117 for k in 0..len { *s.add(pos) = buf[k] as c_char; pos += 1; }
13118 i += 1;
13119 prev_in_run = false;
13120 }
13121 *s.add(pos) = 0;
13122 s
13123 } else {
13124 ERRNO = EAFNOSUPPORT;
13125 core::ptr::null_mut()
13126 }
13127}
13128
13129#[no_mangle]
13130pub unsafe extern "C" fn inet_aton(s: *const c_char, dest: *mut c_void) -> c_int {
13131 let a = dest as *mut u8;
13132 let mut p = s as *const u8;
13133 let mut vals = [0u64; 4];
13134 let mut i = 0usize;
13135 while i < 4 {
13136 if *p < b'0' || *p > b'9' { return 0; }
13137 let mut base = 10u32;
13138 if *p == b'0' {
13139 let c = *p.add(1);
13140 if c == b'x' || c == b'X' {
13141 base = 16;
13142 p = p.add(2);
13143 if !((*p >= b'0' && *p <= b'9')
13144 || (*p >= b'a' && *p <= b'f')
13145 || (*p >= b'A' && *p <= b'F')) {
13146 return 0;
13147 }
13148 } else {
13149 base = 8;
13150 }
13151 }
13152 let mut v: u64 = 0;
13153 let start = p;
13154 loop {
13155 let c = *p;
13156 let d = if c >= b'0' && c <= b'9' {
13157 (c - b'0') as u64
13158 } else if base == 16 && c >= b'a' && c <= b'f' {
13159 (c - b'a' + 10) as u64
13160 } else if base == 16 && c >= b'A' && c <= b'F' {
13161 (c - b'A' + 10) as u64
13162 } else {
13163 break;
13164 };
13165 v = v * (base as u64) + d;
13166 p = p.add(1);
13167 }
13168 if p == start { return 0; }
13169 vals[i] = v;
13170 if *p == 0 {
13171 break;
13172 }
13173 if *p != b'.' || i == 3 { return 0; }
13174 p = p.add(1);
13175 i += 1;
13176 }
13177 if i == 4 { return 0; }
13178 if i < 1 { vals[1] = vals[0] & 0xffffff; vals[0] >>= 24; }
13179 if i < 2 { vals[2] = vals[1] & 0xffff; vals[1] >>= 16; }
13180 if i < 3 { vals[3] = vals[2] & 0xff; vals[2] >>= 8; }
13181 for j in 0..4 {
13182 if vals[j] > 255 { return 0; }
13183 *a.add(j) = vals[j] as u8;
13184 }
13185 1
13186}
13187
13188#[no_mangle]
13189pub unsafe extern "C" fn inet_addr(s: *const c_char) -> u32 {
13190 let mut a = [0u8; 4];
13191 if inet_aton(s, a.as_mut_ptr() as *mut c_void) == 1 {
13192 u32::from_ne_bytes(a)
13193 } else {
13194 !0u32 }
13196}
13197
13198#[no_mangle]
13199pub unsafe extern "C" fn inet_ntoa(addr: u32) -> *mut c_char {
13200 static mut NTOA_BUF: [c_char; 16] = [0; 16];
13201 let b = addr.to_ne_bytes();
13202 let mut pos = 0;
13203 for i in 0..4 {
13204 if i > 0 { NTOA_BUF[pos] = b'.' as c_char; pos += 1; }
13205 let (buf, len) = format_u64(b[i] as u64);
13206 for j in 0..len { NTOA_BUF[pos] = buf[j] as c_char; pos += 1; }
13207 }
13208 NTOA_BUF[pos] = 0;
13209 core::ptr::addr_of_mut!(NTOA_BUF).cast::<c_char>()
13210}
13211
13212#[no_mangle]
13214pub unsafe extern "C" fn inet_network(s: *const c_char) -> u32 {
13215 inet_addr(s).to_be()
13216}
13217
13218#[no_mangle]
13219pub extern "C" fn inet_makeaddr(net: c_int, host: c_int) -> u32 {
13220 let addr: u32;
13221 if (net as u32) < 128 {
13222 addr = (net as u32) << 24;
13223 } else if (net as u32) < 0x10000 {
13224 addr = (net as u32) << 16;
13225 } else if (net as u32) < 0x1000000 {
13226 addr = (net as u32) << 8;
13227 } else {
13228 addr = net as u32;
13229 }
13230 addr | (host as u32 & 0xffffffff)
13231}
13232
13233#[no_mangle]
13234pub extern "C" fn inet_lnaof(addr: u32) -> c_int {
13235 let h = u32::from_be(addr);
13236 if h < 0x80000000 { (h & 0x00ffffff) as c_int }
13237 else if h < 0xc0000000 { (h & 0x0000ffff) as c_int }
13238 else { (h & 0x000000ff) as c_int }
13239}
13240
13241#[no_mangle]
13242pub extern "C" fn inet_netof(addr: u32) -> c_int {
13243 let h = u32::from_be(addr);
13244 if h < 0x80000000 { (h >> 24) as c_int }
13245 else if h < 0xc0000000 { (h >> 16) as c_int }
13246 else { (h >> 8) as c_int }
13247}
13248
13249unsafe fn parse_float(s: *const u8, endptr: *mut *mut u8, is_f32: bool) -> f64 {
13258 let mut p = s;
13259 while *p == b' ' || *p == b'\t' || *p == b'\n' || *p == b'\r' { p = p.add(1); }
13261 let mut neg = false;
13262 if *p == b'-' { neg = true; p = p.add(1); }
13263 else if *p == b'+' { p = p.add(1); }
13264
13265 if (*p | 0x20) == b'i'
13267 && (*p.add(1) | 0x20) == b'n'
13268 && (*p.add(2) | 0x20) == b'f'
13269 {
13270 p = p.add(3);
13271 if (*p | 0x20) == b'i'
13273 && (*p.add(1) | 0x20) == b't'
13274 && (*p.add(2) | 0x20) == b'y'
13275 {
13276 p = p.add(3);
13277 }
13278 if !endptr.is_null() { *endptr = p as *mut u8; }
13279 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13280 }
13281 if (*p | 0x20) == b'n'
13283 && (*p.add(1) | 0x20) == b'a'
13284 && (*p.add(2) | 0x20) == b'n'
13285 {
13286 p = p.add(3);
13287 if *p == b'(' {
13289 p = p.add(1);
13290 while *p != 0 && *p != b')' { p = p.add(1); }
13291 if *p == b')' { p = p.add(1); }
13292 }
13293 if !endptr.is_null() { *endptr = p as *mut u8; }
13294 return if neg { -f64::NAN } else { f64::NAN };
13295 }
13296
13297 if *p == b'0' && (*p.add(1) == b'x' || *p.add(1) == b'X') {
13299 p = p.add(2);
13300 let mut mant: u128 = 0;
13301 let mut frac_hex: u32 = 0;
13302 let mut found = false;
13303 let mut in_frac = false;
13304
13305 loop {
13306 if let Some(d) = hex_val(*p) {
13307 if mant <= u128::MAX / 16 {
13308 mant = mant * 16 + d as u128;
13309 }
13310 if in_frac { frac_hex += 1; }
13311 p = p.add(1);
13312 found = true;
13313 } else if *p == b'.' && !in_frac {
13314 in_frac = true;
13315 p = p.add(1);
13316 } else {
13317 break;
13318 }
13319 }
13320
13321 if !found {
13322 if !endptr.is_null() { *endptr = s as *mut u8; }
13323 return 0.0;
13324 }
13325
13326 let mut bin_exp: i32 = 0;
13328 if *p == b'p' || *p == b'P' {
13329 p = p.add(1);
13330 let mut exp_neg = false;
13331 if *p == b'-' { exp_neg = true; p = p.add(1); }
13332 else if *p == b'+' { p = p.add(1); }
13333 while *p >= b'0' && *p <= b'9' {
13334 if bin_exp < 100000 {
13335 bin_exp = bin_exp * 10 + (*p - b'0') as i32;
13336 }
13337 p = p.add(1);
13338 }
13339 if exp_neg { bin_exp = -bin_exp; }
13340 }
13341
13342 if !endptr.is_null() { *endptr = p as *mut u8; }
13343 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13344
13345 let total_exp = bin_exp as i64 - 4 * frac_hex as i64;
13346 return hex_mant_to_f64(mant, total_exp, neg);
13347 }
13348
13349 let mut buf = [0u8; 65536];
13351 let mut n = 0usize;
13352 let mut found_digit = false;
13353
13354 while *p >= b'0' && *p <= b'9' {
13355 if n < 65535 { buf[n] = *p; n += 1; }
13356 p = p.add(1);
13357 found_digit = true;
13358 }
13359 if *p == b'.' {
13360 if n < 65535 { buf[n] = b'.'; n += 1; }
13361 p = p.add(1);
13362 while *p >= b'0' && *p <= b'9' {
13363 if n < 65535 { buf[n] = *p; n += 1; }
13364 p = p.add(1);
13365 found_digit = true;
13366 }
13367 }
13368 if !found_digit {
13369 if !endptr.is_null() { *endptr = s as *mut u8; }
13370 return 0.0;
13371 }
13372 if *p == b'e' || *p == b'E' {
13373 if n < 65535 { buf[n] = b'e'; n += 1; }
13374 p = p.add(1);
13375 if *p == b'-' || *p == b'+' {
13376 if n < 65535 { buf[n] = *p; n += 1; }
13377 p = p.add(1);
13378 }
13379 while *p >= b'0' && *p <= b'9' {
13380 if n < 65535 { buf[n] = *p; n += 1; }
13381 p = p.add(1);
13382 }
13383 }
13384
13385 if !endptr.is_null() { *endptr = p as *mut u8; }
13386 let s_str = core::str::from_utf8_unchecked(
13387 core::slice::from_raw_parts(buf.as_ptr(), n),
13388 );
13389 if is_f32 {
13390 match <f32 as core::str::FromStr>::from_str(s_str) {
13391 Ok(v) => { let r = v as f64; if neg { -r } else { r } }
13392 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13393 }
13394 } else {
13395 match <f64 as core::str::FromStr>::from_str(s_str) {
13396 Ok(v) => if neg { -v } else { v },
13397 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13398 }
13399 }
13400}
13401
13402fn hex_mant_to_f64(mant: u128, total_exp: i64, neg: bool) -> f64 {
13406 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13407
13408 let msb = (127 - mant.leading_zeros()) as i64;
13409 let unbiased_exp = msb + total_exp;
13410 let biased_exp = unbiased_exp + 1023;
13411
13412 if biased_exp >= 2047 {
13414 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13415 }
13416
13417 if biased_exp <= 0 {
13419 let shift = total_exp + 1074;
13422 if shift < 0 {
13423 return if neg { -0.0 } else { 0.0 };
13424 }
13425 if shift > 128 {
13426 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13427 }
13428 let shifted = mant << (shift as u32);
13429 let mantissa52 = (shifted as u64) & 0x000FFFFFFFFFFFFF;
13430 let guard = ((shifted >> 52) & 1) != 0;
13431 let sticky = (shifted >> 53) != 0;
13432 let mut result = mantissa52;
13433 if guard && (sticky || (result & 1) != 0) {
13434 result += 1;
13435 if result > 0x000FFFFFFFFFFFFF {
13436 return if neg { -f64::from_bits(1u64 << 52) } else { f64::from_bits(1u64 << 52) };
13438 }
13439 }
13440 return if neg { -f64::from_bits(result) } else { f64::from_bits(result) };
13441 }
13442
13443 let shift = msb - 52;
13445
13446 if shift <= 0 {
13447 let mantissa = ((mant as u64) & ((1u64 << msb as u32) - 1)) << ((-shift) as u32);
13449 let bits = ((biased_exp as u64) << 52) | mantissa;
13450 return if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) };
13451 }
13452
13453 let mantissa = ((mant >> shift as u32) as u64) & 0x000FFFFFFFFFFFFF;
13455 let guard = ((mant >> (shift as u32 - 1)) & 1) != 0;
13456 let sticky = if shift > 1 {
13457 (mant & ((1u128 << (shift as u32 - 1)) - 1)) != 0
13458 } else { false };
13459
13460 let mut result_mant = mantissa;
13461 let mut result_exp = biased_exp;
13462 if guard && (sticky || (result_mant & 1) != 0) {
13463 result_mant += 1;
13464 if result_mant > 0x000FFFFFFFFFFFFF {
13465 result_mant = 0;
13466 result_exp += 1;
13467 if result_exp >= 2047 {
13468 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13469 }
13470 }
13471 }
13472
13473 let bits = ((result_exp as u64) << 52) | result_mant;
13474 if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) }
13475}
13476
13477unsafe fn hex_val(c: u8) -> Option<u8> {
13478 if c >= b'0' && c <= b'9' { Some(c - b'0') }
13479 else if c >= b'a' && c <= b'f' { Some(c - b'a' + 10) }
13480 else if c >= b'A' && c <= b'F' { Some(c - b'A' + 10) }
13481 else { None }
13482}
13483
13484#[no_mangle]
13485pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13486 let mut end: *mut u8 = s as *mut u8;
13487 let r = parse_float(s as *const u8, &mut end, false);
13488 if !endptr.is_null() { *endptr = end as *mut c_char; }
13489 r
13490}
13491
13492#[no_mangle]
13493pub unsafe extern "C" fn strtof(s: *const c_char, endptr: *mut *mut c_char) -> f32 {
13494 let mut end: *mut u8 = s as *mut u8;
13495 let r = parse_float(s as *const u8, &mut end, true);
13496 if !endptr.is_null() { *endptr = end as *mut c_char; }
13497 r as f32
13498}
13499
13500#[no_mangle]
13501#[cfg(target_arch = "x86_64")]
13502pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13503 strtod(s, endptr)
13504}
13505
13506#[no_mangle]
13507#[cfg(target_arch = "aarch64")]
13508pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13509 strtod(s, endptr) as f128
13510}
13511
13512#[no_mangle]
13513#[cfg(target_arch = "riscv64")]
13514pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13515 strtod(s, endptr) as f128
13516}
13517
13518#[no_mangle]
13519pub unsafe extern "C" fn atof(s: *const c_char) -> f64 {
13520 strtod(s, core::ptr::null_mut())
13521}
13522
13523#[repr(C)]
13528struct MsCookie {
13529 bufp: *mut *mut c_char,
13530 sizep: *mut usize,
13531 pos: usize,
13532 len: usize,
13533 buf: *mut u8,
13534 space: usize,
13535}
13536
13537#[repr(C)]
13538struct MfCookie {
13539 pos: usize,
13540 len: usize,
13541 size: usize,
13542 buf: *mut u8,
13543 mode: c_char,
13544}
13545
13546unsafe extern "C" fn ms_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13547 let c = (*f).cookie as *mut MsCookie;
13548 if whence < 0 || whence > 2 { ERRNO = EINVAL; return -1; }
13549 let base: i64 = match whence {
13550 0 => 0,
13551 1 => (*c).pos as i64,
13552 2 => (*c).len as i64,
13553 _ => { ERRNO = EINVAL; return -1; }
13554 };
13555 if off < -base || off > isize::MAX as i64 - base { ERRNO = EINVAL; return -1; }
13556 (*c).pos = (base + off) as usize;
13557 (*c).pos as i64
13558}
13559
13560unsafe extern "C" fn ms_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13561 let c = (*f).cookie as *mut MsCookie;
13562 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13563 if buffered > 0 {
13564 (*f).wpos = (*f).wbase;
13565 if ms_write(f, (*f).wbase, buffered) < buffered { return 0; }
13566 }
13567 if len == 0 { return 0; }
13568 if (*c).pos + len >= (*c).space {
13569 let new_space = 2 * (*c).space + 1 | (*c).pos + len + 1;
13570 let newbuf = realloc((*c).buf as *mut c_void, new_space) as *mut u8;
13571 if newbuf.is_null() { return 0; }
13572 *(*c).bufp = newbuf as *mut c_char;
13573 core::ptr::write_bytes(newbuf.add((*c).space), 0, new_space - (*c).space);
13574 (*c).buf = newbuf;
13575 (*c).space = new_space;
13576 }
13577 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), len);
13578 (*c).pos += len;
13579 if (*c).pos >= (*c).len { (*c).len = (*c).pos; }
13580 *(*c).sizep = (*c).pos;
13581 len
13582}
13583
13584unsafe extern "C" fn ms_close(_f: *mut FILE) -> c_int {
13585 0
13586}
13587
13588#[no_mangle]
13589pub unsafe extern "C" fn open_memstream(bufp: *mut *mut c_char, sizep: *mut usize) -> *mut FILE {
13590 if bufp.is_null() || sizep.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
13591 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
13592 if f.is_null() { ERRNO = ENOMEM; return core::ptr::null_mut(); }
13593 let buf_area = buf_ptr(f);
13594 init_file(f, -1, b"w\0".as_ptr() as *const c_char, Some(ms_close), buf_area, BUFSIZ);
13595 (*f).flags = F_NORD | F_SVB;
13596 (*f).lbf = -1;
13597 let c = calloc(1, core::mem::size_of::<MsCookie>()) as *mut MsCookie;
13598 if c.is_null() { free(f as *mut c_void); ERRNO = ENOMEM; return core::ptr::null_mut(); }
13599 (*c).bufp = bufp;
13600 (*c).sizep = sizep;
13601 (*c).pos = 0;
13602 (*c).len = 0;
13603 (*c).buf = core::ptr::null_mut();
13604 (*c).space = 0;
13605 (*f).cookie = c as *mut c_void;
13606 (*f).write_fn = Some(ms_write);
13607 (*f).seek_fn = Some(ms_seek);
13608 *bufp = core::ptr::null_mut();
13609 *sizep = 0;
13610 f
13611}
13612
13613unsafe extern "C" fn mseek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13614 let c = (*f).cookie as *mut MfCookie;
13615 if whence < 0 || whence > 2 { ERRNO = EINVAL; return -1; }
13616 let base: i64 = match whence {
13617 0 => 0,
13618 1 => (*c).pos as i64,
13619 2 => (*c).len as i64,
13620 _ => { ERRNO = EINVAL; return -1; }
13621 };
13622 if off < -base || off > (*c).size as i64 - base { ERRNO = EINVAL; return -1; }
13623 (*c).pos = (base + off) as usize;
13624 (*c).pos as i64
13625}
13626
13627unsafe extern "C" fn mread(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
13628 let c = (*f).cookie as *mut MfCookie;
13629 let mut rem = if (*c).pos <= (*c).len { (*c).len - (*c).pos } else { 0 };
13630 let mut l = len;
13631 if l > rem {
13632 l = rem;
13633 (*f).flags |= F_EOF;
13634 }
13635 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), buf, l);
13636 (*c).pos += l;
13637 rem -= l;
13638 if rem > (*f).buf_size { rem = (*f).buf_size; }
13639 (*f).rpos = (*f).buf;
13640 (*f).rend = (*f).buf.add(rem);
13641 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), (*f).rpos, rem);
13642 (*c).pos += rem;
13643 l
13644}
13645
13646unsafe extern "C" fn mwrite(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13647 let c = (*f).cookie as *mut MfCookie;
13648 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13649 if buffered > 0 {
13650 (*f).wpos = (*f).wbase;
13651 if mwrite(f, (*f).wbase, buffered) < buffered { return 0; }
13652 }
13653 if len == 0 { return 0; }
13654 if (*c).mode == b'a' as c_char { (*c).pos = (*c).len; }
13655 let rem = (*c).size - (*c).pos;
13656 let mut l = len;
13657 if l > rem { l = rem; }
13658 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), l);
13659 (*c).pos += l;
13660 if (*c).pos > (*c).len {
13661 (*c).len = (*c).pos;
13662 if (*c).len < (*c).size {
13663 *(*c).buf.add((*c).len) = 0;
13664 } else if ((*f).flags & F_NORD) != 0 && (*c).size > 0 {
13665 *(*c).buf.add((*c).size - 1) = 0;
13666 }
13667 }
13668 l
13669}
13670
13671unsafe extern "C" fn mclose(_f: *mut FILE) -> c_int {
13672 0
13673}
13674
13675#[no_mangle]
13676pub unsafe extern "C" fn fmemopen(buf: *mut c_void, size: usize, mode: *const c_char) -> *mut FILE {
13677 if mode.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
13678 let m = *mode;
13679 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
13680 ERRNO = EINVAL; return core::ptr::null_mut();
13681 }
13682 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
13683 let need_alloc = buf.is_null();
13684 let alloc_size = core::mem::size_of::<FILE>() + UNGET + BUFSIZ + if need_alloc { size } else { 0 };
13685 let f = calloc(1, alloc_size) as *mut FILE;
13686 if f.is_null() { ERRNO = ENOMEM; return core::ptr::null_mut(); }
13687 let buf_area = buf_ptr(f);
13688 init_file(f, -1, mode, Some(mclose), buf_area, BUFSIZ);
13689 (*f).flags |= F_SVB;
13690 let actual_buf: *mut u8 = if need_alloc {
13691 (f as *mut u8).add(alloc_size - size)
13692 } else {
13693 buf as *mut u8
13694 };
13695 if need_alloc { core::ptr::write_bytes(actual_buf, 0, size); }
13696 let c = calloc(1, core::mem::size_of::<MfCookie>()) as *mut MfCookie;
13697 if c.is_null() { free(f as *mut c_void); ERRNO = ENOMEM; return core::ptr::null_mut(); }
13698 (*c).buf = actual_buf;
13699 (*c).size = size;
13700 (*c).mode = m;
13701 (*f).cookie = c as *mut c_void;
13702 (*f).read_fn = Some(mread);
13703 (*f).write_fn = Some(mwrite);
13704 (*f).seek_fn = Some(mseek);
13705 if !has_plus { (*f).flags = if m == b'r' as c_char { F_NOWR } else { F_NORD }; }
13706 if m == b'r' as c_char {
13707 (*c).len = size;
13708 } else if m == b'a' as c_char {
13709 (*c).len = strnlen(actual_buf, size);
13710 (*c).pos = (*c).len;
13711 } else if has_plus {
13712 *actual_buf = 0;
13713 }
13714 f
13715}
13716
13717#[repr(C)]
13722struct kernel_stat64 {
13723 st_dev: u64,
13724 st_ino: u64,
13725 st_nlink: u64,
13726 st_mode: u32,
13727 st_uid: u32,
13728 st_gid: u32,
13729 __pad0: c_int,
13730 st_rdev: u64,
13731 st_size: i64,
13732 st_blksize: i64,
13733 st_blocks: i64,
13734 st_atime: i64,
13735 st_atime_nsec: i64,
13736 st_mtime: i64,
13737 st_mtime_nsec: i64,
13738 st_ctime: i64,
13739 st_ctime_nsec: i64,
13740 __unused: [i64; 3],
13741}
13742
13743#[inline]
13745unsafe fn sys_stat(path: *const u8, statbuf: *mut kernel_stat64) -> i64 {
13746 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, statbuf as i64, 0)
13747}
13748
13749const HSEARCH_MINSIZE: usize = 8;
13754
13755#[repr(C)]
13756#[derive(Copy, Clone)]
13757pub struct HSearchEntry {
13758 key: *mut c_char,
13759 data: *mut c_void,
13760}
13761
13762#[repr(C)]
13763struct HTab {
13764 entries: *mut HSearchEntry,
13765 mask: usize,
13766 used: usize,
13767}
13768
13769#[repr(C)]
13770pub struct HSearchData {
13771 tab: *mut HTab,
13772 __unused1: c_uint,
13773 __unused2: c_uint,
13774}
13775
13776static mut HTAB_DATA: HSearchData = HSearchData {
13778 tab: core::ptr::null_mut(),
13779 __unused1: 0,
13780 __unused2: 0,
13781};
13782
13783unsafe fn keyhash(k: *const c_char) -> usize {
13784 let mut h: usize = 0;
13785 let mut p = k;
13786 while *p != 0 {
13787 h = h.wrapping_mul(31).wrapping_add(*p as usize);
13788 p = p.add(1);
13789 }
13790 h
13791}
13792
13793unsafe fn htab_lookup(key: *const c_char, hash: usize, htab: *mut HSearchData) -> *mut HSearchEntry {
13794 let tab = (*htab).tab;
13795 let mask = (*tab).mask;
13796 let entries = (*tab).entries;
13797 let mut i = hash;
13798 let mut j: usize = 1;
13799 loop {
13800 let e = entries.add(i & mask);
13801 if (*e).key.is_null() || strcmp((*e).key as *const u8, key as *const u8) == 0 {
13802 return e;
13803 }
13804 i = i.wrapping_add(j);
13805 j += 1;
13806 }
13807}
13808
13809unsafe fn htab_resize(nel: usize, htab: *mut HSearchData) -> c_int {
13810 let tab = (*htab).tab;
13811 let old_entries = (*tab).entries;
13812 let old_size = (*tab).mask + 1;
13813
13814 let mut newsize: usize = HSEARCH_MINSIZE;
13815 while newsize < nel {
13816 let Some(next) = newsize.checked_mul(2) else {
13817 ERRNO = ENOMEM;
13818 return 0;
13819 };
13820 newsize = next;
13821 }
13822
13823 let new_entries = calloc(newsize, core::mem::size_of::<HSearchEntry>()) as *mut HSearchEntry;
13824 if new_entries.is_null() {
13825 ERRNO = ENOMEM;
13826 return 0;
13827 }
13828 (*tab).entries = new_entries;
13829 (*tab).mask = newsize - 1;
13830
13831 if !old_entries.is_null() {
13832 for idx in 0..old_size {
13833 let old_e = old_entries.add(idx);
13834 if !(*old_e).key.is_null() {
13835 let h = keyhash((*old_e).key);
13836 let mut i = h;
13837 let mut j: usize = 1;
13838 loop {
13839 let e = new_entries.add(i & (*tab).mask);
13840 if (*e).key.is_null() {
13841 *e = *old_e;
13842 break;
13843 }
13844 i = i.wrapping_add(j);
13845 j += 1;
13846 }
13847 }
13848 }
13849 free(old_entries as *mut c_void);
13850 }
13851 1
13852}
13853
13854unsafe fn hcreate_r_impl(nel: usize, htab: *mut HSearchData) -> c_int {
13855 if nel == 0 || nel > (1usize << 30) {
13856 ERRNO = ENOMEM;
13857 return 0;
13858 }
13859 (*htab).tab = calloc(1, core::mem::size_of::<HTab>()) as *mut HTab;
13860 if (*htab).tab.is_null() {
13861 ERRNO = ENOMEM;
13862 return 0;
13863 }
13864 if htab_resize(nel, htab) == 0 {
13865 free((*htab).tab as *mut c_void);
13866 (*htab).tab = core::ptr::null_mut();
13867 return 0;
13868 }
13869 1
13870}
13871
13872unsafe fn hdestroy_r_impl(htab: *mut HSearchData) {
13873 if !(*htab).tab.is_null() {
13874 if !(*(*htab).tab).entries.is_null() {
13875 free((*(*htab).tab).entries as *mut c_void);
13876 }
13877 free((*htab).tab as *mut c_void);
13878 (*htab).tab = core::ptr::null_mut();
13879 }
13880}
13881
13882unsafe fn hsearch_r_impl(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
13883 let hash = keyhash(item.key);
13884 let e = htab_lookup(item.key, hash, htab);
13885
13886 if !(*e).key.is_null() {
13887 *retval = e;
13888 return 1;
13889 }
13890 if action == 0 { *retval = core::ptr::null_mut();
13892 return 0;
13893 }
13894 let item_key = item.key;
13896 *e = item;
13897 (*(*htab).tab).used += 1;
13898 if (*(*htab).tab).used > (*(*htab).tab).mask - (*(*htab).tab).mask / 4 {
13899 if htab_resize(2 * (*(*htab).tab).used, htab) == 0 {
13900 (*(*htab).tab).used -= 1;
13901 (*e).key = core::ptr::null_mut();
13902 *retval = core::ptr::null_mut();
13903 return 0;
13904 }
13905 let e2 = htab_lookup(item_key, hash, htab);
13906 *retval = e2;
13907 return 1;
13908 }
13909 *retval = e;
13910 1
13911}
13912
13913#[no_mangle]
13914pub unsafe extern "C" fn hcreate(nel: usize) -> c_int {
13915 hcreate_r_impl(nel, core::ptr::addr_of_mut!(HTAB_DATA))
13916}
13917
13918#[no_mangle]
13919pub unsafe extern "C" fn hdestroy() {
13920 hdestroy_r_impl(core::ptr::addr_of_mut!(HTAB_DATA));
13921}
13922
13923#[no_mangle]
13924pub unsafe extern "C" fn hsearch(item: HSearchEntry, action: c_int) -> *mut HSearchEntry {
13925 let mut e: *mut HSearchEntry = core::ptr::null_mut();
13926 hsearch_r_impl(item, action, &mut e, core::ptr::addr_of_mut!(HTAB_DATA));
13927 e
13928}
13929
13930#[no_mangle]
13931pub unsafe extern "C" fn hcreate_r(nel: usize, htab: *mut HSearchData) -> c_int {
13932 hcreate_r_impl(nel, htab)
13933}
13934
13935#[no_mangle]
13936pub unsafe extern "C" fn hdestroy_r(htab: *mut HSearchData) {
13937 hdestroy_r_impl(htab);
13938}
13939
13940#[no_mangle]
13941pub unsafe extern "C" fn hsearch_r(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
13942 hsearch_r_impl(item, action, retval, htab)
13943}
13944
13945#[repr(C)]
13950struct QueNode {
13951 next: *mut QueNode,
13952 prev: *mut QueNode,
13953}
13954
13955#[no_mangle]
13956pub unsafe extern "C" fn insque(element: *mut c_void, pred: *mut c_void) {
13957 let e = element as *mut QueNode;
13958 let p = pred as *mut QueNode;
13959 if p.is_null() {
13960 (*e).next = core::ptr::null_mut();
13961 (*e).prev = core::ptr::null_mut();
13962 return;
13963 }
13964 (*e).next = (*p).next;
13965 (*e).prev = p;
13966 (*p).next = e;
13967 if !(*e).next.is_null() {
13968 (*(*e).next).prev = e;
13969 }
13970}
13971
13972#[no_mangle]
13973pub unsafe extern "C" fn remque(element: *mut c_void) {
13974 let e = element as *mut QueNode;
13975 if !(*e).next.is_null() {
13976 (*(*e).next).prev = (*e).prev;
13977 }
13978 if !(*e).prev.is_null() {
13979 (*(*e).prev).next = (*e).next;
13980 }
13981}
13982
13983#[no_mangle]
13988pub unsafe extern "C" fn lsearch(
13989 key: *const c_void,
13990 base: *mut c_void,
13991 nelp: *mut usize,
13992 width: usize,
13993 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
13994) -> *mut c_void {
13995 let n = *nelp;
13996 let p = base as *mut u8;
13997 for i in 0..n {
13998 let elem = p.add(i * width);
13999 if compar.unwrap()(key, elem as *const c_void) == 0 {
14000 return elem as *mut c_void;
14001 }
14002 }
14003 let dest = p.add(n * width);
14004 memcpy(dest as *mut c_void, key as *const c_void, width);
14005 *nelp = n + 1;
14006 dest as *mut c_void
14007}
14008
14009#[no_mangle]
14010pub unsafe extern "C" fn lfind(
14011 key: *const c_void,
14012 base: *const c_void,
14013 nelp: *mut usize,
14014 width: usize,
14015 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
14016) -> *mut c_void {
14017 let n = *nelp;
14018 let p = base as *const u8;
14019 for i in 0..n {
14020 let elem = p.add(i * width);
14021 if compar.unwrap()(key, elem as *const c_void) == 0 {
14022 return elem as *mut c_void;
14023 }
14024 }
14025 core::ptr::null_mut()
14026}
14027
14028#[repr(C)]
14034pub struct TreeNode {
14035 key: *const c_void,
14036 left: *mut TreeNode,
14037 right: *mut TreeNode,
14038}
14039
14040type ComparFn = Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>;
14041
14042unsafe fn bst_new(key: *const c_void) -> *mut TreeNode {
14043 let n = calloc(1, core::mem::size_of::<TreeNode>()) as *mut TreeNode;
14044 if !n.is_null() {
14045 (*n).key = key;
14046 (*n).left = core::ptr::null_mut();
14047 (*n).right = core::ptr::null_mut();
14048 }
14049 n
14050}
14051
14052#[no_mangle]
14053pub unsafe extern "C" fn tsearch(
14054 key: *const c_void,
14055 rootp: *mut *mut TreeNode,
14056 compar: ComparFn,
14057) -> *mut c_void {
14058 if rootp.is_null() {
14059 return core::ptr::null_mut();
14060 }
14061 let mut pp = rootp;
14062 loop {
14063 let n = *pp;
14064 if n.is_null() {
14065 let r = bst_new(key);
14066 if r.is_null() {
14067 return core::ptr::null_mut();
14068 }
14069 *pp = r;
14070 return r as *mut c_void;
14071 }
14072 let c = compar.unwrap()(key, (*n).key);
14073 if c == 0 {
14074 return n as *mut c_void;
14075 }
14076 if c < 0 {
14077 pp = &mut (*n).left;
14078 } else {
14079 pp = &mut (*n).right;
14080 }
14081 }
14082}
14083
14084#[no_mangle]
14085pub unsafe extern "C" fn tfind(
14086 key: *const c_void,
14087 rootp: *const *mut TreeNode,
14088 compar: ComparFn,
14089) -> *mut c_void {
14090 if rootp.is_null() {
14091 return core::ptr::null_mut();
14092 }
14093 let mut n = *rootp;
14094 loop {
14095 if n.is_null() {
14096 return core::ptr::null_mut();
14097 }
14098 let c = compar.unwrap()(key, (*n).key);
14099 if c == 0 {
14100 return n as *mut c_void;
14101 }
14102 if c < 0 {
14103 n = (*n).left;
14104 } else {
14105 n = (*n).right;
14106 }
14107 }
14108}
14109
14110#[no_mangle]
14111pub unsafe extern "C" fn tdelete(
14112 key: *const c_void,
14113 rootp: *mut *mut TreeNode,
14114 compar: ComparFn,
14115) -> *mut c_void {
14116 if rootp.is_null() {
14117 return core::ptr::null_mut();
14118 }
14119 let mut pp = rootp;
14120 loop {
14121 let n = *pp;
14122 if n.is_null() {
14123 return core::ptr::null_mut();
14124 }
14125 let c = compar.unwrap()(key, (*n).key);
14126 if c == 0 {
14127 break;
14128 }
14129 if c < 0 {
14130 pp = &mut (*n).left;
14131 } else {
14132 pp = &mut (*n).right;
14133 }
14134 }
14135 let n = *pp;
14136 let parent = *rootp;
14138 if !(*n).left.is_null() {
14139 let mut q = &mut (*n).left;
14141 while !(*(*q)).right.is_null() {
14142 q = &mut (*(*q)).right;
14143 }
14144 let pred = *q;
14145 (*n).key = (*pred).key;
14147 *q = (*pred).left;
14149 free(pred as *mut c_void);
14150 } else {
14151 *pp = (*n).right;
14153 free(n as *mut c_void);
14154 }
14155 parent as *mut c_void
14156}
14157
14158#[no_mangle]
14159pub unsafe extern "C" fn twalk(
14160 root: *const TreeNode,
14161 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
14162) {
14163 unsafe fn walk(
14164 node: *const TreeNode,
14165 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
14166 depth: c_int,
14167 ) {
14168 if node.is_null() {
14169 return;
14170 }
14171 let is_leaf = (*node).left.is_null() && (*node).right.is_null();
14172 if is_leaf {
14173 action.unwrap()(node as *const c_void, 3, depth); } else {
14175 action.unwrap()(node as *const c_void, 0, depth); walk((*node).left, action, depth + 1);
14177 action.unwrap()(node as *const c_void, 1, depth); walk((*node).right, action, depth + 1);
14179 action.unwrap()(node as *const c_void, 2, depth); }
14181 }
14182 walk(root, action, 0);
14183}
14184
14185#[no_mangle]
14186pub unsafe extern "C" fn tdestroy(root: *mut TreeNode, freekey: Option<unsafe extern "C" fn(*mut c_void)>) {
14187 if root.is_null() {
14188 return;
14189 }
14190 tdestroy((*root).left, freekey);
14191 tdestroy((*root).right, freekey);
14192 if let Some(f) = freekey {
14193 f((*root).key as *mut c_void);
14194 }
14195 free(root as *mut c_void);
14196}
14197
14198const FNM_PATHNAME: c_int = 0x1;
14203const FNM_NOESCAPE: c_int = 0x2;
14204const FNM_PERIOD: c_int = 0x4;
14205const FNM_LEADING_DIR: c_int = 0x8;
14206const FNM_CASEFOLD: c_int = 0x10;
14207const FNM_NOMATCH: c_int = 1;
14208
14209const FNM_END: c_int = 0;
14210const FNM_STAR: c_int = -5;
14211const FNM_QUESTION: c_int = -4;
14212const FNM_BRACKET: c_int = -3;
14213const FNM_UNMATCHABLE: c_int = -2;
14214
14215fn ascii_tolower(c: u8) -> u8 {
14216 if c >= b'A' && c <= b'Z' { c + 32 } else { c }
14217}
14218
14219fn ascii_toupper(c: u8) -> u8 {
14220 if c >= b'a' && c <= b'z' { c - 32 } else { c }
14221}
14222
14223fn ascii_casefold(k: u8) -> u8 {
14224 let upper = ascii_toupper(k);
14225 if upper != k { upper } else { ascii_tolower(k) }
14226}
14227
14228unsafe fn pat_next(pat: *const u8, m: usize, flags: c_int) -> (c_int, usize) {
14231 if m == 0 || *pat == 0 {
14232 return (FNM_END, 0);
14233 }
14234 let mut p = pat;
14235 let mut step = 1usize;
14236 let mut esc = false;
14237 if *p == b'\\' && !(flags & FNM_NOESCAPE != 0) && *p.add(1) != 0 {
14238 p = p.add(1);
14239 step = 2;
14240 esc = true;
14241 }
14242 if *p == b'[' && !esc {
14243 let mut k = 1usize;
14245 if k < m && (*pat.add(k) == b'^' || *pat.add(k) == b'!') { k += 1; }
14246 if k < m && *pat.add(k) == b']' { k += 1; }
14247 while k < m && *pat.add(k) != 0 && *pat.add(k) != b']' {
14248 if k + 1 < m && *pat.add(k) == b'[' &&
14249 (*pat.add(k+1) == b':' || *pat.add(k+1) == b'.' || *pat.add(k+1) == b'=') {
14250 let z = *pat.add(k+1);
14251 k += 2;
14252 if k < m { k += 1; }
14253 while k < m && *pat.add(k) != 0 && (*pat.add(k-1) != z || *pat.add(k) != b']') { k += 1; }
14254 if k == m || *pat.add(k) == 0 { break; }
14255 }
14256 k += 1;
14257 }
14258 if k == m || *pat.add(k) == 0 {
14259 return (b'[' as c_int, 1);
14261 }
14262 return (FNM_BRACKET, k + 1);
14263 }
14264 if *p == b'*' && !esc {
14265 return (FNM_STAR, 1);
14266 }
14267 if *p == b'?' && !esc {
14268 return (FNM_QUESTION, 1);
14269 }
14270 (*p as c_int, step)
14271}
14272
14273unsafe fn match_class(name: &[u8], k: u8, kfold: u8) -> bool {
14274 let eq = |c: u8| k == c || kfold == c;
14275 let in_range = |lo: u8, hi: u8| (k >= lo && k <= hi) || (kfold >= lo && kfold <= hi);
14276 match name {
14277 b"alnum" => in_range(b'0', b'9') || in_range(b'A', b'Z') || in_range(b'a', b'z'),
14278 b"alpha" => in_range(b'A', b'Z') || in_range(b'a', b'z'),
14279 b"blank" => eq(b' ') || eq(b'\t'),
14280 b"cntrl" => k < 0x20 || k == 0x7f,
14281 b"digit" => in_range(b'0', b'9'),
14282 b"graph" => k >= 0x21 && k <= 0x7e,
14283 b"lower" => in_range(b'a', b'z'),
14284 b"print" => k >= 0x20 && k <= 0x7e,
14285 b"punct" =>
14286 (k >= 0x21 && k <= 0x2f) ||
14287 (k >= 0x3a && k <= 0x40) ||
14288 (k >= 0x5b && k <= 0x60) ||
14289 (k >= 0x7b && k <= 0x7e),
14290 b"space" => eq(b' ') || eq(b'\t') || eq(b'\n') || eq(b'\r') || eq(0x0c) || eq(0x0b),
14291 b"upper" => in_range(b'A', b'Z'),
14292 b"xdigit" => in_range(b'0', b'9') || in_range(b'A', b'F') || in_range(b'a', b'f'),
14293 _ => false,
14294 }
14295}
14296
14297unsafe fn match_bracket(mut p: *const u8, k: u8, kfold: u8) -> bool {
14299 let mut inv = false;
14300 p = p.add(1); if *p == b'^' || *p == b'!' {
14302 inv = true;
14303 p = p.add(1);
14304 }
14305 if *p == b']' {
14307 if k == b']' { return !inv; }
14308 p = p.add(1);
14309 } else if *p == b'-' {
14310 if k == b'-' { return !inv; }
14311 p = p.add(1);
14312 }
14313 while *p != b']' && *p != 0 {
14314 if *p == b'-' && *p.add(1) != b']' && *p.add(1) != 0 {
14315 let lo = *p.sub(1);
14317 let hi = *p.add(1);
14318 if lo <= hi && (k >= lo && k <= hi || kfold >= lo && kfold <= hi) {
14319 return !inv;
14320 }
14321 p = p.add(2);
14322 } else if *p == b'[' && (*p.add(1) == b':' || *p.add(1) == b'.' || *p.add(1) == b'=') {
14323 let z = *p.add(1);
14324 let start = p.add(2);
14325 let mut q = start;
14326 while *q != 0 && (*q != z || *q.add(1) != b']') { q = q.add(1); }
14327 if *q != 0 {
14328 let len = (q as usize) - (start as usize);
14329 if len > 0 {
14330 let inner = core::slice::from_raw_parts(start, len);
14331 let matched =
14332 if z == b':' { match_class(inner, k, kfold) }
14333 else { len == 1 && (inner[0] == k || inner[0] == kfold) };
14334 if matched { return !inv; }
14335 }
14336 p = q.add(2);
14337 continue;
14338 }
14339 } else {
14340 if *p == k || *p == kfold {
14341 return !inv;
14342 }
14343 p = p.add(1);
14344 }
14345 }
14346 inv
14347}
14348
14349unsafe fn fnmatch_internal(pat: *const u8, str: *const u8, flags: c_int) -> c_int {
14351 if flags & FNM_PERIOD != 0 && *str == b'.' && *pat != b'.' {
14353 return FNM_NOMATCH;
14354 }
14355
14356 let mut p = pat;
14357 let mut s = str;
14358
14359 loop {
14361 let (tok, step) = pat_next(p, usize::MAX, flags);
14362 match tok {
14363 FNM_END => {
14364 return if *s == 0 { 0 } else { FNM_NOMATCH };
14365 }
14366 FNM_STAR => {
14367 p = p.add(1);
14368 break;
14369 }
14370 FNM_QUESTION => {
14371 if *s == 0 { return FNM_NOMATCH; }
14372 s = s.add(1);
14373 p = p.add(step);
14374 }
14375 FNM_BRACKET => {
14376 if *s == 0 { return FNM_NOMATCH; }
14377 let k = *s;
14378 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14379 if !match_bracket(p, k, kfold) { return FNM_NOMATCH; }
14380 p = p.add(step);
14381 s = s.add(1);
14382 }
14383 c => {
14384 if *s == 0 { return FNM_NOMATCH; }
14385 let k = *s;
14386 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14387 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14388 p = p.add(step);
14389 s = s.add(1);
14390 }
14391 }
14392 }
14393
14394 let mut ptail = p;
14397 let mut tailcnt: usize = 0;
14398 let mut pp = p;
14399 loop {
14400 let (tok, step) = pat_next(pp, usize::MAX, flags);
14401 if tok == FNM_END { break; }
14402 if tok == FNM_STAR {
14403 tailcnt = 0;
14404 ptail = pp.add(1);
14405 } else {
14406 tailcnt += 1;
14407 }
14408 pp = pp.add(step);
14409 }
14410
14411 let slen = strlen(s as *const c_char);
14413 if slen < tailcnt { return FNM_NOMATCH; }
14414
14415 let stail = s.add(slen - tailcnt);
14417 let mut tp = ptail;
14418 let mut ts = stail;
14419 loop {
14420 let (tok, step) = pat_next(tp, usize::MAX, flags);
14421 tp = tp.add(step);
14422 if tok == FNM_END {
14423 break;
14424 }
14425 let k = *ts;
14426 if k == 0 { return FNM_NOMATCH; }
14427 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14428 match tok {
14429 FNM_QUESTION => { ts = ts.add(1); }
14430 FNM_BRACKET => {
14431 if !match_bracket(tp.sub(step), k, kfold) { return FNM_NOMATCH; }
14432 ts = ts.add(1);
14433 }
14434 c => {
14435 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14436 ts = ts.add(1);
14437 }
14438 }
14439 }
14440
14441 let endstr = stail;
14442 let endpat = ptail;
14443
14444 let mut cp = p;
14445 let mut cs = s;
14446 while cp < endpat {
14447 let (tok, step) = pat_next(cp, usize::MAX, flags);
14448 if tok == FNM_STAR {
14449 cp = cp.add(step);
14450 cs = s;
14451 continue;
14452 }
14453 let comp_start = cp;
14454 let mut ok = false;
14455 let mut try_s = cs;
14456 while try_s < endstr {
14457 let mut tmp_p = comp_start;
14458 let mut tmp_s = try_s;
14459 let mut matched = true;
14460 loop {
14461 let (t, st) = pat_next(tmp_p, usize::MAX, flags);
14462 if t == FNM_STAR || t == FNM_END {
14463 cp = tmp_p;
14464 cs = tmp_s;
14465 ok = true;
14466 break;
14467 }
14468 if *tmp_s == 0 {
14469 matched = false;
14470 break;
14471 }
14472 let k = *tmp_s;
14473 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14474 match t {
14475 FNM_QUESTION => {
14476 tmp_s = tmp_s.add(1);
14477 }
14478 FNM_BRACKET => {
14479 if !match_bracket(tmp_p, k, kfold) {
14480 matched = false;
14481 break;
14482 }
14483 tmp_s = tmp_s.add(1);
14484 }
14485 c => {
14486 if k as c_int != c && kfold as c_int != c {
14487 matched = false;
14488 break;
14489 }
14490 tmp_s = tmp_s.add(1);
14491 }
14492 }
14493 tmp_p = tmp_p.add(st);
14494 }
14495 if ok { break; }
14496 if !matched {
14497 try_s = try_s.add(1);
14498 }
14499 }
14500 if !ok {
14501 return FNM_NOMATCH;
14502 }
14503 }
14504 0
14505}
14506
14507#[no_mangle]
14508pub unsafe extern "C" fn fnmatch(pat: *const c_char, str: *const c_char, flags: c_int) -> c_int {
14509 let pat = pat as *const u8;
14510 let str = str as *const u8;
14511
14512 if flags & FNM_PATHNAME != 0 {
14513 let mut s = str;
14515 let mut p = pat;
14516 loop {
14517 let mut send = s;
14519 while *send != 0 && *send != b'/' { send = send.add(1); }
14520 let mut pend = p;
14522 loop {
14523 let (tok, step) = pat_next(pend, usize::MAX, flags);
14524 if tok == FNM_END || (tok >= 0 && tok as u8 == b'/') {
14525 break;
14526 }
14527 pend = pend.add(step);
14528 }
14529 let (ptok, pstep) = pat_next(pend, usize::MAX, flags);
14530 let pat_is_slash = ptok >= 0 && ptok as u8 == b'/';
14531 let str_is_slash = *send == b'/';
14532 if pat_is_slash != str_is_slash && (*send != 0 || !(flags & FNM_LEADING_DIR != 0)) {
14533 return FNM_NOMATCH;
14534 }
14535 let plen = (pend as usize) - (p as usize);
14538 let slen = (send as usize) - (s as usize);
14539 if plen > 1024 || slen > 1024 { return FNM_NOMATCH; }
14542 let mut pbuf = [0u8; 1025];
14543 let mut sbuf = [0u8; 1025];
14544 core::ptr::copy_nonoverlapping(p, pbuf.as_mut_ptr(), plen);
14545 pbuf[plen] = 0;
14546 core::ptr::copy_nonoverlapping(s, sbuf.as_mut_ptr(), slen);
14547 sbuf[slen] = 0;
14548 if fnmatch_internal(pbuf.as_ptr(), sbuf.as_ptr(), flags & !FNM_LEADING_DIR) != 0 {
14549 return FNM_NOMATCH;
14550 }
14551 if !pat_is_slash {
14552 return 0;
14553 }
14554 s = send.add(1);
14555 p = pend.add(pstep);
14556 }
14557 }
14558
14559 if flags & FNM_LEADING_DIR != 0 {
14560 let mut s = str;
14562 while *s != 0 {
14563 if *s == b'/' {
14564 let len = (s as usize) - (str as usize);
14567 if len < 4096 {
14569 let mut buf = [0u8; 4096];
14570 core::ptr::copy_nonoverlapping(str, buf.as_mut_ptr(), len);
14571 buf[len] = 0;
14572 if fnmatch_internal(pat, buf.as_ptr(), flags) == 0 {
14573 return 0;
14574 }
14575 }
14576 }
14577 s = s.add(1);
14578 }
14579 }
14580
14581 fnmatch_internal(pat, str, flags)
14582}
14583
14584#[no_mangle]
14589pub unsafe extern "C" fn setmntent(name: *const c_char, mode: *const c_char) -> *mut FILE {
14590 fopen(name, mode)
14591}
14592
14593#[no_mangle]
14594pub unsafe extern "C" fn endmntent(f: *mut FILE) -> c_int {
14595 if !f.is_null() {
14596 fclose(f);
14597 }
14598 1
14599}
14600
14601static mut MNTENT_MNT: MntEnt = MntEnt {
14603 mnt_fsname: core::ptr::null_mut(),
14604 mnt_dir: core::ptr::null_mut(),
14605 mnt_type: core::ptr::null_mut(),
14606 mnt_opts: core::ptr::null_mut(),
14607 mnt_freq: 0,
14608 mnt_passno: 0,
14609};
14610
14611#[repr(C)]
14612pub struct MntEnt {
14613 mnt_fsname: *mut c_char,
14614 mnt_dir: *mut c_char,
14615 mnt_type: *mut c_char,
14616 mnt_opts: *mut c_char,
14617 mnt_freq: c_int,
14618 mnt_passno: c_int,
14619}
14620
14621unsafe fn unescape_ent(beg: *mut c_char) -> *mut c_char {
14622 let mut dest = beg;
14623 let mut src = beg;
14624 while *src != 0 {
14625 if *src != b'\\' as c_char {
14626 *dest = *src;
14627 dest = dest.add(1);
14628 src = src.add(1);
14629 continue;
14630 }
14631 if *src.add(1) == b'\\' as c_char {
14633 src = src.add(1);
14634 *dest = *src;
14635 dest = dest.add(1);
14636 src = src.add(1);
14637 continue;
14638 }
14639 let mut val: u8 = 0;
14641 let mut cnt = 0;
14642 let mut sp = src.add(1);
14643 while cnt < 3 && *sp >= b'0' as c_char && *sp <= b'7' as c_char {
14644 val = val * 8 + (*sp as u8 - b'0');
14645 sp = sp.add(1);
14646 cnt += 1;
14647 }
14648 if cnt > 0 {
14649 *dest = val as c_char;
14650 dest = dest.add(1);
14651 src = sp;
14652 } else {
14653 *dest = *src;
14654 dest = dest.add(1);
14655 src = src.add(1);
14656 }
14657 }
14658 *dest = 0;
14659 beg
14660}
14661
14662unsafe fn parse_mntent_line(
14663 linebuf: *mut c_char,
14664 mnt: *mut MntEnt,
14665) -> *mut MntEnt {
14666 let _len = strlen(linebuf as *const c_char);
14667 let mut p = linebuf;
14670 while *p == b' ' as c_char || *p == b'\t' as c_char || *p == b'\n' as c_char || *p == b'\r' as c_char {
14672 p = p.add(1);
14673 }
14674 if *p == 0 || *p == b'#' as c_char {
14675 return core::ptr::null_mut();
14676 }
14677
14678 (*mnt).mnt_fsname = p;
14680 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14681 p = p.add(1);
14682 }
14683 if *p == 0 { return core::ptr::null_mut(); }
14684 *p = 0;
14685 p = p.add(1);
14686 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14687
14688 (*mnt).mnt_dir = p;
14690 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14691 p = p.add(1);
14692 }
14693 if *p == 0 { return core::ptr::null_mut(); }
14694 *p = 0;
14695 p = p.add(1);
14696 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14697
14698 (*mnt).mnt_type = p;
14700 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14701 p = p.add(1);
14702 }
14703 if *p == 0 { return core::ptr::null_mut(); }
14704 *p = 0;
14705 p = p.add(1);
14706 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14707
14708 (*mnt).mnt_opts = p;
14710 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14711 p = p.add(1);
14712 }
14713 if *p != 0 {
14714 *p = 0;
14715 p = p.add(1);
14716 }
14717 if *(*mnt).mnt_opts == 0 {
14718 (*mnt).mnt_opts = b"defaults\0".as_ptr() as *mut c_char;
14719 }
14720
14721 (*mnt).mnt_freq = 0;
14723 (*mnt).mnt_passno = 0;
14724 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14726 if *p >= b'0' as c_char && *p <= b'9' as c_char {
14727 (*mnt).mnt_freq = (*p - b'0' as c_char) as c_int;
14728 p = p.add(1);
14729 while *p >= b'0' as c_char && *p <= b'9' as c_char {
14730 (*mnt).mnt_freq = (*mnt).mnt_freq * 10 + (*p - b'0' as c_char) as c_int;
14731 p = p.add(1);
14732 }
14733 }
14734 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14735 if *p >= b'0' as c_char && *p <= b'9' as c_char {
14736 (*mnt).mnt_passno = (*p - b'0' as c_char) as c_int;
14737 p = p.add(1);
14738 while *p >= b'0' as c_char && *p <= b'9' as c_char {
14739 (*mnt).mnt_passno = (*mnt).mnt_passno * 10 + (*p - b'0' as c_char) as c_int;
14740 p = p.add(1);
14741 }
14742 }
14743
14744 unescape_ent((*mnt).mnt_fsname);
14746 unescape_ent((*mnt).mnt_dir);
14747 unescape_ent((*mnt).mnt_type);
14748 unescape_ent((*mnt).mnt_opts);
14749
14750 mnt
14751}
14752
14753static SENTINEL_PTR: usize = 1;
14756
14757unsafe fn mntent_fgetc(f: *mut FILE) -> c_int {
14759 fgetc(f)
14760}
14761
14762unsafe fn mntent_fgets(buf: *mut c_char, n: usize, f: *mut FILE) -> *mut c_char {
14763 if n == 0 { return core::ptr::null_mut(); }
14764 let max = n - 1;
14765 let mut i = 0usize;
14766 while i < max {
14767 let c = mntent_fgetc(f);
14768 if c == -1 { if i == 0 { return core::ptr::null_mut(); } break; }
14769 *buf.add(i) = c as c_char;
14770 i += 1;
14771 if c == b'\n' as c_int { break; }
14772 }
14773 *buf.add(i) = 0;
14774 buf
14775}
14776
14777#[no_mangle]
14778pub unsafe extern "C" fn getmntent_r(
14779 f: *mut FILE,
14780 mnt: *mut MntEnt,
14781 mut linebuf: *mut c_char,
14782 _buflen: c_int,
14783) -> *mut MntEnt {
14784 let use_internal = linebuf as usize == SENTINEL_PTR;
14785
14786 (*mnt).mnt_freq = 0;
14787 (*mnt).mnt_passno = 0;
14788
14789 static mut INTERNAL_BUF: [c_char; 4096] = [0; 4096];
14791
14792 loop {
14793 if use_internal {
14794 linebuf = core::ptr::addr_of_mut!(INTERNAL_BUF).cast::<c_char>();
14795 }
14796 let res = mntent_fgets(linebuf, 4096, f);
14797 if res.is_null() {
14798 return core::ptr::null_mut();
14799 }
14800 let mut has_newline = false;
14801 let mut p = linebuf;
14802 while *p != 0 { if *p == b'\n' as c_char { has_newline = true; break; } p = p.add(1); }
14803 if !has_newline {
14804 ERRNO = 34;
14805 return core::ptr::null_mut();
14806 }
14807 let result = parse_mntent_line(linebuf, mnt);
14808 if !result.is_null() {
14809 return result;
14810 }
14811 }
14812}
14813
14814#[no_mangle]
14815pub unsafe extern "C" fn getmntent(f: *mut FILE) -> *mut MntEnt {
14816 getmntent_r(f, core::ptr::addr_of_mut!(MNTENT_MNT), SENTINEL_PTR as *mut c_char, 0)
14817}
14818
14819#[no_mangle]
14820pub unsafe extern "C" fn addmntent(f: *mut FILE, mnt: *const MntEnt) -> c_int {
14821 fseek(f, 0, 2); let written = fprintf(
14823 f,
14824 b"%s\t%s\t%s\t%s\t%d\t%d\n\0".as_ptr() as *const c_char,
14825 (*mnt).mnt_fsname,
14826 (*mnt).mnt_dir,
14827 (*mnt).mnt_type,
14828 (*mnt).mnt_opts,
14829 (*mnt).mnt_freq,
14830 (*mnt).mnt_passno,
14831 );
14832 if written < 0 { 1 } else { 0 }
14833}
14834
14835#[no_mangle]
14836pub unsafe extern "C" fn hasmntopt(mnt: *const MntEnt, opt: *const c_char) -> *mut c_char {
14837 let l = strlen(opt as *const c_char);
14838 let mut p = (*mnt).mnt_opts;
14839 loop {
14840 if strncmp(p as *const u8, opt as *const u8, l) == 0 {
14841 let after = *p.add(l);
14842 if after == 0 || after == b',' as c_char || after == b'=' as c_char {
14843 return p;
14844 }
14845 }
14846 let comma = strchr(p as *const u8, b',' as c_int);
14847 if comma.is_null() {
14848 return core::ptr::null_mut();
14849 }
14850 p = comma.add(1) as *mut c_char;
14851 }
14852}
14853
14854const EEXIST: c_int = 17;
14862const ENAMETOOLONG: c_int = 36;
14863const EMFILE: c_int = 24;
14864const EIDRM: c_int = 43;
14865
14866#[inline]
14867unsafe fn sys_msgget(key: c_int, msgflg: c_int) -> i64 {
14868 <Arch as Syscalls>::syscall2(SYS_MSGGET, key as i64, msgflg as i64)
14869}
14870
14871#[inline]
14872unsafe fn sys_msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> i64 {
14873 <Arch as Syscalls>::syscall4(SYS_MSGSND, msqid as i64, msgp as i64, msgsz as i64, msgflg as i64)
14874}
14875
14876#[inline]
14877unsafe fn sys_msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> i64 {
14878 <Arch as Syscalls>::syscall5(SYS_MSGRCV, msqid as i64, msgp as i64, msgsz as i64, msgtyp as i64, msgflg as i64)
14879}
14880
14881#[inline]
14882unsafe fn sys_msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
14883 <Arch as Syscalls>::syscall3(SYS_MSGCTL, msqid as i64, cmd as i64, buf as i64)
14884}
14885
14886#[inline]
14887unsafe fn sys_semget(key: c_int, nsems: c_int, semflg: c_int) -> i64 {
14888 <Arch as Syscalls>::syscall3(SYS_SEMGET, key as i64, nsems as i64, semflg as i64)
14889}
14890
14891#[inline]
14892unsafe fn sys_semop(semid: c_int, sops: *const c_void, nsops: usize) -> i64 {
14893 <Arch as Syscalls>::syscall3(SYS_SEMOP, semid as i64, sops as i64, nsops as i64)
14894}
14895
14896#[inline]
14897unsafe fn sys_semctl(semid: c_int, semnum: c_int, cmd: c_int, arg: *mut c_void) -> i64 {
14898 <Arch as Syscalls>::syscall4(SYS_SEMCTL, semid as i64, semnum as i64, cmd as i64, arg as i64)
14899}
14900
14901#[inline]
14902unsafe fn sys_shmget(key: c_int, size: usize, shmflg: c_int) -> i64 {
14903 <Arch as Syscalls>::syscall3(SYS_SHMGET, key as i64, size as i64, shmflg as i64)
14904}
14905
14906#[inline]
14907unsafe fn sys_shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> i64 {
14908 <Arch as Syscalls>::syscall3(SYS_SHMAT, shmid as i64, shmaddr as i64, shmflg as i64)
14909}
14910
14911#[inline]
14912unsafe fn sys_shmdt(shmaddr: *const c_void) -> i64 {
14913 <Arch as Syscalls>::syscall1(SYS_SHMDT, shmaddr as i64)
14914}
14915
14916#[inline]
14917unsafe fn sys_shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
14918 <Arch as Syscalls>::syscall3(SYS_SHMCTL, shmid as i64, cmd as i64, buf as i64)
14919}
14920
14921#[no_mangle]
14923pub unsafe extern "C" fn ftok(path: *const c_char, id: c_int) -> c_int {
14924 let mut st: kernel_stat64 = core::mem::zeroed();
14925 let r = sys_stat(path as *const u8, &mut st);
14926 if r < 0 {
14927 ERRNO = (-r) as c_int;
14928 return -1;
14929 }
14930 ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) | (((id as u32 & 0xff) << 24)) as u64) as c_int
14931}
14932
14933#[no_mangle]
14935pub unsafe extern "C" fn msgget(key: c_int, msgflg: c_int) -> c_int {
14936 let r = sys_msgget(key, msgflg);
14937 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14938}
14939
14940#[no_mangle]
14942pub unsafe extern "C" fn msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> c_int {
14943 let r = sys_msgsnd(msqid, msgp, msgsz, msgflg);
14944 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14945}
14946
14947#[no_mangle]
14949pub unsafe extern "C" fn msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> isize {
14950 let r = sys_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
14951 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
14952}
14953
14954#[no_mangle]
14956pub unsafe extern "C" fn msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
14957 let r = sys_msgctl(msqid, cmd, buf);
14958 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14959}
14960
14961#[no_mangle]
14963pub unsafe extern "C" fn semget(key: c_int, nsems: c_int, semflg: c_int) -> c_int {
14964 if nsems > 65535 { ERRNO = 22; return -1; }
14965 let r = sys_semget(key, nsems, semflg);
14966 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14967}
14968
14969#[no_mangle]
14971pub unsafe extern "C" fn semop(semid: c_int, sops: *const c_void, nsops: usize) -> c_int {
14972 let r = sys_semop(semid, sops, nsops);
14973 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14974}
14975
14976#[no_mangle]
14978pub unsafe extern "C" fn semctl(semid: c_int, semnum: c_int, cmd: c_int, mut args: ...) -> c_int {
14979 let mut arg: *mut c_void = core::ptr::null_mut();
14980 match cmd {
14982 16 | 13 | 17 | 1 | 3 | 2 | 0x102 | 0x104 | 0x106 => {
14983 arg = args.next_arg::<*mut c_void>();
14984 }
14985 _ => {}
14986 }
14987 let r = sys_semctl(semid, semnum, cmd, arg);
14988 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14989}
14990
14991#[no_mangle]
14993pub unsafe extern "C" fn shmget(key: c_int, size: usize, shmflg: c_int) -> c_int {
14994 let r = sys_shmget(key, size, shmflg);
14995 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14996}
14997
14998#[no_mangle]
15000pub unsafe extern "C" fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void {
15001 let r = sys_shmat(shmid, shmaddr, shmflg);
15002 if (r as usize) > (-(4096isize as isize)) as usize {
15003 ERRNO = (-r) as c_int;
15004 return core::ptr::null_mut();
15005 }
15006 r as *mut c_void
15007}
15008
15009#[no_mangle]
15011pub unsafe extern "C" fn shmdt(shmaddr: *const c_void) -> c_int {
15012 let r = sys_shmdt(shmaddr);
15013 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
15014}
15015
15016#[no_mangle]
15018pub unsafe extern "C" fn shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
15019 let r = sys_shmctl(shmid, cmd, buf);
15020 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
15021}
15022
15023#[no_mangle]
15033pub static mut __auxv: *const usize = core::ptr::null();
15034
15035#[no_mangle]
15036pub static mut __progname: *mut c_char = core::ptr::null_mut();
15037#[no_mangle]
15038pub static mut __progname_full: *mut c_char = core::ptr::null_mut();
15039#[no_mangle]
15040pub static mut program_invocation_name: *mut c_char = core::ptr::null_mut();
15041#[no_mangle]
15042pub static mut program_invocation_short_name: *mut c_char = core::ptr::null_mut();
15043
15044#[no_mangle]
15045pub static in6addr_any: [u8; 16] = [0; 16];
15046#[no_mangle]
15047pub static in6addr_loopback: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
15048
15049#[no_mangle]
15050pub static mut __daylight: c_int = 0;
15051#[no_mangle]
15052pub static mut __timezone: c_long = 0;
15053#[no_mangle]
15054pub static mut __tzname: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
15055
15056#[no_mangle]
15057pub unsafe extern "C" fn getauxval(type_: c_ulong) -> c_ulong {
15058 let mut p = __auxv;
15059 if p.is_null() {
15060 return 0;
15061 }
15062 loop {
15063 let tag = *p;
15064 if tag == 0 {
15065 return 0;
15066 }
15067 if tag == type_ as usize {
15068 return *p.add(1) as c_ulong;
15069 }
15070 p = p.add(2);
15071 }
15072}
15073
15074type MainFn = unsafe extern "C" fn(c_int, *const *const c_char, *const *const c_char) -> c_int;
15075type InitFn = unsafe extern "C" fn();
15076
15077#[no_mangle]
15078pub unsafe extern "C" fn __libc_start_main(
15079 main: MainFn,
15080 argc: c_int,
15081 argv: *const *const c_char,
15082 _init: *const c_void,
15083 _fini: *const c_void,
15084 _rtld_fini: *const c_void,
15085 _stack_end: *const c_void,
15086) -> ! {
15087 let envp = argv.add((argc + 1) as usize);
15088 __environ = envp as *mut *mut c_char;
15089 environ = __environ; ___environ = __environ;
15091 _environ = __environ;
15092
15093 if !argv.is_null() && argc > 0 {
15095 let argv0 = *argv;
15096 __progname_full = argv0 as *mut c_char;
15097 program_invocation_name = argv0 as *mut c_char;
15098 let mut base = argv0;
15099 let mut p = argv0;
15100 while *p != 0 {
15101 if *p == b'/' as c_char { base = p.add(1); }
15102 p = p.add(1);
15103 }
15104 __progname = base as *mut c_char;
15105 program_invocation_short_name = base as *mut c_char;
15106 }
15107
15108 __stdio_init();
15109
15110 let mut set: SigSetT = 0;
15111 sigemptyset(&mut set);
15112 sigaddset(&mut set, SIGCANCEL);
15113 sigprocmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
15114
15115 if !_init.is_null() {
15116 let init_fn: InitFn = core::mem::transmute(_init);
15117 init_fn();
15118 }
15119
15120 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
15124 {
15125 let random_ptr = getauxval(25) as *const u8; if !random_ptr.is_null() {
15127 let a = core::ptr::read_unaligned(random_ptr as *const u64);
15128 let b = core::ptr::read_unaligned(random_ptr.add(8) as *const u64);
15129 __stack_chk_guard = (a ^ b) as usize;
15130 } else {
15131 __stack_chk_guard = 0xdefaced_cafebeef;
15133 }
15134 }
15135
15136 let result = main(argc, argv, envp);
15137
15138 if !_fini.is_null() {
15139 let fini_fn: InitFn = core::mem::transmute(_fini);
15140 fini_fn();
15141 }
15142
15143 exit(result);
15144}
15145
15146type LdsoDlopenFn = unsafe extern "C" fn(*const c_char, c_int) -> *mut c_void;
15147type LdsoDlsymFn = unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void;
15148type LdsoDlcloseFn = unsafe extern "C" fn(*mut c_void) -> c_int;
15149type LdsoDlerrorFn = unsafe extern "C" fn() -> *const c_char;
15150
15151static mut LDSO_DLOPEN: Option<LdsoDlopenFn> = None;
15152static mut LDSO_DLSYM: Option<LdsoDlsymFn> = None;
15153static mut LDSO_DLCLOSE: Option<LdsoDlcloseFn> = None;
15154static mut LDSO_DLERROR: Option<LdsoDlerrorFn> = None;
15155
15156#[no_mangle]
15157pub unsafe extern "C" fn __ldso_register_dlopen(f: LdsoDlopenFn) {
15158 LDSO_DLOPEN = Some(f);
15159}
15160
15161#[no_mangle]
15162pub unsafe extern "C" fn __ldso_register_dlsym(f: LdsoDlsymFn) {
15163 LDSO_DLSYM = Some(f);
15164}
15165
15166#[no_mangle]
15167pub unsafe extern "C" fn __ldso_register_dlclose(f: LdsoDlcloseFn) {
15168 LDSO_DLCLOSE = Some(f);
15169}
15170
15171#[no_mangle]
15172pub unsafe extern "C" fn __ldso_register_dlerror(f: LdsoDlerrorFn) {
15173 LDSO_DLERROR = Some(f);
15174}
15175
15176#[no_mangle]
15177pub unsafe extern "C" fn dlopen(filename: *const c_char, flags: c_int) -> *mut c_void {
15178 if let Some(f) = LDSO_DLOPEN {
15179 f(filename, flags)
15180 } else {
15181 null_mut()
15182 }
15183}
15184
15185#[no_mangle]
15186pub unsafe extern "C" fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void {
15187 if let Some(f) = LDSO_DLSYM {
15188 f(handle, symbol)
15189 } else {
15190 null_mut()
15191 }
15192}
15193
15194#[no_mangle]
15195pub unsafe extern "C" fn dlclose(handle: *mut c_void) -> c_int {
15196 if let Some(f) = LDSO_DLCLOSE {
15197 f(handle)
15198 } else {
15199 0
15200 }
15201}
15202
15203#[no_mangle]
15204pub unsafe extern "C" fn dlerror() -> *const c_char {
15205 if let Some(f) = LDSO_DLERROR {
15206 f()
15207 } else {
15208 core::ptr::null()
15209 }
15210}
15211
15212include!("crypt_impl.rs");
15213include!("statvfs.rs");
15214include!("daemon.rs");
15215include!("dn_expand.rs");
15216include!("lrand48.rs");
15217include!("strverscmp.rs");
15218include!("syscall.rs");
15219include!("pthread_atfork.rs");
15220include!("fenv.rs");
15221include!("locale_ctype.rs");
15222include!("regression_stubs.rs");
15223include!("netdb_extra.rs");
15224include!("compat_extra.rs");
15225include!("stdio_extra.rs");
15226include!("ns_parse.rs");
15227include!("fts.rs");
15228include!("ifaddrs.rs");
15229include!("dl_extra.rs");
15230include!("des.rs");
15231include!("path_extra.rs");
15232include!("wordexp.rs");
15233include!("getopt_impl.rs");
15234
15235type regoff_t = c_int;
15240
15241#[repr(C)]
15242pub struct regex_t {
15243 pub re_nsub: usize,
15244 pub __opaque: *mut c_void,
15245 pub __padding: [*mut c_void; 4],
15246 pub __nsub2: usize,
15247 pub __padding2: c_char,
15248}
15249
15250#[repr(C)]
15251pub struct regmatch_t {
15252 pub rm_so: regoff_t,
15253 pub rm_eo: regoff_t,
15254}
15255
15256include!("regex.rs");
15257
15258#[cfg(test)]
15259mod libc_unit_stub {
15260 #[test]
15261 fn stub() {
15262 assert!(true);
15263 }
15264}
15265
15266#[inline]
15271pub(crate) fn fmax_impl(x: f64, y: f64) -> f64 {
15272 if x.is_nan() { return y; }
15273 if y.is_nan() { return x; }
15274 if x == 0.0 && y == 0.0 {
15275 return if x.is_sign_negative() && y.is_sign_negative() { -0.0 } else { 0.0 };
15276 }
15277 if x > y { x } else { y }
15278}
15279
15280#[inline]
15281pub(crate) fn fmin_impl(x: f64, y: f64) -> f64 {
15282 if x.is_nan() { return y; }
15283 if y.is_nan() { return x; }
15284 if x == 0.0 && y == 0.0 {
15285 return if x.is_sign_negative() || y.is_sign_negative() { -0.0 } else { 0.0 };
15286 }
15287 if x < y { x } else { y }
15288}
15289
15290#[inline]
15291pub(crate) fn fmaxf_impl(x: f32, y: f32) -> f32 {
15292 if x.is_nan() { return y; }
15293 if y.is_nan() { return x; }
15294 if x == 0.0 && y == 0.0 {
15295 return if x.is_sign_negative() && y.is_sign_negative() { -0.0 } else { 0.0 };
15296 }
15297 if x > y { x } else { y }
15298}
15299
15300#[inline]
15301pub(crate) fn fminf_impl(x: f32, y: f32) -> f32 {
15302 if x.is_nan() { return y; }
15303 if y.is_nan() { return x; }
15304 if x == 0.0 && y == 0.0 {
15305 return if x.is_sign_negative() || y.is_sign_negative() { -0.0 } else { 0.0 };
15306 }
15307 if x < y { x } else { y }
15308}
15309
15310#[inline(never)]
15311#[no_mangle]
15312pub unsafe extern "C" fn fmax(x: f64, y: f64) -> f64 {
15313 fmax_impl(x, y)
15314}
15315
15316#[inline(never)]
15317#[no_mangle]
15318pub unsafe extern "C" fn fmin(x: f64, y: f64) -> f64 {
15319 fmin_impl(x, y)
15320}
15321
15322#[no_mangle]
15323pub unsafe extern "C" fn fminf(x: f32, y: f32) -> f32 {
15324 fminf_impl(x, y)
15325}
15326
15327#[no_mangle]
15328pub unsafe extern "C" fn fdim(x: f64, y: f64) -> f64 {
15329 if x.is_nan() || y.is_nan() {
15330 return f64::NAN;
15331 }
15332 if x > y { x - y } else { 0.0 }
15333}
15334
15335#[no_mangle]
15336pub unsafe extern "C" fn fma(x: f64, y: f64, z: f64) -> f64 {
15337 if (x.is_infinite() && y == 0.0) || (y.is_infinite() && x == 0.0) {
15338 feraiseexcept(FE_INVALID);
15339 return f64::NAN;
15340 }
15341 if x.is_nan() || y.is_nan() || z.is_nan() {
15342 return f64::NAN;
15343 }
15344 let r = libm::fma(x, y, z);
15345 if r.is_nan() {
15347 feraiseexcept(FE_INVALID);
15348 }
15349 r
15350}
15351
15352#[no_mangle]
15353pub unsafe extern "C" fn ilogb(x: f64) -> i32 {
15354 if x.is_nan() {
15355 feraiseexcept(FE_INVALID);
15356 return -0x7fffffff - 1; }
15358 if x == 0.0 || x.is_infinite() {
15359 feraiseexcept(FE_INVALID);
15360 return if x == 0.0 { -0x7fffffff - 1 } else { 0x7fffffff };
15361 }
15362 let bits = x.to_bits();
15363 let exp = ((bits >> 52) & 0x7ff) as i32;
15364 if exp == 0 {
15365 let mut v = bits & 0xfffffffffffff;
15367 let mut e = -1022;
15368 while v < (1u64 << 52) { v <<= 1; e -= 1; }
15369 e
15370 } else {
15371 exp - 1023
15372 }
15373}
15374
15375#[no_mangle]
15376pub unsafe extern "C" fn logb(x: f64) -> f64 {
15377 if x.is_nan() { return x; }
15378 if x == 0.0 { return __math_divzero(1); }
15379 let bits = x.to_bits();
15380 let exp = ((bits >> 52) & 0x7ff) as i32;
15381 if exp == 0 {
15382 let mut v = bits & 0xfffffffffffff;
15384 let mut e = -1022i32;
15385 while v < (1u64 << 52) { v <<= 1; e -= 1; }
15386 e as f64
15387 } else if exp == 0x7ff {
15388 x * x } else {
15390 (exp - 1023) as f64
15391 }
15392}
15393
15394#[no_mangle]
15395pub unsafe extern "C" fn nearbyint(x: f64) -> f64 {
15396 let had_inexact = fetestexcept(FE_INEXACT) & FE_INEXACT != 0;
15397 let r = libm::rint(x);
15398 if !had_inexact {
15399 feclearexcept(FE_INEXACT);
15400 }
15401 r
15402}
15403
15404#[no_mangle]
15405pub unsafe extern "C" fn nextafter(x: f64, y: f64) -> f64 {
15406 if x.is_nan() || y.is_nan() { return x + y; }
15407 if x == 0.0 && y == 0.0 { return y; }
15408 if x == y { return x; }
15409 let r = libm::nextafter(x, y);
15410 if r.is_infinite() && x.is_finite() {
15411 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
15412 } else if r != x {
15413 let bits = r.to_bits();
15414 let is_subnormal = (bits & 0x7ff0000000000000) == 0 && (bits & 0xfffffffffffff) != 0;
15415 if r == 0.0 || is_subnormal {
15416 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
15417 }
15418 }
15419 r
15420}
15421
15422#[no_mangle]
15423pub unsafe extern "C" fn nexttoward(x: f64, y: f64) -> f64 {
15424 if x == 0.0 && y == 0.0 {
15426 return if y.is_sign_negative() { -0.0 } else { 0.0 };
15427 }
15428 nextafter(x, y)
15429}
15430
15431#[no_mangle]
15432pub unsafe extern "C" fn remainder(x: f64, y: f64) -> f64 {
15433 if x.is_nan() || y.is_nan() { return x + y; }
15434 if y == 0.0 || x.is_infinite() { return __math_invalid(x); }
15435 libm::remainder(x, y)
15436}
15437
15438#[no_mangle]
15439pub unsafe extern "C" fn remquo(x: f64, y: f64, quo: *mut i32) -> f64 {
15440 if x.is_nan() || y.is_nan() {
15441 if !quo.is_null() { *quo = 0; }
15442 return x + y;
15443 }
15444 if y == 0.0 || x.is_infinite() {
15445 if !quo.is_null() { *quo = 0; }
15446 return __math_invalid(x);
15447 }
15448 let (r, q) = libm::remquo(x, y);
15449 if !quo.is_null() { *quo = q; }
15450 r
15451}
15452
15453#[no_mangle]
15454pub unsafe extern "C" fn exp2(x: f64) -> f64 {
15455 if x.is_nan() { return f64::NAN; }
15456 if x == f64::INFINITY { return f64::INFINITY; }
15457 if x == f64::NEG_INFINITY { return 0.0; }
15458 let r = libm::exp2(x);
15459 if r.is_infinite() && x.is_finite() {
15460 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
15461 } else if r == 0.0 && x < -1074.0 {
15462 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
15463 } else if r != 0.0 && x != libm::trunc(x) {
15464 let bits = r.to_bits();
15465 if (bits & 0x7ff0000000000000) == 0 {
15466 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
15467 }
15468 }
15469 r
15470}
15471
15472#[no_mangle]
15473pub unsafe extern "C" fn expm1(x: f64) -> f64 {
15474 let r = libm::expm1(x);
15475 if r != 0.0 && x != 0.0 && libm::fabs(x) < 1e-307 {
15477 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
15478 }
15479 r
15480}
15481
15482#[no_mangle]
15483pub unsafe extern "C" fn log1p(x: f64) -> f64 {
15484 if x == -1.0 {
15485 feraiseexcept(FE_DIVBYZERO);
15486 return f64::NEG_INFINITY;
15487 }
15488 libm::log1p(x)
15489}
15490
15491#[no_mangle]
15492pub unsafe extern "C" fn acosh(x: f64) -> f64 {
15493 if x < 1.0 {
15494 feraiseexcept(FE_INVALID);
15495 return f64::NAN;
15496 }
15497 libm::acosh(x)
15498}
15499
15500#[no_mangle]
15501pub unsafe extern "C" fn asinh(x: f64) -> f64 {
15502 if x == 0.0 { return x; }
15503 libm::asinh(x)
15504}
15505
15506#[no_mangle]
15507pub unsafe extern "C" fn atanh(x: f64) -> f64 {
15508 if x == 0.0 { return x; }
15509 let e = ((x.to_bits() >> 52) & 0x7ff) as i32;
15510 if e < 0x3ff - 32 {
15511 feraiseexcept(FE_INEXACT);
15512 if e == 0 { feraiseexcept(FE_UNDERFLOW); }
15513 return x;
15514 }
15515 if x == 1.0 {
15516 feraiseexcept(FE_DIVBYZERO);
15517 return f64::INFINITY;
15518 }
15519 if x == -1.0 {
15520 feraiseexcept(FE_DIVBYZERO);
15521 return f64::NEG_INFINITY;
15522 }
15523 if x.is_nan() { return x; }
15524 let ax = libm::fabs(x);
15525 if ax > 1.0 {
15526 feraiseexcept(FE_INVALID);
15527 return f64::NAN;
15528 }
15529 if ax < 0.5 {
15530 let r = libm::log1p(2.0 * (ax + ax * ax / (1.0 - ax))) / 2.0;
15532 if x < 0.0 { -r } else { r }
15533 } else {
15534 let r = 0.5 * libm::log((1.0 + ax) / (1.0 - ax));
15536 if x < 0.0 { -r } else { r }
15537 }
15538}
15539
15540#[no_mangle]
15541pub unsafe extern "C" fn cbrt(x: f64) -> f64 {
15542 libm::cbrt(x)
15543}
15544
15545#[no_mangle]
15546pub unsafe extern "C" fn erf(x: f64) -> f64 {
15547 libm::erf(x)
15548}
15549
15550#[no_mangle]
15551pub unsafe extern "C" fn erfc(x: f64) -> f64 {
15552 libm::erfc(x)
15553}
15554
15555#[no_mangle]
15556pub unsafe extern "C" fn lgamma(x: f64) -> f64 {
15557 if x.is_nan() {
15558 crate::signgam = 1;
15559 return x;
15560 }
15561 if x == 0.0 {
15562 crate::signgam = if x.is_sign_negative() { -1 } else { 1 };
15563 feraiseexcept(FE_DIVBYZERO);
15564 return f64::INFINITY;
15565 }
15566 let (r, sign) = libm::lgamma_r(x);
15567 crate::signgam = sign;
15568 r
15569}
15570
15571#[no_mangle]
15572pub unsafe extern "C" fn tgamma(x: f64) -> f64 {
15573 if x.is_nan() { return x; }
15574 if x == 0.0 {
15575 feraiseexcept(FE_DIVBYZERO);
15576 return if x.is_sign_negative() { f64::NEG_INFINITY } else { f64::INFINITY };
15577 }
15578 if x.is_infinite() {
15579 return if x.is_sign_negative() { __math_invalid(x) } else { f64::INFINITY };
15580 }
15581 if x < 0.0 && x == libm::floor(x) {
15582 feraiseexcept(FE_INVALID);
15583 return f64::NAN;
15584 }
15585 libm::tgamma(x)
15586}
15587
15588#[no_mangle]
15589pub unsafe extern "C" fn lround(x: f64) -> core::ffi::c_long {
15590 libm::round(x) as core::ffi::c_long
15591}
15592
15593#[no_mangle]
15594pub unsafe extern "C" fn llround(x: f64) -> i64 {
15595 libm::round(x) as i64
15596}
15597
15598#[no_mangle]
15605pub unsafe extern "C" fn cabs(z: (f64, f64)) -> f64 {
15606 libm::sqrt(z.0 * z.0 + z.1 * z.1)
15607}
15608
15609#[no_mangle]
15610pub unsafe extern "C" fn cabsf(z: (f32, f32)) -> f32 {
15611 libm::sqrtf(z.0 * z.0 + z.1 * z.1)
15612}
15613
15614#[no_mangle]
15615pub unsafe extern "C" fn cabsl(z: (f64, f64)) -> f64 {
15616 cabs(z)
15617}
15618
15619#[no_mangle]
15620pub unsafe extern "C" fn carg(z: (f64, f64)) -> f64 {
15621 libm::atan2(z.1, z.0)
15622}
15623
15624#[no_mangle]
15625pub unsafe extern "C" fn cargf(z: (f32, f32)) -> f32 {
15626 libm::atan2f(z.1, z.0)
15627}
15628
15629#[no_mangle]
15630pub unsafe extern "C" fn cargl(z: (f64, f64)) -> f64 {
15631 carg(z)
15632}
15633
15634#[no_mangle]
15635pub unsafe extern "C" fn cimag(z: (f64, f64)) -> f64 {
15636 z.1
15637}
15638
15639#[no_mangle]
15640pub unsafe extern "C" fn cimagf(z: (f32, f32)) -> f32 {
15641 z.1
15642}
15643
15644#[no_mangle]
15645pub unsafe extern "C" fn cimagl(z: (f64, f64)) -> f64 {
15646 z.1
15647}
15648
15649#[no_mangle]
15650pub unsafe extern "C" fn creal(z: (f64, f64)) -> f64 {
15651 z.0
15652}
15653
15654#[no_mangle]
15655pub unsafe extern "C" fn crealf(z: (f32, f32)) -> f32 {
15656 z.0
15657}
15658
15659#[no_mangle]
15660pub unsafe extern "C" fn creall(z: (f64, f64)) -> f64 {
15661 z.0
15662}
15663
15664#[no_mangle]
15665pub unsafe extern "C" fn conj(z: (f64, f64)) -> (f64, f64) {
15666 (z.0, -z.1)
15667}
15668
15669#[no_mangle]
15670pub unsafe extern "C" fn conjf(z: (f32, f32)) -> (f32, f32) {
15671 (z.0, -z.1)
15672}
15673
15674#[no_mangle]
15675pub unsafe extern "C" fn conjl(z: (f64, f64)) -> (f64, f64) {
15676 conj(z)
15677}
15678
15679#[no_mangle]
15680pub unsafe extern "C" fn cproj(z: (f64, f64)) -> (f64, f64) {
15681 if z.0.is_infinite() || z.1.is_infinite() {
15682 (f64::INFINITY, if z.1.is_sign_positive() { 0.0 } else { -0.0 })
15683 } else {
15684 z
15685 }
15686}
15687
15688#[no_mangle]
15689pub unsafe extern "C" fn cprojf(z: (f32, f32)) -> (f32, f32) {
15690 if z.0.is_infinite() || z.1.is_infinite() {
15691 (f32::INFINITY, if z.1.is_sign_positive() { 0.0 } else { -0.0 })
15692 } else {
15693 z
15694 }
15695}
15696
15697#[no_mangle]
15698pub unsafe extern "C" fn cprojl(z: (f64, f64)) -> (f64, f64) {
15699 cproj(z)
15700}
15701
15702#[no_mangle]
15704pub unsafe extern "C" fn cexp(z: (f64, f64)) -> (f64, f64) {
15705 let r = libm::exp(z.0);
15706 (r * libm::cos(z.1), r * libm::sin(z.1))
15707}
15708
15709#[no_mangle]
15710pub unsafe extern "C" fn cexpf(z: (f32, f32)) -> (f32, f32) {
15711 let r = libm::expf(z.0);
15712 (r * libm::cosf(z.1), r * libm::sinf(z.1))
15713}
15714
15715#[no_mangle]
15716pub unsafe extern "C" fn cexpl(z: (f64, f64)) -> (f64, f64) {
15717 cexp(z)
15718}
15719
15720#[no_mangle]
15722pub unsafe extern "C" fn clog(z: (f64, f64)) -> (f64, f64) {
15723 (libm::log(cabs(z)), carg(z))
15724}
15725
15726#[no_mangle]
15727pub unsafe extern "C" fn clogf(z: (f32, f32)) -> (f32, f32) {
15728 (libm::logf(cabsf(z)), cargf(z))
15729}
15730
15731#[no_mangle]
15732pub unsafe extern "C" fn clogl(z: (f64, f64)) -> (f64, f64) {
15733 clog(z)
15734}
15735
15736#[no_mangle]
15738pub unsafe extern "C" fn csqrt(z: (f64, f64)) -> (f64, f64) {
15739 let r = cabs(z);
15740 let sign = if z.1 < 0.0 { -1.0 } else { 1.0 };
15741 (libm::sqrt((r + z.0) / 2.0), sign * libm::sqrt((r - z.0) / 2.0))
15742}
15743
15744#[no_mangle]
15745pub unsafe extern "C" fn csqrtf(z: (f32, f32)) -> (f32, f32) {
15746 let r = cabsf(z);
15747 let sign = if z.1 < 0.0 { -1.0f32 } else { 1.0f32 };
15748 (libm::sqrtf((r + z.0) / 2.0), sign * libm::sqrtf((r - z.0) / 2.0))
15749}
15750
15751#[no_mangle]
15752pub unsafe extern "C" fn csqrtl(z: (f64, f64)) -> (f64, f64) {
15753 csqrt(z)
15754}
15755
15756#[no_mangle]
15758pub unsafe extern "C" fn cpow(z: (f64, f64), w: (f64, f64)) -> (f64, f64) {
15759 let log_z = clog(z);
15760 let exp_arg = (w.0 * log_z.0 - w.1 * log_z.1, w.0 * log_z.1 + w.1 * log_z.0);
15761 cexp(exp_arg)
15762}
15763
15764#[no_mangle]
15765pub unsafe extern "C" fn cpowf(z: (f32, f32), w: (f32, f32)) -> (f32, f32) {
15766 let log_z = clogf(z);
15767 let exp_arg = (w.0 * log_z.0 - w.1 * log_z.1, w.0 * log_z.1 + w.1 * log_z.0);
15768 cexpf(exp_arg)
15769}
15770
15771#[no_mangle]
15772pub unsafe extern "C" fn cpowl(z: (f64, f64), w: (f64, f64)) -> (f64, f64) {
15773 cpow(z, w)
15774}
15775
15776#[no_mangle]
15778pub unsafe extern "C" fn ccos(z: (f64, f64)) -> (f64, f64) {
15779 (libm::cos(z.0) * libm::cosh(z.1), -libm::sin(z.0) * libm::sinh(z.1))
15780}
15781
15782#[no_mangle]
15783pub unsafe extern "C" fn ccosf(z: (f32, f32)) -> (f32, f32) {
15784 (libm::cosf(z.0) * libm::coshf(z.1), -libm::sinf(z.0) * libm::sinhf(z.1))
15785}
15786
15787#[no_mangle]
15788pub unsafe extern "C" fn ccosl(z: (f64, f64)) -> (f64, f64) {
15789 ccos(z)
15790}
15791
15792#[no_mangle]
15794pub unsafe extern "C" fn csin(z: (f64, f64)) -> (f64, f64) {
15795 (libm::sin(z.0) * libm::cosh(z.1), libm::cos(z.0) * libm::sinh(z.1))
15796}
15797
15798#[no_mangle]
15799pub unsafe extern "C" fn csinf(z: (f32, f32)) -> (f32, f32) {
15800 (libm::sinf(z.0) * libm::coshf(z.1), libm::cosf(z.0) * libm::sinhf(z.1))
15801}
15802
15803#[no_mangle]
15804pub unsafe extern "C" fn csinl(z: (f64, f64)) -> (f64, f64) {
15805 csin(z)
15806}
15807
15808#[no_mangle]
15810pub unsafe extern "C" fn ctan(z: (f64, f64)) -> (f64, f64) {
15811 let d = libm::cos(2.0 * z.0) + libm::cosh(2.0 * z.1);
15812 (libm::sin(2.0 * z.0) / d, libm::sinh(2.0 * z.1) / d)
15813}
15814
15815#[no_mangle]
15816pub unsafe extern "C" fn ctanf(z: (f32, f32)) -> (f32, f32) {
15817 let d = libm::cosf(2.0 * z.0) + libm::coshf(2.0 * z.1);
15818 (libm::sinf(2.0 * z.0) / d, libm::sinhf(2.0 * z.1) / d)
15819}
15820
15821#[no_mangle]
15822pub unsafe extern "C" fn ctanl(z: (f64, f64)) -> (f64, f64) {
15823 ctan(z)
15824}
15825
15826#[no_mangle]
15828pub unsafe extern "C" fn ccosh(z: (f64, f64)) -> (f64, f64) {
15829 (libm::cosh(z.0) * libm::cos(z.1), libm::sinh(z.0) * libm::sin(z.1))
15830}
15831
15832#[no_mangle]
15833pub unsafe extern "C" fn ccoshf(z: (f32, f32)) -> (f32, f32) {
15834 (libm::coshf(z.0) * libm::cosf(z.1), libm::sinhf(z.0) * libm::sinf(z.1))
15835}
15836
15837#[no_mangle]
15838pub unsafe extern "C" fn ccoshl(z: (f64, f64)) -> (f64, f64) {
15839 ccosh(z)
15840}
15841
15842#[no_mangle]
15844pub unsafe extern "C" fn csinh(z: (f64, f64)) -> (f64, f64) {
15845 (libm::sinh(z.0) * libm::cos(z.1), libm::cosh(z.0) * libm::sin(z.1))
15846}
15847
15848#[no_mangle]
15849pub unsafe extern "C" fn csinhf(z: (f32, f32)) -> (f32, f32) {
15850 (libm::sinhf(z.0) * libm::cosf(z.1), libm::coshf(z.0) * libm::sinf(z.1))
15851}
15852
15853#[no_mangle]
15854pub unsafe extern "C" fn csinhl(z: (f64, f64)) -> (f64, f64) {
15855 csinh(z)
15856}
15857
15858#[no_mangle]
15860pub unsafe extern "C" fn ctanh(z: (f64, f64)) -> (f64, f64) {
15861 let d = libm::cosh(2.0 * z.0) + libm::cos(2.0 * z.1);
15862 (libm::sinh(2.0 * z.0) / d, libm::sin(2.0 * z.1) / d)
15863}
15864
15865#[no_mangle]
15866pub unsafe extern "C" fn ctanhf(z: (f32, f32)) -> (f32, f32) {
15867 let d = libm::coshf(2.0 * z.0) + libm::cosf(2.0 * z.1);
15868 (libm::sinhf(2.0 * z.0) / d, libm::sinf(2.0 * z.1) / d)
15869}
15870
15871#[no_mangle]
15872pub unsafe extern "C" fn ctanhl(z: (f64, f64)) -> (f64, f64) {
15873 ctanh(z)
15874}
15875
15876#[no_mangle]
15879pub unsafe extern "C" fn cacos(z: (f64, f64)) -> (f64, f64) {
15880 let asin_z = casin(z);
15881 (3.14159265358979323846264338327950288419716939937510582097494459230781640 / 2.0 - asin_z.0, -asin_z.1)
15882}
15883
15884#[no_mangle]
15885pub unsafe extern "C" fn cacosf(z: (f32, f32)) -> (f32, f32) {
15886 let asin_z = casinf(z);
15887 (3.14159265358979323846264338327950288419716939937510582097494459230781640f32 / 2.0 - asin_z.0, -asin_z.1)
15888}
15889
15890#[no_mangle]
15891pub unsafe extern "C" fn cacosl(z: (f64, f64)) -> (f64, f64) {
15892 cacos(z)
15893}
15894
15895#[no_mangle]
15897pub unsafe extern "C" fn casin(z: (f64, f64)) -> (f64, f64) {
15898 let iz = (-z.1, z.0);
15900 let one_minus_z2 = (1.0 - z.0 * z.0 + z.1 * z.1, -2.0 * z.0 * z.1);
15902 let sqrt_val = csqrt(one_minus_z2);
15903 let arg = clog((iz.0 + sqrt_val.0, iz.1 + sqrt_val.1));
15904 (arg.1, -arg.0)
15906}
15907
15908#[no_mangle]
15909pub unsafe extern "C" fn casinf(z: (f32, f32)) -> (f32, f32) {
15910 let iz = (-z.1, z.0);
15911 let one_minus_z2 = (1.0 - z.0 * z.0 + z.1 * z.1, -2.0 * z.0 * z.1);
15912 let sqrt_val = csqrtf(one_minus_z2);
15913 let arg = clogf((iz.0 + sqrt_val.0, iz.1 + sqrt_val.1));
15914 (arg.1, -arg.0)
15915}
15916
15917#[no_mangle]
15918pub unsafe extern "C" fn casinl(z: (f64, f64)) -> (f64, f64) {
15919 casin(z)
15920}
15921
15922#[no_mangle]
15924pub unsafe extern "C" fn catan(z: (f64, f64)) -> (f64, f64) {
15925 let num = (1.0 + z.1, -z.0);
15929 let den = (1.0 - z.1, z.0);
15930 let ratio = cdiv(num, den);
15931 let log_ratio = clog(ratio);
15932 (-log_ratio.1 / 2.0, log_ratio.0 / 2.0)
15934}
15935
15936#[no_mangle]
15937pub unsafe extern "C" fn catanf(z: (f32, f32)) -> (f32, f32) {
15938 let num = (1.0 + z.1, -z.0);
15939 let den = (1.0 - z.1, z.0);
15940 let ratio = cdivf(num, den);
15941 let log_ratio = clogf(ratio);
15942 (-log_ratio.1 / 2.0, log_ratio.0 / 2.0)
15943}
15944
15945#[no_mangle]
15946pub unsafe extern "C" fn catanl(z: (f64, f64)) -> (f64, f64) {
15947 catan(z)
15948}
15949
15950fn cdiv(a: (f64, f64), b: (f64, f64)) -> (f64, f64) {
15952 let d = b.0 * b.0 + b.1 * b.1;
15953 ((a.0 * b.0 + a.1 * b.1) / d, (a.1 * b.0 - a.0 * b.1) / d)
15954}
15955
15956fn cdivf(a: (f32, f32), b: (f32, f32)) -> (f32, f32) {
15957 let d = b.0 * b.0 + b.1 * b.1;
15958 ((a.0 * b.0 + a.1 * b.1) / d, (a.1 * b.0 - a.0 * b.1) / d)
15959}
15960
15961#[no_mangle]
15963pub unsafe extern "C" fn cacosh(z: (f64, f64)) -> (f64, f64) {
15964 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
15965 let z2_minus_1 = (z2.0 - 1.0, z2.1);
15966 let sqrt_val = csqrt(z2_minus_1);
15967 clog((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
15968}
15969
15970#[no_mangle]
15971pub unsafe extern "C" fn cacoshf(z: (f32, f32)) -> (f32, f32) {
15972 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
15973 let z2_minus_1 = (z2.0 - 1.0, z2.1);
15974 let sqrt_val = csqrtf(z2_minus_1);
15975 clogf((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
15976}
15977
15978#[no_mangle]
15979pub unsafe extern "C" fn cacoshl(z: (f64, f64)) -> (f64, f64) {
15980 cacosh(z)
15981}
15982
15983#[no_mangle]
15985pub unsafe extern "C" fn casinh(z: (f64, f64)) -> (f64, f64) {
15986 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
15987 let z2_plus_1 = (z2.0 + 1.0, z2.1);
15988 let sqrt_val = csqrt(z2_plus_1);
15989 clog((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
15990}
15991
15992#[no_mangle]
15993pub unsafe extern "C" fn casinhf(z: (f32, f32)) -> (f32, f32) {
15994 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
15995 let z2_plus_1 = (z2.0 + 1.0, z2.1);
15996 let sqrt_val = csqrtf(z2_plus_1);
15997 clogf((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
15998}
15999
16000#[no_mangle]
16001pub unsafe extern "C" fn casinhl(z: (f64, f64)) -> (f64, f64) {
16002 casinh(z)
16003}
16004
16005#[no_mangle]
16007pub unsafe extern "C" fn catanh(z: (f64, f64)) -> (f64, f64) {
16008 let num = (1.0 + z.0, z.1);
16009 let den = (1.0 - z.0, -z.1);
16010 let ratio = cdiv(num, den);
16011 let log_ratio = clog(ratio);
16012 (log_ratio.0 / 2.0, log_ratio.1 / 2.0)
16013}
16014
16015#[no_mangle]
16016pub unsafe extern "C" fn catanhf(z: (f32, f32)) -> (f32, f32) {
16017 let num = (1.0 + z.0, z.1);
16018 let den = (1.0 - z.0, -z.1);
16019 let ratio = cdivf(num, den);
16020 let log_ratio = clogf(ratio);
16021 (log_ratio.0 / 2.0, log_ratio.1 / 2.0)
16022}
16023
16024#[no_mangle]
16025pub unsafe extern "C" fn catanhl(z: (f64, f64)) -> (f64, f64) {
16026 catanh(z)
16027}
16028
16029#[inline(never)]
16034#[no_mangle]
16035pub unsafe extern "C" fn fmaxf(x: f32, y: f32) -> f32 {
16036 fmaxf_impl(x, y)
16037}
16038
16039#[no_mangle]
16040pub unsafe extern "C" fn fdimf(x: f32, y: f32) -> f32 {
16041 if x.is_nan() || y.is_nan() {
16042 return f32::NAN;
16043 }
16044 if x > y { x - y } else { 0.0 }
16045}
16046
16047#[no_mangle]
16048pub unsafe extern "C" fn fmaf(x: f32, y: f32, z: f32) -> f32 {
16049 if (x.is_infinite() && y == 0.0) || (y.is_infinite() && x == 0.0) {
16050 feraiseexcept(FE_INVALID);
16051 return f32::NAN;
16052 }
16053 if x.is_nan() || y.is_nan() || z.is_nan() {
16054 return f32::NAN;
16055 }
16056 let r = libm::fmaf(x, y, z);
16057 if r.is_nan() {
16058 feraiseexcept(FE_INVALID);
16059 }
16060 r
16061}
16062
16063#[no_mangle]
16064pub unsafe extern "C" fn ilogbf(x: f32) -> i32 {
16065 if x.is_nan() {
16066 feraiseexcept(FE_INVALID);
16067 return -0x7fffffff - 1;
16068 }
16069 if x == 0.0 || x.is_infinite() {
16070 feraiseexcept(FE_INVALID);
16071 return if x == 0.0 { -0x7fffffff - 1 } else { 0x7fffffff };
16072 }
16073 let bits = x.to_bits();
16074 let exp = ((bits >> 23) & 0xff) as i32;
16075 if exp == 0 {
16076 let mut v = bits & 0x7fffff;
16077 let mut e = -126;
16078 while v < (1u32 << 23) { v <<= 1; e -= 1; }
16079 e
16080 } else {
16081 exp - 127
16082 }
16083}
16084
16085#[no_mangle]
16086pub unsafe extern "C" fn logbf(x: f32) -> f32 {
16087 if x.is_nan() { return x; }
16088 if x == 0.0 { return __math_divzerof(1); }
16089 let bits = x.to_bits();
16090 let exp = ((bits >> 23) & 0xff) as i32;
16091 if exp == 0 {
16092 let mut v = bits & 0x7fffff;
16093 let mut e = -126i32;
16094 while v < (1u32 << 23) { v <<= 1; e -= 1; }
16095 e as f32
16096 } else if exp == 0xff {
16097 x * x
16098 } else {
16099 (exp - 127) as f32
16100 }
16101}
16102
16103#[no_mangle]
16104pub unsafe extern "C" fn nearbyintf(x: f32) -> f32 {
16105 let had_inexact = fetestexcept(FE_INEXACT) & FE_INEXACT != 0;
16106 let r = libm::rintf(x);
16107 if !had_inexact {
16108 feclearexcept(FE_INEXACT);
16109 }
16110 r
16111}
16112
16113#[no_mangle]
16114pub unsafe extern "C" fn nextafterf(x: f32, y: f32) -> f32 {
16115 if x.is_nan() || y.is_nan() { return x + y; }
16116 if x == 0.0 && y == 0.0 { return y; }
16117 if x == y { return x; }
16118 let r = libm::nextafterf(x, y);
16119 if r.is_infinite() && x.is_finite() {
16120 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16121 } else if r != x {
16122 let bits = r.to_bits();
16123 let is_subnormal = (bits & 0x7f800000) == 0 && (bits & 0x7fffff) != 0;
16124 if r == 0.0 || is_subnormal {
16125 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16126 }
16127 }
16128 r
16129}
16130
16131#[no_mangle]
16132#[cfg(target_arch = "x86_64")]
16133pub unsafe extern "C" fn nexttowardf(x: f32, y: f64) -> f32 {
16134 if y.is_nan() { return (x as f64 + y) as f32; }
16135 if x == 0.0 && y == 0.0 {
16136 return if y.is_sign_negative() { -0.0 } else { 0.0 };
16137 }
16138 if (x as f64) == y { return x; }
16139 nextafterf(x, if y > x as f64 { f32::INFINITY } else { f32::NEG_INFINITY })
16140}
16141
16142#[no_mangle]
16143#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
16144pub unsafe extern "C" fn nexttowardf(x: f32, y: f128) -> f32 {
16145 if y.is_nan() { return (x as f128 + y) as f32; }
16146 if (x as f128) == y { return x; }
16147 nextafterf(x, if y > x as f128 { f32::INFINITY } else { f32::NEG_INFINITY })
16148}
16149
16150#[no_mangle]
16151pub unsafe extern "C" fn remainderf(x: f32, y: f32) -> f32 {
16152 if x.is_nan() || y.is_nan() { return x + y; }
16153 if y == 0.0 || x.is_infinite() { return __math_invalidf(x); }
16154 libm::remainderf(x, y)
16155}
16156
16157#[no_mangle]
16158pub unsafe extern "C" fn remquof(x: f32, y: f32, quo: *mut i32) -> f32 {
16159 if x.is_nan() || y.is_nan() {
16160 if !quo.is_null() { *quo = 0; }
16161 return x + y;
16162 }
16163 if y == 0.0 || x.is_infinite() {
16164 if !quo.is_null() { *quo = 0; }
16165 return __math_invalidf(x);
16166 }
16167 let (r, q) = libm::remquof(x, y);
16168 if !quo.is_null() { *quo = q; }
16169 r
16170}
16171
16172#[no_mangle]
16173pub unsafe extern "C" fn exp2f(x: f32) -> f32 {
16174 if x == f32::INFINITY { return f32::INFINITY; }
16175 if x == f32::NEG_INFINITY { return 0.0; }
16176 if x.is_nan() { return f32::NAN; }
16177 let r = libm::exp2f(x);
16178 if r.is_infinite() && x.is_finite() {
16179 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16180 } else if r == 0.0 && x < -149.0 {
16181 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16182 } else if r != 0.0 && x != libm::truncf(x) {
16183 let bits = r.to_bits();
16184 if (bits & 0x7f800000) == 0 {
16185 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16186 }
16187 }
16188 r
16189}
16190
16191#[no_mangle]
16192pub unsafe extern "C" fn expm1f(x: f32) -> f32 {
16193 libm::expm1f(x)
16194}
16195
16196#[no_mangle]
16197pub unsafe extern "C" fn log1pf(x: f32) -> f32 {
16198 if x == -1.0 {
16199 feraiseexcept(FE_DIVBYZERO);
16200 return f32::NEG_INFINITY;
16201 }
16202 libm::log1pf(x)
16203}
16204
16205#[no_mangle]
16206pub unsafe extern "C" fn acoshf(x: f32) -> f32 {
16207 if x < 1.0 {
16208 feraiseexcept(FE_INVALID);
16209 return f32::NAN;
16210 }
16211 libm::acoshf(x)
16212}
16213
16214#[no_mangle]
16215pub unsafe extern "C" fn asinhf(x: f32) -> f32 {
16216 if x == 0.0 { return x; }
16217 libm::asinhf(x)
16218}
16219
16220#[no_mangle]
16221pub unsafe extern "C" fn atanhf(x: f32) -> f32 {
16222 if x == 0.0 { return x; }
16223 let e = ((x.to_bits() >> 23) & 0xff) as i32;
16224 if e < 0x7f - 32 {
16225 feraiseexcept(FE_INEXACT);
16226 if e == 0 { feraiseexcept(FE_UNDERFLOW); }
16227 return x;
16228 }
16229 if x == 1.0 {
16230 feraiseexcept(FE_DIVBYZERO);
16231 return f32::INFINITY;
16232 }
16233 if x == -1.0 {
16234 feraiseexcept(FE_DIVBYZERO);
16235 return f32::NEG_INFINITY;
16236 }
16237 if x.is_nan() { return x; }
16238 let ax = libm::fabsf(x);
16239 if ax > 1.0 {
16240 feraiseexcept(FE_INVALID);
16241 return f32::NAN;
16242 }
16243 if ax < 0.5 {
16244 let r = libm::log1pf(2.0 * (ax + ax * ax / (1.0 - ax))) / 2.0;
16245 if x < 0.0 { -r } else { r }
16246 } else {
16247 let r = 0.5 * libm::logf((1.0 + ax) / (1.0 - ax));
16248 if x < 0.0 { -r } else { r }
16249 }
16250}
16251
16252#[no_mangle]
16253pub unsafe extern "C" fn cbrtf(x: f32) -> f32 {
16254 libm::cbrtf(x)
16255}
16256
16257#[no_mangle]
16258pub unsafe extern "C" fn erff(x: f32) -> f32 {
16259 libm::erff(x)
16260}
16261
16262#[no_mangle]
16263pub unsafe extern "C" fn erfcf(x: f32) -> f32 {
16264 libm::erfcf(x)
16265}
16266
16267#[no_mangle]
16268pub unsafe extern "C" fn lgammaf(x: f32) -> f32 {
16269 if x.is_nan() {
16270 crate::signgam = 1;
16271 return x;
16272 }
16273 if x == 0.0 {
16274 crate::signgam = if x.is_sign_negative() { -1 } else { 1 };
16275 feraiseexcept(FE_DIVBYZERO);
16276 return f32::INFINITY;
16277 }
16278 let (r, sign) = libm::lgammaf_r(x);
16279 crate::signgam = sign;
16280 r
16281}
16282
16283#[no_mangle]
16284pub unsafe extern "C" fn tgammaf(x: f32) -> f32 {
16285 if x.is_nan() { return x; }
16286 if x == 0.0 {
16287 feraiseexcept(FE_DIVBYZERO);
16288 return if x.is_sign_negative() { f32::NEG_INFINITY } else { f32::INFINITY };
16289 }
16290 if x.is_infinite() {
16291 return if x.is_sign_negative() { __math_invalidf(x) } else { f32::INFINITY };
16292 }
16293 if x < 0.0 && x == libm::floorf(x) {
16294 feraiseexcept(FE_INVALID);
16295 return f32::NAN;
16296 }
16297 libm::tgammaf(x)
16298}
16299
16300#[no_mangle]
16301pub unsafe extern "C" fn lroundf(x: f32) -> core::ffi::c_long {
16302 libm::roundf(x) as core::ffi::c_long
16303}
16304
16305#[no_mangle]
16306pub unsafe extern "C" fn llroundf(x: f32) -> i64 {
16307 libm::roundf(x) as i64
16308}
16309
16310#[no_mangle]
16315pub unsafe extern "C" fn wcscasecmp(s1: *const u32, s2: *const u32) -> i32 {
16316 let mut i = 0;
16317 loop {
16318 let c1 = *s1.add(i);
16319 let c2 = *s2.add(i);
16320 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16321 let l1 = if c1 >= 'A' as u32 && c1 <= 'Z' as u32 { c1 + 32 } else { c1 };
16322 let l2 = if c2 >= 'A' as u32 && c2 <= 'Z' as u32 { c2 + 32 } else { c2 };
16323 if l1 != l2 { return (l1 as i32) - (l2 as i32); }
16324 i += 1;
16325 }
16326}
16327
16328#[no_mangle]
16329pub unsafe extern "C" fn wcscasecmp_l(s1: *const u32, s2: *const u32, _loc: *mut core::ffi::c_void) -> i32 {
16330 wcscasecmp(s1, s2)
16331}
16332
16333#[no_mangle]
16334pub unsafe extern "C" fn wcsncasecmp(s1: *const u32, s2: *const u32, n: usize) -> i32 {
16335 let mut i = 0;
16336 while i < n {
16337 let c1 = *s1.add(i);
16338 let c2 = *s2.add(i);
16339 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16340 let l1 = if c1 >= 'A' as u32 && c1 <= 'Z' as u32 { c1 + 32 } else { c1 };
16341 let l2 = if c2 >= 'A' as u32 && c2 <= 'Z' as u32 { c2 + 32 } else { c2 };
16342 if l1 != l2 { return (l1 as i32) - (l2 as i32); }
16343 i += 1;
16344 }
16345 0
16346}
16347
16348#[no_mangle]
16349pub unsafe extern "C" fn wcsncasecmp_l(s1: *const u32, s2: *const u32, n: usize, _loc: *mut core::ffi::c_void) -> i32 {
16350 wcsncasecmp(s1, s2, n)
16351}
16352
16353#[no_mangle]
16354pub unsafe extern "C" fn wcscoll(s1: *const u32, s2: *const u32) -> i32 {
16355 let mut i = 0;
16357 loop {
16358 let c1 = *s1.add(i);
16359 let c2 = *s2.add(i);
16360 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16361 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
16362 i += 1;
16363 }
16364}
16365
16366#[no_mangle]
16367pub unsafe extern "C" fn wcstok(s: *mut u32, sep: *const u32, p: *mut *mut u32) -> *mut u32 {
16368 let mut src = if s.is_null() { *p } else { s };
16369 while *src != 0 && *sep.add(0) == *src { src = src.add(1); }
16371 if *src == 0 { return core::ptr::null_mut(); }
16372 let start = src;
16373 while *src != 0 && *sep.add(0) != *src { src = src.add(1); }
16375 if *src != 0 {
16376 *src = 0;
16377 *p = src.add(1);
16378 } else {
16379 *p = src;
16380 }
16381 start
16382}
16383
16384#[no_mangle]
16385pub unsafe extern "C" fn wcswcs(haystack: *const u32, needle: *const u32) -> *mut u32 {
16386 if *needle == 0 { return haystack as *mut u32; }
16387 let mut i = 0;
16388 while *haystack.add(i) != 0 {
16389 let mut j = 0;
16390 while *needle.add(j) != 0 && *haystack.add(i + j) == *needle.add(j) {
16391 j += 1;
16392 }
16393 if *needle.add(j) == 0 { return haystack.add(i) as *mut u32; }
16394 i += 1;
16395 }
16396 core::ptr::null_mut()
16397}
16398
16399#[no_mangle]
16400pub unsafe extern "C" fn wcswidth(s: *const u32, n: usize) -> i32 {
16401 let mut width = 0i32;
16402 let mut i = 0;
16403 while i < n {
16404 let c = *s.add(i);
16405 if c == 0 { break; }
16406 width += 1;
16408 i += 1;
16409 }
16410 width
16411}
16412
16413#[no_mangle]
16414pub unsafe extern "C" fn wcsftime(s: *mut u32, maxsize: usize, fmt: *const u32, tm: *const c_void) -> usize {
16415 if s.is_null() || fmt.is_null() || maxsize == 0 { return 0; }
16416 let mut cfmt = [0u8; 1024];
16419 let mut o = 0usize;
16420 let mut i = 0usize;
16421 let mut st: c_uint = 0;
16422 while *fmt.add(i) != 0 && o + 8 < cfmt.len() {
16423 let n = wcrtomb(
16424 cfmt.as_mut_ptr().add(o) as *mut c_char,
16425 *fmt.add(i) as c_int,
16426 &mut st as *mut c_uint,
16427 );
16428 if n == !0usize { return 0; }
16429 o += n;
16430 i += 1;
16431 }
16432 cfmt[o] = 0;
16433 let mut out = [0u8; 4096];
16434 let mut lim = maxsize.saturating_mul(4);
16435 if lim > out.len() { lim = out.len(); }
16436 let n = strftime(out.as_mut_ptr() as *mut c_char, lim, cfmt.as_ptr() as *const c_char, tm as *const tm);
16437 if n == 0 { return 0; }
16438 let mut ws = 0usize;
16439 let mut p = 0usize;
16440 while p < n && ws + 1 < maxsize {
16441 let mut wc: c_int = 0;
16442 let mut st2: c_uint = 0;
16443 let r = mbrtowc(&mut wc, out.as_ptr().add(p) as *const c_char, n - p, &mut st2);
16444 if r == !0usize { return 0; }
16445 if r == 0 || r == !1usize { break; }
16446 *s.add(ws) = wc as u32;
16447 ws += 1;
16448 p += r;
16449 }
16450 *s.add(ws) = 0;
16451 ws
16452}
16453
16454#[no_mangle]
16455pub unsafe extern "C" fn mbsnrtowcs(
16456 dst: *mut u32,
16457 src: *mut *const u8,
16458 nms: usize,
16459 len: usize,
16460 st: *mut core::ffi::c_void,
16461) -> usize {
16462 if src.is_null() { return 0; }
16463 let mut s = *src;
16464 if s.is_null() { return 0; }
16465 let state = st as *mut c_uint;
16466 let limit = if dst.is_null() { usize::MAX } else { len };
16467 let mut count = 0usize;
16468 let mut n = nms;
16469 while count < limit && n > 0 {
16470 let c = *s;
16471 if c == 0 {
16472 if !dst.is_null() {
16473 if count < len { *dst.add(count) = 0; }
16474 *src = core::ptr::null();
16475 }
16476 return count;
16477 }
16478 let mut wc: c_int = 0;
16479 let r = mbrtowc(&mut wc, s as *const c_char, n, state);
16480 if r == !0usize {
16481 *src = s;
16482 return !0usize;
16483 }
16484 if r == !1usize { break; }
16485 if !dst.is_null() { *dst.add(count) = wc as u32; }
16486 count += 1;
16487 s = s.add(r);
16488 n -= r;
16489 }
16490 *src = s;
16491 count
16492}
16493
16494#[no_mangle]
16495pub unsafe extern "C" fn wcsnrtombs(dst: *mut u8, src: *mut *const u32, nwc: usize, len: usize, _st: *mut core::ffi::c_void) -> usize {
16496 let mut count = 0;
16497 let mut s = *src;
16498 let mut d = dst;
16499 while count < len && count < nwc {
16500 let c = *s;
16501 if c == 0 { break; }
16502 if !d.is_null() {
16503 if c < 0x80 {
16504 *d = c as u8;
16505 d = d.add(1);
16506 count += 1;
16507 } else if c < 0x800 {
16508 if count + 2 > len { break; }
16509 *d = 0xc0 | (c >> 6) as u8;
16510 *d.add(1) = 0x80 | (c & 0x3f) as u8;
16511 d = d.add(2);
16512 count += 2;
16513 } else if c < 0x10000 {
16514 if count + 3 > len { break; }
16515 *d = 0xe0 | (c >> 12) as u8;
16516 *d.add(1) = 0x80 | ((c >> 6) & 0x3f) as u8;
16517 *d.add(2) = 0x80 | (c & 0x3f) as u8;
16518 d = d.add(3);
16519 count += 3;
16520 } else {
16521 if count + 4 > len { break; }
16522 *d = 0xf0 | (c >> 18) as u8;
16523 *d.add(1) = 0x80 | ((c >> 12) & 0x3f) as u8;
16524 *d.add(2) = 0x80 | ((c >> 6) & 0x3f) as u8;
16525 *d.add(3) = 0x80 | (c & 0x3f) as u8;
16526 d = d.add(4);
16527 count += 4;
16528 }
16529 }
16530 s = s.add(1);
16531 }
16532 if !dst.is_null() { *src = s; }
16533 count
16534}
16535
16536pub type thrd_start_t = Option<unsafe extern "C" fn(arg: *mut core::ffi::c_void) -> i32>;
16543
16544#[no_mangle]
16546pub unsafe extern "C" fn thrd_create(thr: *mut usize, func: thrd_start_t, arg: *mut core::ffi::c_void) -> i32 {
16547 let mut thread: u64 = 0;
16548 let r = pthread_create(&mut thread, core::ptr::null(), core::mem::transmute(func), arg);
16549 if r == 0 {
16550 *thr = thread as usize;
16551 0 } else {
16553 -1 }
16555}
16556
16557#[no_mangle]
16558pub unsafe extern "C" fn thrd_join(thr: usize, res: *mut i32) -> i32 {
16559 let mut retval: *mut core::ffi::c_void = core::ptr::null_mut();
16560 let r = pthread_join(thr as u64, &mut retval);
16561 if r == 0 {
16562 if !res.is_null() { *res = retval as i32; }
16563 0
16564 } else {
16565 -1
16566 }
16567}
16568
16569#[no_mangle]
16570pub unsafe extern "C" fn thrd_exit(res: i32) {
16571 pthread_exit(res as *mut core::ffi::c_void);
16572}
16573
16574#[no_mangle]
16575pub unsafe extern "C" fn thrd_detach(thr: usize) -> i32 {
16576 let r = pthread_detach(thr as u64);
16577 if r == 0 { 0 } else { -1 }
16578}
16579
16580#[no_mangle]
16581pub unsafe extern "C" fn thrd_current() -> usize {
16582 pthread_self() as usize
16583}
16584
16585#[no_mangle]
16586pub unsafe extern "C" fn thrd_equal(thr1: usize, thr2: usize) -> i32 {
16587 (thr1 == thr2) as i32
16588}
16589
16590#[no_mangle]
16591pub unsafe extern "C" fn thrd_sleep(duration: *const core::ffi::c_void, remaining: *mut core::ffi::c_void) -> i32 {
16592 nanosleep(duration as *const timespec, remaining as *mut timespec)
16593}
16594
16595#[no_mangle]
16596pub unsafe extern "C" fn thrd_yield() {
16597 sched_yield();
16598}
16599
16600#[no_mangle]
16602pub unsafe extern "C" fn mtx_init(mtx: *mut usize, _mtx_type: i32) -> i32 {
16603 let r = pthread_mutex_init(mtx as *mut pthread_mutex_t, core::ptr::null());
16604 if r == 0 { 0 } else { -1 }
16605}
16606
16607#[no_mangle]
16608pub unsafe extern "C" fn mtx_lock(mtx: *mut usize) -> i32 {
16609 let r = pthread_mutex_lock(mtx as *mut pthread_mutex_t);
16610 if r == 0 { 0 } else { -1 }
16611}
16612
16613#[no_mangle]
16614pub unsafe extern "C" fn mtx_trylock(mtx: *mut usize) -> i32 {
16615 let r = pthread_mutex_trylock(mtx as *mut pthread_mutex_t);
16616 if r == 0 { 0 } else { -1 }
16617}
16618
16619#[no_mangle]
16620pub unsafe extern "C" fn mtx_unlock(mtx: *mut usize) -> i32 {
16621 let r = pthread_mutex_unlock(mtx as *mut pthread_mutex_t);
16622 if r == 0 { 0 } else { -1 }
16623}
16624
16625#[no_mangle]
16626pub unsafe extern "C" fn mtx_destroy(mtx: *mut usize) {
16627 pthread_mutex_destroy(mtx as *mut pthread_mutex_t);
16628}
16629
16630#[no_mangle]
16631pub unsafe extern "C" fn mtx_timedlock(mtx: *mut usize, ts: *const core::ffi::c_void) -> i32 {
16632 let r = pthread_mutex_timedlock(mtx as *mut pthread_mutex_t, ts as *const timespec);
16633 if r == 0 { 0 } else { -1 }
16634}
16635
16636#[no_mangle]
16638pub unsafe extern "C" fn cnd_init(cnd: *mut usize) -> i32 {
16639 let r = pthread_cond_init(cnd as *mut pthread_cond_t, core::ptr::null());
16640 if r == 0 { 0 } else { -1 }
16641}
16642
16643#[no_mangle]
16644pub unsafe extern "C" fn cnd_signal(cnd: *mut usize) -> i32 {
16645 let r = pthread_cond_signal(cnd as *mut pthread_cond_t);
16646 if r == 0 { 0 } else { -1 }
16647}
16648
16649#[no_mangle]
16650pub unsafe extern "C" fn cnd_broadcast(cnd: *mut usize) -> i32 {
16651 let r = pthread_cond_broadcast(cnd as *mut pthread_cond_t);
16652 if r == 0 { 0 } else { -1 }
16653}
16654
16655#[no_mangle]
16656pub unsafe extern "C" fn cnd_wait(cnd: *mut usize, mtx: *mut usize) -> i32 {
16657 let r = pthread_cond_wait(cnd as *mut pthread_cond_t, mtx as *mut pthread_mutex_t);
16658 if r == 0 { 0 } else { -1 }
16659}
16660
16661#[no_mangle]
16662pub unsafe extern "C" fn cnd_timedwait(cnd: *mut usize, mtx: *mut usize, ts: *const core::ffi::c_void) -> i32 {
16663 let r = pthread_cond_timedwait(cnd as *mut pthread_cond_t, mtx as *mut pthread_mutex_t, ts as *const timespec);
16664 if r == 0 { 0 } else { -1 }
16665}
16666
16667#[no_mangle]
16668pub unsafe extern "C" fn cnd_destroy(cnd: *mut usize) {
16669 pthread_cond_destroy(cnd as *mut pthread_cond_t);
16670}
16671
16672#[no_mangle]
16674pub unsafe extern "C" fn tss_create(key: *mut u32, dtor: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>) -> i32 {
16675 let r = pthread_key_create(key, dtor);
16676 if r == 0 { 0 } else { -1 }
16677}
16678
16679#[no_mangle]
16680pub unsafe extern "C" fn tss_delete(key: u32) {
16681 pthread_key_delete(key);
16682}
16683
16684#[no_mangle]
16685pub unsafe extern "C" fn tss_set(key: u32, val: *mut core::ffi::c_void) -> i32 {
16686 let r = pthread_setspecific(key, val);
16687 if r == 0 { 0 } else { -1 }
16688}
16689
16690#[no_mangle]
16691pub unsafe extern "C" fn tss_get(key: u32) -> *mut core::ffi::c_void {
16692 pthread_getspecific(key)
16693}
16694
16695#[no_mangle]
16697pub unsafe extern "C" fn call_once(flag: *mut u32, func: Option<unsafe extern "C" fn()>) {
16698 if *flag == 0 {
16699 if let Some(f) = func { f(); }
16700 *flag = 1;
16701 }
16702}
16703
16704#[no_mangle]
16710pub unsafe extern "C" fn accept4(fd: i32, addr: *mut core::ffi::c_void, addrlen: *mut u32, flags: i32) -> i32 {
16711 <Arch as Syscalls>::syscall4(SYS_ACCEPT4, fd as i64, addr as i64, addrlen as i64, flags as i64) as i32
16712}
16713
16714#[no_mangle]
16720pub unsafe extern "C" fn epoll_create(size: i32) -> i32 {
16721 #[cfg(target_arch = "x86_64")]
16722 { <Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE, size as i64) as i32 }
16723 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
16724 {
16725 if size < 1 {
16726 ERRNO = EINVAL;
16727 return -1;
16728 }
16729 <Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE1, 0) as i32
16730 }
16731}
16732
16733#[no_mangle]
16734pub unsafe extern "C" fn epoll_create1(flags: i32) -> i32 {
16735 <Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE1, flags as i64) as i32
16736}
16737
16738#[no_mangle]
16739pub unsafe extern "C" fn epoll_ctl(epfd: i32, op: i32, fd: i32, event: *mut core::ffi::c_void) -> i32 {
16740 <Arch as Syscalls>::syscall4(SYS_EPOLL_CTL, epfd as i64, op as i64, fd as i64, event as i64) as i32
16741}
16742
16743#[no_mangle]
16744pub unsafe extern "C" fn epoll_wait(epfd: i32, events: *mut core::ffi::c_void, maxevents: i32, timeout: i32) -> i32 {
16745 <Arch as Syscalls>::syscall4(SYS_EPOLL_WAIT, epfd as i64, events as i64, maxevents as i64, timeout as i64) as i32
16746}
16747
16748#[no_mangle]
16749pub unsafe extern "C" fn epoll_pwait(epfd: i32, events: *mut core::ffi::c_void, maxevents: i32, timeout: i32, sigmask: *const u64) -> i32 {
16750 <Arch as Syscalls>::syscall6(SYS_EPOLL_WAIT, epfd as i64, events as i64, maxevents as i64, timeout as i64, sigmask as i64, 8) as i32
16751}
16752
16753#[no_mangle]
16754pub unsafe extern "C" fn eventfd(initval: u32, flags: i32) -> i32 {
16755 <Arch as Syscalls>::syscall2(SYS_EVENTFD2, initval as i64, flags as i64) as i32
16756}
16757
16758#[no_mangle]
16759pub unsafe extern "C" fn eventfd_read(fd: i32, value: *mut u64) -> i32 {
16760 let n = crate::read(fd, value as *mut core::ffi::c_void, 8);
16761 if n == 8 { 0 } else { -1 }
16762}
16763
16764#[no_mangle]
16765pub unsafe extern "C" fn eventfd_write(fd: i32, value: u64) -> i32 {
16766 let n = crate::write(fd, &value as *const u64 as *const core::ffi::c_void, 8);
16767 if n == 8 { 0 } else { -1 }
16768}
16769
16770#[no_mangle]
16771pub unsafe extern "C" fn signalfd(fd: i32, mask: *const u64, flags: i32) -> i32 {
16772 <Arch as Syscalls>::syscall4(SYS_SIGNALFD4, fd as i64, mask as i64, 8, flags as i64) as i32
16773}
16774
16775#[no_mangle]
16776pub unsafe extern "C" fn timerfd_create(clockid: i32, flags: i32) -> i32 {
16777 <Arch as Syscalls>::syscall2(SYS_TIMERFD_CREATE, clockid as i64, flags as i64) as i32
16778}
16779
16780#[no_mangle]
16781pub 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 {
16782 <Arch as Syscalls>::syscall4(SYS_TIMERFD_SETTIME, fd as i64, flags as i64, new_value as i64, old_value as i64) as i32
16783}
16784
16785#[no_mangle]
16786pub unsafe extern "C" fn timerfd_gettime(fd: i32, curr_value: *mut core::ffi::c_void) -> i32 {
16787 <Arch as Syscalls>::syscall2(SYS_TIMERFD_GETTIME, fd as i64, curr_value as i64) as i32
16788}
16789
16790#[no_mangle]
16795pub unsafe extern "C" fn prctl(option: i32, mut args: ...) -> i32 {
16796 let a1 = args.next_arg::<i64>();
16797 let a2 = args.next_arg::<i64>();
16798 let a3 = args.next_arg::<i64>();
16799 let a4 = args.next_arg::<i64>();
16800 <Arch as Syscalls>::syscall5(SYS_PRCTL, option as i64, a1, a2, a3, a4) as i32
16801}
16802
16803#[no_mangle]
16804pub unsafe extern "C" fn quotactl(cmd: i32, special: *const core::ffi::c_char, id: i32, addr: *mut core::ffi::c_char) -> i32 {
16805 <Arch as Syscalls>::syscall4(sysno(179, 60), cmd as i64, special as i64, id as i64, addr as i64) as i32
16806}
16807
16808#[no_mangle]
16809pub unsafe extern "C" fn klogctl(type_: i32, bufp: *mut core::ffi::c_char, len: i32) -> i32 {
16810 <Arch as Syscalls>::syscall3(sysno(103, 116), type_ as i64, bufp as i64, len as i64) as i32
16811}
16812
16813static mut SYSLOG_IDENT: [core::ffi::c_char; 64] = [0; 64];
16814static mut SYSLOG_OPTIONS: i32 = 0;
16815static mut SYSLOG_FACILITY: i32 = 1;
16816
16817#[no_mangle]
16818pub unsafe extern "C" fn openlog(ident: *const core::ffi::c_char, option: i32, facility: i32) {
16819 SYSLOG_OPTIONS = option;
16820 SYSLOG_FACILITY = facility & 0x3f8;
16821 SYSLOG_IDENT[0] = 0;
16822 if !ident.is_null() {
16823 let mut i = 0;
16824 while i < 63 && *ident.add(i) != 0 {
16825 SYSLOG_IDENT[i] = *ident.add(i);
16826 i += 1;
16827 }
16828 SYSLOG_IDENT[i] = 0;
16829 }
16830}
16831
16832#[repr(C)]
16833struct SockAddrUn {
16834 sun_family: u16,
16835 sun_path: [core::ffi::c_char; 108],
16836}
16837
16838unsafe fn syslog_emit(priority: i32, msg: *const core::ffi::c_char, len: usize) {
16839 let mut out = [0u8; 1200];
16840 let mut o = 0usize;
16841 let pri = (SYSLOG_FACILITY | (priority & 7)) as u32;
16842 out[o] = b'<'; o += 1;
16843 if pri >= 100 { out[o] = b'0' + (pri / 100) as u8; o += 1; }
16844 if pri >= 10 { out[o] = b'0' + ((pri / 10) % 10) as u8; o += 1; }
16845 out[o] = b'0' + (pri % 10) as u8; o += 1;
16846 out[o] = b'>'; o += 1;
16847 let mut i = 0;
16848 while i < 63 && SYSLOG_IDENT[i] != 0 && o + 1 < out.len() {
16849 out[o] = SYSLOG_IDENT[i] as u8; o += 1; i += 1;
16850 }
16851 if SYSLOG_OPTIONS & 1 != 0 {
16852 out[o] = b'['; o += 1;
16853 let mut pid = crate::getpid() as u32;
16854 let mut digits = [0u8; 10];
16855 let mut d = 0;
16856 if pid == 0 { digits[0] = b'0'; d = 1; }
16857 while pid > 0 { digits[d] = b'0' + (pid % 10) as u8; pid /= 10; d += 1; }
16858 while d > 0 { d -= 1; out[o] = digits[d]; o += 1; }
16859 out[o] = b']'; o += 1;
16860 }
16861 out[o] = b':'; o += 1; out[o] = b' '; o += 1;
16862 let copy = core::cmp::min(len, out.len() - o - 1);
16863 core::ptr::copy_nonoverlapping(msg as *const u8, out.as_mut_ptr().add(o), copy);
16864 o += copy;
16865 let fd = crate::socket(AF_UNIX, SOCK_DGRAM, 0);
16866 if fd >= 0 {
16867 let mut sa: SockAddrUn = core::mem::zeroed();
16868 sa.sun_family = AF_UNIX as u16;
16869 let path = b"/dev/log";
16870 for i in 0..path.len() { sa.sun_path[i] = path[i] as core::ffi::c_char; }
16871 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);
16872 crate::close(fd);
16873 if r >= 0 { return; }
16874 }
16875 crate::write(2, out.as_ptr() as *const core::ffi::c_void, o);
16876 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
16877}
16878
16879#[no_mangle]
16880pub unsafe extern "C" fn vsyslog(priority: c_int, fmt: *const c_char, ap: VaList) {
16881 let mut msg = [0 as c_char; 1024];
16882 let n = vsnprintf(msg.as_mut_ptr(), msg.len(), fmt, ap);
16883 if n > 0 { syslog_emit(priority, msg.as_ptr(), core::cmp::min(n as usize, msg.len() - 1)); }
16884}
16885
16886#[no_mangle]
16887pub unsafe extern "C" fn syslog(priority: c_int, fmt: *const c_char, args: ...) {
16888 vsyslog(priority, fmt, args);
16889}
16890
16891#[no_mangle]
16892pub unsafe extern "C" fn closelog() {
16893 }
16895
16896#[no_mangle]
16897pub unsafe extern "C" fn setlogmask(mask: i32) -> i32 {
16898 static mut LOG_MASK: i32 = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80;
16899 let old = LOG_MASK;
16900 if mask != 0 { LOG_MASK = mask; }
16901 old
16902}
16903
16904#[no_mangle]
16905pub unsafe extern "C" fn acct(filename: *const core::ffi::c_char) -> i32 {
16906 <Arch as Syscalls>::syscall1(SYS_ACCT, filename as i64) as i32
16907}
16908
16909#[no_mangle]
16910pub unsafe extern "C" fn swapon(path: *const core::ffi::c_char, flags: i32) -> i32 {
16911 <Arch as Syscalls>::syscall2(SYS_SWAPON, path as i64, flags as i64) as i32
16912}
16913
16914#[no_mangle]
16915pub unsafe extern "C" fn swapoff(path: *const core::ffi::c_char) -> i32 {
16916 <Arch as Syscalls>::syscall1(SYS_SWAPOFF, path as i64) as i32
16917}
16918
16919#[no_mangle]
16920pub unsafe extern "C" fn syncfs(fd: i32) -> i32 {
16921 <Arch as Syscalls>::syscall1(SYS_SYNCFS, fd as i64) as i32
16922}
16923
16924#[no_mangle]
16925pub unsafe extern "C" fn sync_file_range(fd: i32, offset: i64, nbytes: u64, flags: u32) -> i32 {
16926 <Arch as Syscalls>::syscall4(sysno(277, 84), fd as i64, offset, nbytes as i64, flags as i64) as i32
16927}
16928
16929#[no_mangle]
16930pub unsafe extern "C" fn posix_fadvise(fd: i32, offset: i64, len: u64, advice: i32) -> i32 {
16931 <Arch as Syscalls>::syscall4(sysno(221, 223), fd as i64, offset, len as i64, advice as i64) as i32
16932}
16933
16934#[no_mangle]
16935pub unsafe extern "C" fn posix_fallocate(fd: i32, offset: i64, len: u64) -> i32 {
16936 <Arch as Syscalls>::syscall3(SYS_FALLOCATE, fd as i64, offset, len as i64) as i32
16937}
16938
16939#[no_mangle]
16940pub unsafe extern "C" fn readahead(fd: i32, offset: i64, count: usize) -> i32 {
16941 <Arch as Syscalls>::syscall3(sysno(187, 213), fd as i64, offset, count as i64) as i32
16942}
16943
16944#[no_mangle]
16945pub unsafe extern "C" fn fallocate(fd: i32, mode: i32, offset: i64, len: u64) -> i32 {
16946 <Arch as Syscalls>::syscall4(SYS_FALLOCATE, fd as i64, mode as i64, offset, len as i64) as i32
16947}
16948
16949#[no_mangle]
16954pub unsafe extern "C" fn tcgetattr(fd: i32, termios_p: *mut core::ffi::c_void) -> i32 {
16955 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5401, termios_p as i64) as i32
16956}
16957
16958#[no_mangle]
16959pub unsafe extern "C" fn tcsetattr(fd: i32, optional_actions: i32, termios_p: *const core::ffi::c_void) -> i32 {
16960 let cmd = match optional_actions {
16961 0 => 0x5402,
16962 1 => 0x5403,
16963 2 => 0x5404,
16964 _ => 0x5402,
16965 };
16966 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, cmd, termios_p as i64) as i32
16967}
16968
16969#[no_mangle]
16970pub unsafe extern "C" fn tcdrain(fd: i32) -> i32 {
16971 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5409, 1) as i32
16972}
16973
16974#[no_mangle]
16975pub unsafe extern "C" fn tcflush(fd: i32, queue_selector: i32) -> i32 {
16976 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540B, queue_selector as i64) as i32
16977}
16978
16979#[no_mangle]
16980pub unsafe extern "C" fn tcflow(fd: i32, action: i32) -> i32 {
16981 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540A, action as i64) as i32
16982}
16983
16984#[no_mangle]
16985pub unsafe extern "C" fn tcsendbreak(fd: i32, duration: i32) -> i32 {
16986 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5425, duration as i64) as i32
16987}
16988
16989#[no_mangle]
16990pub unsafe extern "C" fn tcgetsid(fd: i32) -> i32 {
16991 let mut sid: i32 = 0;
16992 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5429, &mut sid as *mut i32 as i64);
16993 if r < 0 { -1 } else { sid }
16994}
16995
16996#[no_mangle]
16997pub unsafe extern "C" fn tcgetpgrp(fd: i32) -> i32 {
16998 let mut pgrp: i32 = 0;
16999 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540F, &mut pgrp as *mut i32 as i64);
17000 if r < 0 { -1 } else { pgrp }
17001}
17002
17003#[no_mangle]
17004pub unsafe extern "C" fn tcsetpgrp(fd: i32, pgrp: i32) -> i32 {
17005 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5410, &pgrp as *const i32 as i64) as i32
17006}
17007
17008#[no_mangle]
17019pub unsafe extern "C" fn mq_open(name: *const core::ffi::c_char, oflag: i32, _args: ...) -> i64 {
17020 crate::open(name, oflag, 0) as i64
17021}
17022
17023#[no_mangle]
17024pub unsafe extern "C" fn mq_close(mqdes: i64) -> i32 {
17025 crate::close(mqdes as i32)
17026}
17027
17028#[no_mangle]
17029pub unsafe extern "C" fn mq_unlink(name: *const core::ffi::c_char) -> i32 {
17030 crate::unlink(name)
17031}
17032
17033#[no_mangle]
17034pub unsafe extern "C" fn mq_send(mqdes: i64, msg_ptr: *const core::ffi::c_char, msg_len: usize, _msg_prio: u32) -> i32 {
17035 let r = crate::write(mqdes as i32, msg_ptr as *const core::ffi::c_void, msg_len) as i32;
17036 if r >= 0 { mq_notify_fire(mqdes); }
17037 r
17038}
17039
17040#[no_mangle]
17041pub unsafe extern "C" fn mq_receive(mqdes: i64, msg_ptr: *mut core::ffi::c_char, msg_len: usize, _msg_prio: *mut u32) -> isize {
17042 crate::read(mqdes as i32, msg_ptr as *mut core::ffi::c_void, msg_len)
17043}
17044
17045#[no_mangle]
17046pub unsafe extern "C" fn mq_timedsend(mqdes: i64, msg_ptr: *const core::ffi::c_char, msg_len: usize, msg_prio: u32, _abs_timeout: *const core::ffi::c_void) -> i32 {
17047 mq_send(mqdes, msg_ptr, msg_len, msg_prio)
17048}
17049
17050#[no_mangle]
17051pub unsafe extern "C" fn mq_timedreceive(mqdes: i64, msg_ptr: *mut core::ffi::c_char, msg_len: usize, msg_prio: *mut u32, _abs_timeout: *const core::ffi::c_void) -> isize {
17052 mq_receive(mqdes, msg_ptr, msg_len, msg_prio)
17053}
17054
17055#[no_mangle]
17060pub unsafe extern "C" fn pthread_getaffinity_np(thread: usize, cpusetsize: usize, cpuset: *mut u8) -> i32 {
17061 sched_getaffinity(thread as i32, cpusetsize, cpuset)
17062}
17063
17064#[no_mangle]
17065pub unsafe extern "C" fn pthread_setaffinity_np(thread: usize, cpusetsize: usize, cpuset: *const u8) -> i32 {
17066 sched_setaffinity(thread as i32, cpusetsize, cpuset)
17067}
17068
17069#[no_mangle]
17074pub unsafe extern "C" fn sched_yield() -> i32 {
17075 <Arch as Syscalls>::syscall0(sysno(24, 124)) as i32
17076}
17077
17078#[no_mangle]
17079pub unsafe extern "C" fn sched_get_priority_max(policy: i32) -> i32 {
17080 <Arch as Syscalls>::syscall1(sysno(146, 125), policy as i64) as i32
17081}
17082
17083#[no_mangle]
17084pub unsafe extern "C" fn sched_get_priority_min(policy: i32) -> i32 {
17085 <Arch as Syscalls>::syscall1(sysno(147, 126), policy as i64) as i32
17086}
17087
17088#[no_mangle]
17089pub unsafe extern "C" fn sched_getparam(pid: i32, param: *mut core::ffi::c_void) -> i32 {
17090 <Arch as Syscalls>::syscall2(sysno(143, 121), pid as i64, param as i64) as i32
17091}
17092
17093#[no_mangle]
17094pub unsafe extern "C" fn sched_setparam(pid: i32, param: *const core::ffi::c_void) -> i32 {
17095 <Arch as Syscalls>::syscall2(sysno(142, 118), pid as i64, param as i64) as i32
17096}
17097
17098#[no_mangle]
17099pub unsafe extern "C" fn sched_getscheduler(pid: i32) -> i32 {
17100 <Arch as Syscalls>::syscall1(sysno(145, 120), pid as i64) as i32
17101}
17102
17103#[no_mangle]
17104pub unsafe extern "C" fn sched_setscheduler(pid: i32, policy: i32, param: *const core::ffi::c_void) -> i32 {
17105 <Arch as Syscalls>::syscall3(sysno(144, 119), pid as i64, policy as i64, param as i64) as i32
17106}
17107
17108#[no_mangle]
17109pub unsafe extern "C" fn sched_setaffinity(pid: i32, cpusetsize: usize, cpuset: *const u8) -> i32 {
17110 <Arch as Syscalls>::syscall3(sysno(203, 122), pid as i64, cpusetsize as i64, cpuset as i64) as i32
17111}
17112
17113#[no_mangle]
17114pub unsafe extern "C" fn sched_getaffinity(pid: i32, cpusetsize: usize, cpuset: *mut u8) -> i32 {
17115 <Arch as Syscalls>::syscall3(sysno(204, 123), pid as i64, cpusetsize as i64, cpuset as i64) as i32
17116}
17117
17118#[no_mangle]
17119pub unsafe extern "C" fn sched_getcpu() -> i32 {
17120 let mut cpu: i32 = 0;
17121 <Arch as Syscalls>::syscall3(sysno(309, 168), &mut cpu as *mut i32 as i64, 0, 0);
17122 cpu
17123}
17124
17125#[no_mangle]
17126pub unsafe extern "C" fn sched_rr_get_interval(pid: i32, tp: *mut core::ffi::c_void) -> i32 {
17127 <Arch as Syscalls>::syscall2(sysno(148, 127), pid as i64, tp as i64) as i32
17128}
17129
17130#[no_mangle]
17135pub unsafe extern "C" fn timer_create(clockid: i32, sevp: *mut core::ffi::c_void, timerid: *mut i32) -> i32 {
17136 <Arch as Syscalls>::syscall3(sysno(222, 107), clockid as i64, sevp as i64, timerid as i64) as i32
17137}
17138
17139#[no_mangle]
17140pub unsafe extern "C" fn timer_delete(timerid: i32) -> i32 {
17141 <Arch as Syscalls>::syscall1(sysno(226, 111), timerid as i64) as i32
17142}
17143
17144#[no_mangle]
17145pub 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 {
17146 <Arch as Syscalls>::syscall4(sysno(223, 110), timerid as i64, flags as i64, new_value as i64, old_value as i64) as i32
17147}
17148
17149#[no_mangle]
17150pub unsafe extern "C" fn timer_gettime(timerid: i32, curr_value: *mut core::ffi::c_void) -> i32 {
17151 <Arch as Syscalls>::syscall2(sysno(224, 108), timerid as i64, curr_value as i64) as i32
17152}
17153
17154#[no_mangle]
17155pub unsafe extern "C" fn timer_getoverrun(timerid: i32) -> i32 {
17156 <Arch as Syscalls>::syscall1(sysno(225, 109), timerid as i64) as i32
17157}
17158
17159#[no_mangle]
17160pub unsafe extern "C" fn clock_adjtime(_clockid: i32, buf: *mut core::ffi::c_void) -> i32 {
17161 <Arch as Syscalls>::syscall2(SYS_ADJTIMEX, buf as i64, 0) as i32
17162}
17163
17164#[no_mangle]
17165pub unsafe extern "C" fn clock_getcpuclockid(pid: i32, clockid: *mut i32) -> i32 {
17166 if clockid.is_null() { return EINVAL; }
17167 let id: i32 = ((-(pid as i64) - 1) * 8 + 2) as i32;
17168 let mut ts: timespec = core::mem::zeroed();
17169 let r = <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, id as i64, &mut ts as *mut timespec as i64);
17170 if r < 0 {
17171 let e = (-r) as c_int;
17172 return if e == EINVAL { 3 } else { e };
17173 }
17174 *clockid = id;
17175 0
17176}
17177
17178#[no_mangle]
17183pub unsafe extern "C" fn strcoll(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char) -> i32 {
17184 let mut i = 0;
17186 loop {
17187 let c1 = *s1.add(i) as u8;
17188 let c2 = *s2.add(i) as u8;
17189 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
17190 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
17191 i += 1;
17192 }
17193}
17194
17195#[no_mangle]
17196pub unsafe extern "C" fn strxfrm(dest: *mut core::ffi::c_char, src: *const core::ffi::c_char, n: usize) -> usize {
17197 let mut i = 0;
17198 while i < n {
17199 let c = *src.add(i);
17200 *dest.add(i) = c;
17201 if c == 0 { break; }
17202 i += 1;
17203 }
17204 i
17205}
17206
17207#[no_mangle]
17212pub 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 {
17213 let dir = opendir(dirp);
17214 if dir.is_null() { return -1; }
17215 let mut count = 0;
17216 loop {
17217 let ent = readdir(dir);
17218 if ent.is_null() { break; }
17219 count += 1;
17220 }
17221 closedir(dir);
17222 count
17223}
17224
17225#[no_mangle]
17226pub unsafe extern "C" fn alphasort(a: *const *const core::ffi::c_void, b: *const *const core::ffi::c_void) -> i32 {
17227 let s1 = *a as *const core::ffi::c_char;
17228 let s2 = *b as *const core::ffi::c_char;
17229 crate::strcmp(s1 as *const u8, s2 as *const u8)
17230}
17231
17232#[no_mangle]
17233pub unsafe extern "C" fn versionsort(a: *const *const core::ffi::c_void, b: *const *const core::ffi::c_void) -> i32 {
17234 let s1 = *a as *const core::ffi::c_char;
17235 let s2 = *b as *const core::ffi::c_char;
17236 crate::strcmp(s1 as *const u8, s2 as *const u8)
17237}
17238
17239unsafe fn vwarn_impl(fmt: *const c_char, ap: VaList, with_errno: bool) {
17247 let mut buf = [0 as c_char; 1024];
17248 let n = vsnprintf(buf.as_mut_ptr(), buf.len(), fmt, ap);
17249 if n > 0 {
17250 let l = core::cmp::min(n as usize, buf.len() - 1);
17251 crate::write(2, buf.as_ptr() as *const c_void, l);
17252 }
17253 if with_errno {
17254 let e = ERRNO;
17255 crate::write(2, b": ".as_ptr() as *const c_void, 2);
17256 let msg = strerror(e);
17257 crate::write(2, msg as *const c_void, crate::strlen(msg));
17258 }
17259 crate::write(2, b"\n".as_ptr() as *const c_void, 1);
17260}
17261
17262#[no_mangle]
17263pub unsafe extern "C" fn verr(eval: c_int, fmt: *const c_char, ap: VaList) {
17264 vwarn_impl(fmt, ap, true);
17265 crate::exit(eval);
17266}
17267
17268#[no_mangle]
17269pub unsafe extern "C" fn verrx(eval: c_int, fmt: *const c_char, ap: VaList) {
17270 vwarn_impl(fmt, ap, false);
17271 crate::exit(eval);
17272}
17273
17274#[no_mangle]
17275pub unsafe extern "C" fn vwarn(fmt: *const c_char, ap: VaList) {
17276 vwarn_impl(fmt, ap, true);
17277}
17278
17279#[no_mangle]
17280pub unsafe extern "C" fn vwarnx(fmt: *const c_char, ap: VaList) {
17281 vwarn_impl(fmt, ap, false);
17282}
17283
17284#[no_mangle]
17285pub unsafe extern "C" fn err(eval: c_int, fmt: *const c_char, args: ...) {
17286 verr(eval, fmt, args);
17287}
17288
17289#[no_mangle]
17290pub unsafe extern "C" fn errx(eval: c_int, fmt: *const c_char, args: ...) {
17291 verrx(eval, fmt, args);
17292}
17293
17294#[no_mangle]
17295pub unsafe extern "C" fn warn(fmt: *const c_char, args: ...) {
17296 vwarn(fmt, args);
17297}
17298
17299#[no_mangle]
17300pub unsafe extern "C" fn warnx(fmt: *const c_char, args: ...) {
17301 vwarnx(fmt, args);
17302}
17303
17304#[no_mangle]
17309pub unsafe extern "C" fn ecvt(value: f64, ndigit: i32, decpt: *mut i32, sign: *mut i32) -> *mut core::ffi::c_char {
17310 static mut BUF: [core::ffi::c_char; 80] = [0; 80];
17311 if value < 0.0 { *sign = 1; } else { *sign = 0; }
17312 let v = if value < 0.0 { -value } else { value };
17313 if v == 0.0 { *decpt = 0; BUF[0] = 0; return BUF.as_mut_ptr(); }
17314 let mut d = 0i32;
17315 let mut tmp = v;
17316 while tmp >= 10.0 { tmp /= 10.0; d += 1; }
17317 while tmp < 1.0 { tmp *= 10.0; d -= 1; }
17318 *decpt = d + 1;
17319 let mut i = 0;
17320 let mut val = tmp;
17321 while i < ndigit as usize && i < 79 {
17322 let digit = val as i32;
17323 BUF[i] = (b'0' + digit as u8) as c_char;
17324 val = (val - digit as f64) * 10.0;
17325 i += 1;
17326 }
17327 BUF[i] = 0;
17328 BUF.as_mut_ptr()
17329}
17330
17331#[no_mangle]
17332pub unsafe extern "C" fn fcvt(value: f64, ndigit: i32, decpt: *mut i32, sign: *mut i32) -> *mut core::ffi::c_char {
17333 static mut BUF: [core::ffi::c_char; 80] = [0; 80];
17334 if value < 0.0 { *sign = 1; } else { *sign = 0; }
17335 let v = if value < 0.0 { -value } else { value };
17336 if v == 0.0 { *decpt = 0; BUF[0] = 0; return BUF.as_mut_ptr(); }
17337 let mut d = 0i32;
17338 let mut tmp = v;
17339 while tmp >= 10.0 { tmp /= 10.0; d += 1; }
17340 while tmp < 1.0 { tmp *= 10.0; d -= 1; }
17341 *decpt = d + 1;
17342 let mut val = tmp;
17343 let mut i = 0;
17344 while i < (*decpt) as usize && i < 79 {
17345 let digit = val as i32;
17346 BUF[i] = (b'0' + digit as u8) as c_char;
17347 val = (val - digit as f64) * 10.0;
17348 i += 1;
17349 }
17350 if ndigit > 0 && i < 79 {
17351 BUF[i] = '.' as c_char;
17352 i += 1;
17353 let mut frac = val;
17354 let mut j = 0;
17355 while j < ndigit as usize && i < 79 {
17356 let digit = frac as i32;
17357 BUF[i] = (b'0' + digit as u8) as c_char;
17358 frac = (frac - digit as f64) * 10.0;
17359 i += 1;
17360 j += 1;
17361 }
17362 }
17363 BUF[i] = 0;
17364 BUF.as_mut_ptr()
17365}
17366
17367#[no_mangle]
17368pub unsafe extern "C" fn gcvt(value: f64, _ndigit: i32, buf: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
17369 if value == 0.0 {
17371 *buf = '0' as c_char;
17372 *buf.add(1) = 0;
17373 return buf;
17374 }
17375 let mut i = 0;
17376 let v = if value < 0.0 { *buf = '-' as c_char; i = 1; -value } else { value };
17377 let mut int_part = v as i64;
17379 let mut digits = [0u8; 32];
17380 let mut di = 0;
17381 if int_part == 0 {
17382 digits[0] = 0;
17383 di = 1;
17384 } else {
17385 while int_part > 0 && di < 32 {
17386 digits[di] = (int_part % 10) as u8;
17387 int_part /= 10;
17388 di += 1;
17389 }
17390 }
17391 while di > 0 && i < 79 {
17392 di -= 1;
17393 *buf.add(i) = (b'0' + digits[di]) as c_char;
17394 i += 1;
17395 }
17396 *buf.add(i) = 0;
17397 buf
17398}
17399
17400static mut SHELLS: [*const core::ffi::c_char; 3] = [
17405 b"/bin/sh\0".as_ptr() as *const core::ffi::c_char,
17406 b"/bin/bash\0".as_ptr() as *const core::ffi::c_char,
17407 core::ptr::null(),
17408];
17409static mut SHELL_IDX: usize = 0;
17410
17411#[no_mangle]
17412pub unsafe extern "C" fn getusershell() -> *mut core::ffi::c_char {
17413 let s = SHELLS[SHELL_IDX];
17414 if s.is_null() {
17415 SHELL_IDX = 0;
17416 return core::ptr::null_mut();
17417 }
17418 SHELL_IDX += 1;
17419 s as *mut core::ffi::c_char
17420}
17421
17422#[no_mangle]
17423pub unsafe extern "C" fn setusershell() {
17424 SHELL_IDX = 0;
17425}
17426
17427#[no_mangle]
17428pub unsafe extern "C" fn endusershell() {
17429 SHELL_IDX = 0;
17430}
17431
17432#[no_mangle]
17437pub unsafe extern "C" fn ether_aton(s: *const core::ffi::c_char) -> *mut u8 {
17438 static mut EA: [u8; 6] = [0; 6];
17439 if ether_aton_r(s, EA.as_mut_ptr()).is_null() { core::ptr::null_mut() } else { EA.as_mut_ptr() }
17440}
17441
17442#[no_mangle]
17443pub unsafe extern "C" fn ether_aton_r(s: *const core::ffi::c_char, ea: *mut u8) -> *mut u8 {
17444 if ea.is_null() { return core::ptr::null_mut(); }
17445 let mut i = 0;
17446 let mut j = 0;
17447 let mut val: u32 = 0;
17448 let mut digits = 0;
17449 while *s.add(i) != 0 && j < 6 {
17450 let c = *s.add(i);
17451 if c == ':' as c_char {
17452 if digits == 0 { return core::ptr::null_mut(); }
17453 *ea.add(j) = val as u8;
17454 j += 1;
17455 val = 0;
17456 digits = 0;
17457 } 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) {
17458 let d = if c >= '0' as c_char && c <= '9' as c_char { (c - '0' as c_char) as u32 }
17459 else if c >= 'a' as c_char { (c - 'a' as c_char + 10) as u32 }
17460 else { (c - 'A' as c_char + 10) as u32 };
17461 val = val * 16 + d;
17462 if val > 255 { return core::ptr::null_mut(); }
17463 digits += 1;
17464 if digits > 2 { return core::ptr::null_mut(); }
17465 } else {
17466 return core::ptr::null_mut();
17467 }
17468 i += 1;
17469 }
17470 if digits == 0 || j != 5 { return core::ptr::null_mut(); }
17471 *ea.add(j) = val as u8;
17472 ea
17473}
17474
17475#[no_mangle]
17476pub unsafe extern "C" fn ether_ntoa(ea: *const u8) -> *mut core::ffi::c_char {
17477 static mut BUF: [core::ffi::c_char; 18] = [0; 18];
17478 ether_ntoa_r(ea, BUF.as_mut_ptr());
17479 BUF.as_mut_ptr()
17480}
17481
17482#[no_mangle]
17483pub unsafe extern "C" fn ether_ntoa_r(ea: *const u8, buf: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
17484 let a = *ea.add(0); let b = *ea.add(1); let c = *ea.add(2);
17485 let d = *ea.add(3); let e = *ea.add(4); let f = *ea.add(5);
17486 let hex = b"0123456789abcdef\0".as_ptr() as *const u8;
17487 let mut i = 0;
17488 *buf.add(i) = *hex.add((a >> 4) as usize) as c_char; i += 1;
17489 *buf.add(i) = *hex.add((a & 0xf) as usize) as c_char; i += 1;
17490 *buf.add(i) = ':' as c_char; i += 1;
17491 *buf.add(i) = *hex.add((b >> 4) as usize) as c_char; i += 1;
17492 *buf.add(i) = *hex.add((b & 0xf) as usize) as c_char; i += 1;
17493 *buf.add(i) = ':' as c_char; i += 1;
17494 *buf.add(i) = *hex.add((c >> 4) as usize) as c_char; i += 1;
17495 *buf.add(i) = *hex.add((c & 0xf) as usize) as c_char; i += 1;
17496 *buf.add(i) = ':' as c_char; i += 1;
17497 *buf.add(i) = *hex.add((d >> 4) as usize) as c_char; i += 1;
17498 *buf.add(i) = *hex.add((d & 0xf) as usize) as c_char; i += 1;
17499 *buf.add(i) = ':' as c_char; i += 1;
17500 *buf.add(i) = *hex.add((e >> 4) as usize) as c_char; i += 1;
17501 *buf.add(i) = *hex.add((e & 0xf) as usize) as c_char; i += 1;
17502 *buf.add(i) = ':' as c_char; i += 1;
17503 *buf.add(i) = *hex.add((f >> 4) as usize) as c_char; i += 1;
17504 *buf.add(i) = *hex.add((f & 0xf) as usize) as c_char; i += 1;
17505 *buf.add(i) = 0;
17506 buf
17507}
17508
17509#[no_mangle]
17514pub unsafe extern "C" fn getutxent() -> *mut core::ffi::c_void {
17515 getutent()
17516}
17517
17518#[no_mangle]
17519pub unsafe extern "C" fn getutxid(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
17520 getutid(ut)
17521}
17522
17523#[no_mangle]
17524pub unsafe extern "C" fn getutxline(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
17525 getutline(ut)
17526}
17527
17528#[no_mangle]
17529pub unsafe extern "C" fn pututxline(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
17530 pututline(ut)
17531}
17532
17533#[no_mangle]
17534pub unsafe extern "C" fn setutxent() {
17535 setutent()
17536}
17537
17538#[no_mangle]
17539pub unsafe extern "C" fn endutxent() {
17540 endutent()
17541}
17542
17543#[no_mangle]
17548pub unsafe extern "C" fn execv(path: *const core::ffi::c_char, argv: *const *const core::ffi::c_char) -> i32 {
17549 crate::execve(path, argv, core::ptr::null())
17550}
17551
17552#[no_mangle]
17553pub unsafe extern "C" fn execlp(file: *const core::ffi::c_char, _args: ...) -> i32 {
17554 let mut argv: [*const core::ffi::c_char; 64] = [core::ptr::null(); 64];
17556 let mut i = 0;
17557 let mut args = _args;
17558 loop {
17559 let arg = args.next_arg::<*const core::ffi::c_char>();
17560 if arg.is_null() { break; }
17561 argv[i] = arg;
17562 i += 1;
17563 if i >= 63 { break; }
17564 }
17565 argv[i] = core::ptr::null();
17566 execvp(file, argv.as_ptr())
17567}
17568
17569#[no_mangle]
17570pub unsafe extern "C" fn execvp(file: *const core::ffi::c_char, argv: *const *const core::ffi::c_char) -> i32 {
17571 let path = crate::getenv(b"PATH\0".as_ptr() as *const core::ffi::c_char);
17573 if path.is_null() { return -1; }
17574 crate::execve(file, argv, core::ptr::null())
17576}
17577
17578#[no_mangle]
17579pub unsafe extern "C" fn fexecve(fd: i32, argv: *const *const core::ffi::c_char, envp: *const *const core::ffi::c_char) -> i32 {
17580 let mut path: [core::ffi::c_char; 64] = [0; 64];
17582 let mut i = 0;
17583 let src = b"/proc/self/fd/\0".as_ptr() as *const core::ffi::c_char;
17584 while i < 63 && *src.add(i) != 0 { path[i] = *src.add(i); i += 1; }
17585 let mut n = fd as usize;
17586 if n == 0 { path[i] = '0' as c_char; i += 1; }
17587 while n > 0 && i < 63 {
17588 path[i] = (b'0' + (n % 10) as u8) as c_char;
17589 n /= 10;
17590 i += 1;
17591 }
17592 path[i] = 0;
17593 crate::execve(path.as_ptr(), argv, envp)
17594}
17595
17596#[no_mangle]
17601pub unsafe extern "C" fn confstr(name: i32, buf: *mut core::ffi::c_char, len: usize) -> usize {
17602 match name {
17603 0 => { let s = b"/bin:/usr/bin\0".as_ptr() as *const core::ffi::c_char;
17605 let mut i = 0;
17606 while i < len - 1 && *s.add(i) != 0 { *buf.add(i) = *s.add(i); i += 1; }
17607 *buf.add(i) = 0;
17608 i + 1
17609 }
17610 1 => { let s = b"\0".as_ptr() as *const core::ffi::c_char;
17612 let mut i = 0;
17613 while i < len - 1 && *s.add(i) != 0 { *buf.add(i) = *s.add(i); i += 1; }
17614 *buf.add(i) = 0;
17615 i + 1
17616 }
17617 _ => 0,
17618 }
17619}
17620
17621#[no_mangle]
17622pub unsafe extern "C" fn pathconf(_path: *const core::ffi::c_char, name: i32) -> i64 {
17623 match name {
17625 0 => 4096, 1 => 255, 2 => 255, 3 => 255, 4 => 4096, 5 => 4096, 6 => 1, 7 => 0, 8 => 0, _ => -1,
17635 }
17636}
17637
17638#[no_mangle]
17639pub unsafe extern "C" fn fpathconf(_fd: i32, name: i32) -> i64 {
17640 match name {
17642 0 => 4096, 1 => 255, 2 => 255, 3 => 255, 4 => 4096, 5 => 4096, 6 => 1, 7 => 0, 8 => 0, _ => -1,
17652 }
17653}
17654
17655#[no_mangle]
17660pub unsafe extern "C" fn exp10(x: f64) -> f64 {
17661 libm::pow(10.0, x)
17662}
17663
17664#[no_mangle]
17665pub unsafe extern "C" fn exp10f(x: f32) -> f32 {
17666 libm::powf(10.0, x)
17667}
17668
17669#[no_mangle]
17674pub unsafe extern "C" fn explicit_bzero(s: *mut u8, n: usize) {
17675 core::ptr::write_bytes(s, 0, n);
17676 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
17677}
17678
17679#[no_mangle]
17680pub unsafe extern "C" fn memccpy(dest: *mut u8, src: *const u8, c: i32, n: usize) -> *mut u8 {
17681 let mut i = 0;
17682 while i < n {
17683 let byte = *src.add(i);
17684 *dest.add(i) = byte;
17685 if byte == c as u8 {
17686 return dest.add(i + 1);
17687 }
17688 i += 1;
17689 }
17690 core::ptr::null_mut()
17691}
17692
17693#[no_mangle]
17698pub unsafe extern "C" fn faccessat(dirfd: i32, pathname: *const core::ffi::c_char, mode: i32, flags: i32) -> i32 {
17699 <Arch as Syscalls>::syscall4(SYS_FACCESSAT, dirfd as i64, pathname as i64, mode as i64, flags as i64) as i32
17700}
17701
17702#[no_mangle]
17703pub unsafe extern "C" fn fchmodat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32, flags: i32) -> i32 {
17704 <Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, pathname as i64, mode as i64, flags as i64) as i32
17705}
17706
17707#[no_mangle]
17708pub unsafe extern "C" fn fchownat(dirfd: i32, pathname: *const core::ffi::c_char, uid: u32, gid: u32, flags: i32) -> i32 {
17709 <Arch as Syscalls>::syscall5(sysno(260, 54), dirfd as i64, pathname as i64, uid as i64, gid as i64, flags as i64) as i32
17710}
17711
17712#[no_mangle]
17713pub unsafe extern "C" fn linkat(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char, flags: i32) -> i32 {
17714 <Arch as Syscalls>::syscall5(SYS_LINKAT, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64) as i32
17715}
17716
17717#[no_mangle]
17718pub unsafe extern "C" fn mkdirat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32) -> i32 {
17719 <Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, pathname as i64, mode as i64) as i32
17720}
17721
17722#[no_mangle]
17723pub unsafe extern "C" fn mkfifoat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32) -> i32 {
17724 mknodat(dirfd, pathname, mode | 0o010000, 0)
17725}
17726
17727#[no_mangle]
17728pub unsafe extern "C" fn mknodat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32, dev: u64) -> i32 {
17729 <Arch as Syscalls>::syscall4(sysno(259, 33), dirfd as i64, pathname as i64, mode as i64, dev as i64) as i32
17730}
17731
17732#[no_mangle]
17733pub unsafe extern "C" fn readlinkat(dirfd: i32, pathname: *const core::ffi::c_char, buf: *mut core::ffi::c_char, bufsiz: usize) -> isize {
17734 <Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, pathname as i64, buf as i64, bufsiz as i64) as isize
17735}
17736
17737#[no_mangle]
17738pub unsafe extern "C" fn renameat(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char) -> i32 {
17739 <Arch as Syscalls>::syscall4(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64) as i32
17740}
17741
17742#[no_mangle]
17743pub unsafe extern "C" fn renameat2(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char, flags: u32) -> i32 {
17744 <Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64) as i32
17745}
17746
17747#[no_mangle]
17748pub unsafe extern "C" fn symlinkat(target: *const core::ffi::c_char, newdirfd: i32, linkpath: *const core::ffi::c_char) -> i32 {
17749 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64) as i32
17750}
17751
17752#[no_mangle]
17753pub unsafe extern "C" fn unlinkat(dirfd: i32, pathname: *const core::ffi::c_char, flags: i32) -> i32 {
17754 <Arch as Syscalls>::syscall3(SYS_UNLINKAT, dirfd as i64, pathname as i64, flags as i64) as i32
17755}
17756
17757#[no_mangle]
17758pub unsafe extern "C" fn utimes(filename: *const core::ffi::c_char, times: *const core::ffi::c_void) -> i32 {
17759 utimensat(AT_FDCWD, filename, times as *const timespec, 0)
17760}
17761
17762#[no_mangle]
17763pub unsafe extern "C" fn futimes(fd: i32, times: *const core::ffi::c_void) -> i32 {
17764 utimensat(fd, core::ptr::null(), times as *const timespec, 0)
17765}
17766
17767#[no_mangle]
17772pub unsafe extern "C" fn inotify_init() -> i32 {
17773 <Arch as Syscalls>::syscall1(sysno(253, 26), 0) as i32
17774}
17775
17776#[no_mangle]
17777pub unsafe extern "C" fn inotify_init1(flags: i32) -> i32 {
17778 <Arch as Syscalls>::syscall1(sysno(294, 26), flags as i64) as i32
17779}
17780
17781#[no_mangle]
17782pub unsafe extern "C" fn inotify_add_watch(fd: i32, pathname: *const core::ffi::c_char, mask: u32) -> i32 {
17783 <Arch as Syscalls>::syscall3(sysno(254, 27), fd as i64, pathname as i64, mask as i64) as i32
17784}
17785
17786#[no_mangle]
17787pub unsafe extern "C" fn inotify_rm_watch(fd: i32, wd: i32) -> i32 {
17788 <Arch as Syscalls>::syscall2(sysno(255, 28), fd as i64, wd as i64) as i32
17789}
17790
17791#[no_mangle]
17792pub unsafe extern "C" fn fanotify_init(flags: i32, event_f_flags: i32) -> i32 {
17793 <Arch as Syscalls>::syscall2(sysno(300, 262), flags as i64, event_f_flags as i64) as i32
17794}
17795
17796#[no_mangle]
17797pub unsafe extern "C" fn fanotify_mark(fd: i32, flags: i32, mask: u64, dirfd: i32, pathname: *const core::ffi::c_char) -> i32 {
17798 <Arch as Syscalls>::syscall5(sysno(301, 263), fd as i64, flags as i64, mask as i64, dirfd as i64, pathname as i64) as i32
17799}
17800
17801#[no_mangle]
17806pub unsafe extern "C" fn ffs(x: i32) -> i32 {
17807 if x == 0 { return 0; }
17808 x.trailing_zeros() as i32 + 1
17809}
17810
17811#[no_mangle]
17812pub unsafe extern "C" fn ffsl(x: i64) -> i32 {
17813 if x == 0 { return 0; }
17814 x.trailing_zeros() as i32 + 1
17815}
17816
17817#[no_mangle]
17818pub unsafe extern "C" fn ffsll(x: i64) -> i32 {
17819 if x == 0 { return 0; }
17820 x.trailing_zeros() as i32 + 1
17821}
17822
17823#[no_mangle]
17828pub unsafe extern "C" fn fchdir(fd: i32) -> i32 {
17829 <Arch as Syscalls>::syscall1(SYS_FCHDIR, fd as i64) as i32
17830}
17831
17832#[no_mangle]
17833pub unsafe extern "C" fn fchown(fd: i32, uid: u32, gid: u32) -> i32 {
17834 <Arch as Syscalls>::syscall3(SYS_FCHOWN, fd as i64, uid as i64, gid as i64) as i32
17835}
17836
17837#[no_mangle]
17838pub unsafe extern "C" fn fdopendir(fd: i32) -> *mut core::ffi::c_void {
17839 if fd < 0 { return core::ptr::null_mut(); }
17841 DIR_FD = fd;
17842 DIR_POS = 0;
17843 DIR_LEN = 0;
17844 &DIR_FD as *const i32 as *mut core::ffi::c_void
17845}
17846
17847#[no_mangle]
17848pub unsafe extern "C" fn getdtablesize() -> i32 {
17849 let mut rlim: Rlimit = core::mem::zeroed();
17850 if getrlimit(RLIMIT_NOFILE, &mut rlim) == 0 {
17851 rlim.rlim_cur as i32
17852 } else {
17853 1024
17854 }
17855}
17856
17857#[no_mangle]
17858pub unsafe extern "C" fn getentropy(buf: *mut u8, buflen: usize) -> i32 {
17859 getrandom(buf, buflen, 0) as i32
17860}
17861
17862#[no_mangle]
17863pub unsafe extern "C" fn getrandom(buf: *mut u8, buflen: usize, flags: u32) -> isize {
17864 <Arch as Syscalls>::syscall3(sysno(318, 278), buf as i64, buflen as i64, flags as i64) as isize
17865}
17866
17867#[no_mangle]
17868pub unsafe extern "C" fn killpg(pgrp: i32, sig: i32) -> i32 {
17869 <Arch as Syscalls>::syscall2(SYS_KILL, -pgrp as i64, sig as i64) as i32
17870}
17871
17872#[no_mangle]
17873pub unsafe extern "C" fn mkfifo(pathname: *const core::ffi::c_char, mode: u32) -> i32 {
17874 mknod(pathname, 0o010000 | mode, 0)
17875}
17876
17877#[no_mangle]
17882pub unsafe extern "C" fn aligned_alloc(alignment: usize, size: usize) -> *mut core::ffi::c_void {
17883 let p = crate::malloc(size + alignment);
17884 if p.is_null() { return core::ptr::null_mut(); }
17885 let aligned = ((p as usize + alignment - 1) & !(alignment - 1)) as *mut core::ffi::c_void;
17886 aligned
17887}
17888
17889#[no_mangle]
17890pub unsafe extern "C" fn memalign(alignment: usize, size: usize) -> *mut core::ffi::c_void {
17891 let p = crate::malloc(size + alignment);
17892 if p.is_null() { return core::ptr::null_mut(); }
17893 let aligned = ((p as usize + alignment - 1) & !(alignment - 1)) as *mut core::ffi::c_void;
17894 aligned
17895}
17896
17897#[no_mangle]
17898pub unsafe extern "C" fn posix_memalign(memptr: *mut *mut core::ffi::c_void, _alignment: usize, size: usize) -> i32 {
17899 let p = crate::malloc(size);
17900 if p.is_null() { return 12; } *memptr = p;
17902 0
17903}
17904
17905#[no_mangle]
17906pub unsafe extern "C" fn valloc(size: usize) -> *mut core::ffi::c_void {
17907 let p = crate::malloc(size + 4096);
17908 if p.is_null() { return core::ptr::null_mut(); }
17909 let aligned = ((p as usize + 4095) & !4095) as *mut core::ffi::c_void;
17910 aligned
17911}
17912
17913#[no_mangle]
17926pub unsafe extern "C" fn gettext(msgid: *const core::ffi::c_char) -> *const core::ffi::c_char {
17927 msgid
17928}
17929
17930#[no_mangle]
17931pub unsafe extern "C" fn dgettext(_domainname: *const core::ffi::c_char, msgid: *const core::ffi::c_char) -> *const core::ffi::c_char {
17932 msgid
17933}
17934
17935#[no_mangle]
17936pub unsafe extern "C" fn dcgettext(_domainname: *const core::ffi::c_char, msgid: *const core::ffi::c_char, _category: i32) -> *const core::ffi::c_char {
17937 msgid
17938}
17939
17940#[no_mangle]
17941pub unsafe extern "C" fn ngettext(msgid1: *const core::ffi::c_char, msgid2: *const core::ffi::c_char, n: u64) -> *const core::ffi::c_char {
17942 if n == 1 { msgid1 } else { msgid2 }
17943}
17944
17945#[no_mangle]
17946pub 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 {
17947 if n == 1 { msgid1 } else { msgid2 }
17948}
17949
17950#[no_mangle]
17951pub 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 {
17952 if n == 1 { msgid1 } else { msgid2 }
17953}
17954
17955#[no_mangle]
17956pub unsafe extern "C" fn textdomain(domainname: *const core::ffi::c_char) -> *mut core::ffi::c_char {
17957 static mut DOMAIN: [core::ffi::c_char; 256] = [0; 256];
17958 if domainname.is_null() { return DOMAIN.as_mut_ptr(); }
17959 let mut i = 0;
17960 while i < 255 && *domainname.add(i) != 0 {
17961 DOMAIN[i] = *domainname.add(i);
17962 i += 1;
17963 }
17964 DOMAIN[i] = 0;
17965 DOMAIN.as_mut_ptr()
17966}
17967
17968#[no_mangle]
17969pub unsafe extern "C" fn bindtextdomain(_domainname: *const core::ffi::c_char, dirname: *const core::ffi::c_char) -> *mut core::ffi::c_char {
17970 dirname as *mut core::ffi::c_char
17971}
17972
17973#[no_mangle]
17974pub unsafe extern "C" fn bind_textdomain_codeset(_domainname: *const core::ffi::c_char, codeset: *const core::ffi::c_char) -> *mut core::ffi::c_char {
17975 codeset as *mut core::ffi::c_char
17976}
17977
17978#[no_mangle]
17983pub unsafe extern "C" fn wmemcpy(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
17984 let mut i = 0;
17985 while i < n {
17986 *dest.add(i) = *src.add(i);
17987 i += 1;
17988 }
17989 dest
17990}
17991
17992#[no_mangle]
17993pub unsafe extern "C" fn wmemmove(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
17994 if dest as usize <= src as usize {
17995 let mut i = 0;
17996 while i < n {
17997 *dest.add(i) = *src.add(i);
17998 i += 1;
17999 }
18000 } else {
18001 let mut i = n;
18002 while i > 0 {
18003 i -= 1;
18004 *dest.add(i) = *src.add(i);
18005 }
18006 }
18007 dest
18008}
18009
18010#[no_mangle]
18011pub unsafe extern "C" fn wmemset(dest: *mut u32, c: u32, n: usize) -> *mut u32 {
18012 let mut i = 0;
18013 while i < n {
18014 *dest.add(i) = c;
18015 i += 1;
18016 }
18017 dest
18018}
18019
18020#[no_mangle]
18021pub unsafe extern "C" fn wmemcmp(s1: *const u32, s2: *const u32, n: usize) -> i32 {
18022 let mut i = 0;
18023 while i < n {
18024 let c1 = *s1.add(i);
18025 let c2 = *s2.add(i);
18026 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
18027 i += 1;
18028 }
18029 0
18030}
18031
18032#[no_mangle]
18033pub unsafe extern "C" fn wmemchr(s: *const u32, c: u32, n: usize) -> *mut u32 {
18034 let mut i = 0;
18035 while i < n {
18036 if *s.add(i) == c { return s.add(i) as *mut u32; }
18037 i += 1;
18038 }
18039 core::ptr::null_mut()
18040}
18041
18042#[no_mangle]
18043pub unsafe extern "C" fn wcpcpy(dest: *mut u32, src: *const u32) -> *mut u32 {
18044 let mut i = 0;
18045 loop {
18046 let c = *src.add(i);
18047 *dest.add(i) = c;
18048 if c == 0 { return dest.add(i); }
18049 i += 1;
18050 }
18051}
18052
18053#[no_mangle]
18054pub unsafe extern "C" fn wcpncpy(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18055 let mut i = 0;
18056 while i < n {
18057 let c = *src.add(i);
18058 *dest.add(i) = c;
18059 if c == 0 { return dest.add(i); }
18060 i += 1;
18061 }
18062 dest.add(n)
18063}
18064
18065#[no_mangle]
18066pub unsafe extern "C" fn wprintf(fmt: *const wchar_t, args: ...) -> c_int {
18067 vfwprintf(stdout, fmt, args)
18068}
18069
18070#[no_mangle]
18071pub unsafe extern "C" fn vwprintf(fmt: *const wchar_t, ap: core::ffi::VaList) -> c_int {
18072 vfwprintf(stdout, fmt, ap)
18073}
18074
18075#[no_mangle]
18080pub unsafe extern "C" fn c16rtomb(s: *mut u8, c16: u16, ps: *mut core::ffi::c_void) -> usize {
18081 let state = ps as *mut u32;
18083 let saved: u32 = if state.is_null() { 0 } else { *state };
18084 if s.is_null() {
18085 if !state.is_null() { *state = 0; }
18086 return 1;
18087 }
18088 let cp: u32;
18089 if saved != 0 {
18090 if c16 < 0xdc00 || c16 > 0xdfff {
18091 if !state.is_null() { *state = 0; }
18092 ERRNO = EILSEQ;
18093 return !0usize;
18094 }
18095 cp = 0x10000 + (((saved - 0xd800) << 10) | ((c16 as u32) - 0xdc00));
18096 if !state.is_null() { *state = 0; }
18097 } else if c16 >= 0xd800 && c16 <= 0xdbff {
18098 if !state.is_null() { *state = c16 as u32; }
18099 return 0;
18100 } else if c16 >= 0xdc00 && c16 <= 0xdfff {
18101 ERRNO = EILSEQ;
18102 return !0usize;
18103 } else {
18104 cp = c16 as u32;
18105 }
18106 if cp < 0x80 {
18107 *s = cp as u8;
18108 1
18109 } else if cp < 0x800 {
18110 *s = (0xc0 | (cp >> 6)) as u8;
18111 *s.add(1) = (0x80 | (cp & 0x3f)) as u8;
18112 2
18113 } else if cp < 0x10000 {
18114 *s = (0xe0 | (cp >> 12)) as u8;
18115 *s.add(1) = (0x80 | ((cp >> 6) & 0x3f)) as u8;
18116 *s.add(2) = (0x80 | (cp & 0x3f)) as u8;
18117 3
18118 } else {
18119 *s = (0xf0 | (cp >> 18)) as u8;
18120 *s.add(1) = (0x80 | ((cp >> 12) & 0x3f)) as u8;
18121 *s.add(2) = (0x80 | ((cp >> 6) & 0x3f)) as u8;
18122 *s.add(3) = (0x80 | (cp & 0x3f)) as u8;
18123 4
18124 }
18125}
18126
18127#[no_mangle]
18128pub unsafe extern "C" fn c32rtomb(s: *mut u8, c32: u32, _ps: *mut core::ffi::c_void) -> usize {
18129 if s.is_null() { return 1; }
18130 if c32 > 0x10ffff || (c32 >= 0xd800 && c32 <= 0xdfff) {
18131 ERRNO = EILSEQ;
18132 return !0usize;
18133 }
18134 if c32 < 0x80 {
18135 *s = c32 as u8;
18136 1
18137 } else if c32 < 0x800 {
18138 *s = (0xc0 | (c32 >> 6)) as u8;
18139 *s.add(1) = (0x80 | (c32 & 0x3f)) as u8;
18140 2
18141 } else if c32 < 0x10000 {
18142 *s = (0xe0 | (c32 >> 12)) as u8;
18143 *s.add(1) = (0x80 | ((c32 >> 6) & 0x3f)) as u8;
18144 *s.add(2) = (0x80 | (c32 & 0x3f)) as u8;
18145 3
18146 } else {
18147 *s = (0xf0 | (c32 >> 18)) as u8;
18148 *s.add(1) = (0x80 | ((c32 >> 12) & 0x3f)) as u8;
18149 *s.add(2) = (0x80 | ((c32 >> 6) & 0x3f)) as u8;
18150 *s.add(3) = (0x80 | (c32 & 0x3f)) as u8;
18151 4
18152 }
18153}
18154
18155#[no_mangle]
18156pub unsafe extern "C" fn mbrtoc16(pc16: *mut u16, s: *const u8, n: usize, _ps: *mut core::ffi::c_void) -> usize {
18157 if s.is_null() { return 0; }
18158 if n == 0 { return 1; }
18159 let c = *s;
18160 if c == 0 { return 0; }
18161 if c < 0x80 {
18162 if !pc16.is_null() { *pc16 = c as u16; }
18163 return 1;
18164 }
18165 if c < 0xC2 { return 1; } if c < 0xE0 {
18167 if n < 2 { return 1; }
18168 let c2 = *s.add(1);
18169 if (c2 & 0xC0) != 0x80 { return 1; }
18170 if !pc16.is_null() { *pc16 = ((((c & 0x1F) as u32) << 6) | ((c2 & 0x3F) as u32)) as u16; }
18171 return 2;
18172 }
18173 if c < 0xF0 {
18174 if n < 3 { return 1; }
18175 let c2 = *s.add(1);
18176 let c3 = *s.add(2);
18177 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 { return 1; }
18178 if !pc16.is_null() { *pc16 = ((((c & 0x0F) as u32) << 12) | (((c2 & 0x3F) as u32) << 6) | ((c3 & 0x3F) as u32)) as u16; }
18179 return 3;
18180 }
18181 1
18182}
18183
18184#[no_mangle]
18185pub unsafe extern "C" fn mbrtoc32(pc32: *mut u32, s: *const u8, n: usize, _ps: *mut core::ffi::c_void) -> usize {
18186 if s.is_null() { return 0; }
18187 if n == 0 { return 1; }
18188 let c = *s;
18189 if c == 0 { return 0; }
18190 if c < 0x80 {
18191 if !pc32.is_null() { *pc32 = c as u32; }
18192 return 1;
18193 }
18194 if c < 0xC2 { return 1; } if c < 0xE0 {
18196 if n < 2 { return 1; }
18197 let c2 = *s.add(1);
18198 if (c2 & 0xC0) != 0x80 { return 1; }
18199 if !pc32.is_null() { *pc32 = (((c & 0x1F) as u32) << 6) | ((c2 & 0x3F) as u32); }
18200 return 2;
18201 }
18202 if c < 0xF0 {
18203 if n < 3 { return 1; }
18204 let c2 = *s.add(1);
18205 let c3 = *s.add(2);
18206 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 { return 1; }
18207 if !pc32.is_null() { *pc32 = (((c & 0x0F) as u32) << 12) | (((c2 & 0x3F) as u32) << 6) | ((c3 & 0x3F) as u32); }
18208 return 3;
18209 }
18210 if c < 0xF5 {
18211 if n < 4 { return 1; }
18212 let c2 = *s.add(1);
18213 let c3 = *s.add(2);
18214 let c4 = *s.add(3);
18215 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80 { return 1; }
18216 if !pc32.is_null() { *pc32 = (((c & 0x07) as u32) << 18) | (((c2 & 0x3F) as u32) << 12) | (((c3 & 0x3F) as u32) << 6) | ((c4 & 0x3F) as u32); }
18217 return 4;
18218 }
18219 1
18220}
18221
18222#[no_mangle]
18234pub unsafe extern "C" fn chown(path: *const core::ffi::c_char, uid: u32, gid: u32) -> i32 {
18235 <Arch as Syscalls>::syscall3(SYS_FCHOWNAT, AT_FDCWD as i64, path as i64, ((uid as u64) << 32 | gid as u64) as i64) as i32
18236}
18237
18238#[no_mangle]
18239pub unsafe extern "C" fn lchown(path: *const core::ffi::c_char, uid: u32, gid: u32) -> i32 {
18240 <Arch as Syscalls>::syscall4(SYS_FCHOWNAT, AT_FDCWD as i64, path as i64, ((uid as u64) << 32 | gid as u64) as i64, 0x100) as i32
18241}
18242
18243#[no_mangle]
18248pub unsafe extern "C" fn chroot(path: *const core::ffi::c_char) -> i32 {
18249 <Arch as Syscalls>::syscall1(SYS_CHROOT, path as i64) as i32
18250}
18251
18252#[no_mangle]
18253pub unsafe extern "C" fn get_current_dir_name() -> *mut core::ffi::c_char {
18254 static mut BUF: [core::ffi::c_char; 4096] = [0; 4096];
18255 let r = getcwd(BUF.as_mut_ptr(), 4096);
18256 if r.is_null() { core::ptr::null_mut() } else { BUF.as_mut_ptr() }
18257}
18258
18259#[no_mangle]
18264pub unsafe extern "C" fn creat(pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18265 open(pathname, 0o100 | 0o200 | 0o1000, mode as i32)
18266}
18267
18268#[no_mangle]
18269pub unsafe extern "C" fn openat(dirfd: i32, pathname: *const core::ffi::c_char, flags: i32, mode: u32) -> i32 {
18270 <Arch as Syscalls>::syscall4(SYS_OPENAT, dirfd as i64, pathname as i64, flags as i64, mode as i64) as i32
18271}
18272
18273#[no_mangle]
18274pub unsafe extern "C" fn pwrite(fd: i32, buf: *const u8, count: usize, offset: i64) -> isize {
18275 <Arch as Syscalls>::syscall4(sysno(18, 68), fd as i64, buf as i64, count as i64, offset) as isize
18276}
18277
18278#[no_mangle]
18279pub unsafe extern "C" fn readv(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32) -> isize {
18280 <Arch as Syscalls>::syscall3(sysno(19, 65), fd as i64, iov as i64, iovcnt as i64) as isize
18281}
18282
18283#[no_mangle]
18284pub unsafe extern "C" fn writev(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32) -> isize {
18285 <Arch as Syscalls>::syscall3(sysno(20, 66), fd as i64, iov as i64, iovcnt as i64) as isize
18286}
18287
18288#[no_mangle]
18293pub unsafe extern "C" fn flock(fd: i32, operation: i32) -> i32 {
18294 <Arch as Syscalls>::syscall2(SYS_FLOCK, fd as i64, operation as i64) as i32
18295}
18296
18297#[no_mangle]
18298pub unsafe extern "C" fn lockf(fd: i32, cmd: i32, len: i64) -> i32 {
18299 let r = <Arch as Syscalls>::syscall3(SYS_FCNTL, fd as i64, if cmd == 0 { 7 } else if cmd == 1 { 6 } else { 5 } , len);
18300 if r < 0 { return -1; }
18301 0
18302}
18303
18304#[no_mangle]
18309pub unsafe extern "C" fn getdomainname(name: *mut core::ffi::c_char, len: usize) -> i32 {
18310 if cfg!(target_arch = "x86_64") { <Arch as Syscalls>::syscall2(156, name as i64, len as i64) as i32 } else { ERRNO = 38; -1 }
18311}
18312
18313#[no_mangle]
18314pub unsafe extern "C" fn setdomainname(name: *const core::ffi::c_char, len: usize) -> i32 {
18315 <Arch as Syscalls>::syscall2(sysno(171, 162), name as i64, len as i64) as i32
18316}
18317
18318#[no_mangle]
18319pub unsafe extern "C" fn sethostname(name: *const core::ffi::c_char, len: usize) -> i32 {
18320 <Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64) as i32
18321}
18322
18323#[no_mangle]
18324pub unsafe extern "C" fn getlogin_r(name: *mut core::ffi::c_char, bufsize: usize) -> i32 {
18325 let user = crate::getenv(b"USER\0".as_ptr() as *const core::ffi::c_char);
18327 if user.is_null() { return 2; }
18328 let mut i = 0;
18329 while i < bufsize - 1 && *user.add(i) != 0 {
18330 *name.add(i) = *user.add(i);
18331 i += 1;
18332 }
18333 *name.add(i) = 0;
18334 0
18335}
18336
18337#[no_mangle]
18338pub unsafe extern "C" fn cuserid(s: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
18339 let user = crate::getenv(b"USER\0".as_ptr() as *const core::ffi::c_char);
18340 if user.is_null() { return core::ptr::null_mut(); }
18341 if s.is_null() {
18342 static mut BUF: [core::ffi::c_char; 32] = [0; 32];
18343 let mut i = 0;
18344 while i < 31 && *user.add(i) != 0 { BUF[i] = *user.add(i); i += 1; }
18345 BUF[i] = 0;
18346 BUF.as_mut_ptr()
18347 } else {
18348 let mut i = 0;
18349 while i < 31 && *user.add(i) != 0 { *s.add(i) = *user.add(i); i += 1; }
18350 *s.add(i) = 0;
18351 s
18352 }
18353}
18354
18355#[repr(C)]
18360#[derive(Copy, Clone)]
18361pub struct Passwd {
18362 pub pw_name: *mut c_char,
18363 pub pw_passwd: *mut c_char,
18364 pub pw_uid: u32,
18365 pub pw_gid: u32,
18366 pub pw_gecos: *mut c_char,
18367 pub pw_dir: *mut c_char,
18368 pub pw_shell: *mut c_char,
18369}
18370
18371#[repr(C)]
18372#[derive(Copy, Clone)]
18373pub struct Group {
18374 pub gr_name: *mut c_char,
18375 pub gr_passwd: *mut c_char,
18376 pub gr_gid: u32,
18377 pub gr_mem: *mut *mut c_char,
18378}
18379
18380static mut PWD_ENT: Passwd = Passwd {
18381 pw_name: core::ptr::null_mut(), pw_passwd: core::ptr::null_mut(),
18382 pw_uid: 0, pw_gid: 0, pw_gecos: core::ptr::null_mut(),
18383 pw_dir: core::ptr::null_mut(), pw_shell: core::ptr::null_mut(),
18384};
18385static mut PWD_BUF: [c_char; 1024] = [0; 1024];
18386static mut PWD_FILE: *mut FILE = core::ptr::null_mut();
18387
18388static mut GRP_ENT: Group = Group {
18389 gr_name: core::ptr::null_mut(), gr_passwd: core::ptr::null_mut(),
18390 gr_gid: 0, gr_mem: core::ptr::null_mut(),
18391};
18392static mut GRP_BUF: [c_char; 2048] = [0; 2048];
18393static mut GRP_MEM: [*mut c_char; 32] = [core::ptr::null_mut(); 32];
18394static mut GRP_FILE: *mut FILE = core::ptr::null_mut();
18395
18396unsafe fn parse_passwd(line: *const c_char, ent: *mut Passwd, buf: *mut c_char, buflen: usize) -> bool {
18397 let mut src = line;
18398 let mut o = 0usize;
18399 let mut fields: [*mut c_char; 7] = [core::ptr::null_mut(); 7];
18400 let mut n = 0usize;
18401 while n < 7 {
18402 let start = o;
18403 while *src != 0 && *src != b':' as c_char {
18404 if o + 1 >= buflen { return false; }
18405 *buf.add(o) = *src;
18406 o += 1;
18407 src = src.add(1);
18408 }
18409 *buf.add(o) = 0;
18410 o += 1;
18411 fields[n] = buf.add(start);
18412 n += 1;
18413 if *src == 0 { break; }
18414 src = src.add(1);
18415 }
18416 if n < 7 { return false; }
18417 (*ent).pw_name = fields[0];
18418 (*ent).pw_passwd = fields[1];
18419 (*ent).pw_uid = crate::strtol(fields[2], core::ptr::null_mut(), 10) as u32;
18420 (*ent).pw_gid = crate::strtol(fields[3], core::ptr::null_mut(), 10) as u32;
18421 (*ent).pw_gecos = fields[4];
18422 (*ent).pw_dir = fields[5];
18423 (*ent).pw_shell = fields[6];
18424 true
18425}
18426
18427unsafe fn parse_group(line: *const c_char, ent: *mut Group, buf: *mut c_char, buflen: usize) -> bool {
18428 let mut src = line;
18429 let mut o = 0usize;
18430 let mut fields: [*mut c_char; 4] = [core::ptr::null_mut(); 4];
18431 let mut n = 0usize;
18432 while n < 4 {
18433 let start = o;
18434 while *src != 0 && *src != b':' as c_char {
18435 if o + 1 >= buflen { return false; }
18436 *buf.add(o) = *src;
18437 o += 1;
18438 src = src.add(1);
18439 }
18440 *buf.add(o) = 0;
18441 o += 1;
18442 fields[n] = buf.add(start);
18443 n += 1;
18444 if *src == 0 { break; }
18445 src = src.add(1);
18446 }
18447 if n < 4 { return false; }
18448 (*ent).gr_name = fields[0];
18449 (*ent).gr_passwd = fields[1];
18450 (*ent).gr_gid = crate::strtol(fields[2], core::ptr::null_mut(), 10) as u32;
18451 let mut mi = 0usize;
18452 let mut m = fields[3];
18453 if *m != 0 {
18454 loop {
18455 if mi + 1 >= GRP_MEM.len() { break; }
18456 GRP_MEM[mi] = m;
18457 mi += 1;
18458 while *m != 0 && *m != b',' as c_char { m = m.add(1); }
18459 if *m == 0 { break; }
18460 *m = 0;
18461 m = m.add(1);
18462 }
18463 }
18464 GRP_MEM[mi] = core::ptr::null_mut();
18465 (*ent).gr_mem = GRP_MEM.as_mut_ptr();
18466 true
18467}
18468
18469#[no_mangle]
18470pub unsafe extern "C" fn getpwnam(name: *const c_char) -> *mut Passwd {
18471 if name.is_null() { return core::ptr::null_mut(); }
18472 setpwent();
18473 loop {
18474 let p = getpwent();
18475 if p.is_null() { break; }
18476 if crate::strcmp((*p).pw_name as *const u8, name as *const u8) == 0 { endpwent(); return p; }
18477 }
18478 endpwent();
18479 core::ptr::null_mut()
18480}
18481
18482#[no_mangle]
18483pub unsafe extern "C" fn getpwuid(uid: u32) -> *mut Passwd {
18484 setpwent();
18485 loop {
18486 let p = getpwent();
18487 if p.is_null() { break; }
18488 if (*p).pw_uid == uid { endpwent(); return p; }
18489 }
18490 endpwent();
18491 core::ptr::null_mut()
18492}
18493
18494#[no_mangle]
18495pub unsafe extern "C" fn setpwent() {
18496 endpwent();
18497 PWD_FILE = crate::fopen(b"/etc/passwd\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
18498}
18499
18500#[no_mangle]
18501pub unsafe extern "C" fn getpwent() -> *mut Passwd {
18502 if PWD_FILE.is_null() { setpwent(); if PWD_FILE.is_null() { return core::ptr::null_mut(); } }
18503 let mut line = [0 as c_char; 1024];
18504 loop {
18505 if crate::fgets(line.as_mut_ptr(), 1024, PWD_FILE).is_null() { return core::ptr::null_mut(); }
18506 if parse_passwd(line.as_ptr(), &raw mut PWD_ENT, PWD_BUF.as_mut_ptr(), PWD_BUF.len()) {
18507 return &raw mut PWD_ENT;
18508 }
18509 }
18510}
18511
18512#[no_mangle]
18513pub unsafe extern "C" fn endpwent() {
18514 if !PWD_FILE.is_null() { crate::fclose(PWD_FILE); PWD_FILE = core::ptr::null_mut(); }
18515}
18516
18517#[no_mangle]
18518pub 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 {
18519 if result.is_null() { return EINVAL; }
18520 let p = getpwnam(name);
18521 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *pwd = *p; *result = pwd; 0 }
18522}
18523
18524#[no_mangle]
18525pub unsafe extern "C" fn getpwuid_r(uid: u32, pwd: *mut Passwd, _buf: *mut c_char, _buflen: usize, result: *mut *mut Passwd) -> c_int {
18526 if result.is_null() { return EINVAL; }
18527 let p = getpwuid(uid);
18528 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *pwd = *p; *result = pwd; 0 }
18529}
18530
18531#[no_mangle]
18532pub unsafe extern "C" fn fgetpwent(f: *mut FILE) -> *mut Passwd {
18533 if f.is_null() { return core::ptr::null_mut(); }
18534 let mut line = [0 as c_char; 1024];
18535 loop {
18536 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
18537 if parse_passwd(line.as_ptr(), &raw mut PWD_ENT, PWD_BUF.as_mut_ptr(), PWD_BUF.len()) {
18538 return &raw mut PWD_ENT;
18539 }
18540 }
18541}
18542
18543#[no_mangle]
18544pub unsafe extern "C" fn putpwent(f: *mut FILE, p: *const Passwd) -> c_int {
18545 if f.is_null() || p.is_null() { return -1; }
18546 crate::fprintf(f, b"%s:%s:%u:%u:%s:%s:%s\n\0".as_ptr() as *const c_char,
18547 (*p).pw_name, (*p).pw_passwd, (*p).pw_uid, (*p).pw_gid,
18548 (*p).pw_gecos, (*p).pw_dir, (*p).pw_shell)
18549}
18550
18551#[no_mangle]
18552pub unsafe extern "C" fn getgrnam(name: *const c_char) -> *mut Group {
18553 if name.is_null() { return core::ptr::null_mut(); }
18554 setgrent();
18555 loop {
18556 let g = getgrent();
18557 if g.is_null() { break; }
18558 if crate::strcmp((*g).gr_name as *const u8, name as *const u8) == 0 { endgrent(); return g; }
18559 }
18560 endgrent();
18561 core::ptr::null_mut()
18562}
18563
18564#[no_mangle]
18565pub unsafe extern "C" fn getgrgid(gid: u32) -> *mut Group {
18566 setgrent();
18567 loop {
18568 let g = getgrent();
18569 if g.is_null() { break; }
18570 if (*g).gr_gid == gid { endgrent(); return g; }
18571 }
18572 endgrent();
18573 core::ptr::null_mut()
18574}
18575
18576#[no_mangle]
18577pub unsafe extern "C" fn setgrent() {
18578 endgrent();
18579 GRP_FILE = crate::fopen(b"/etc/group\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
18580}
18581
18582#[no_mangle]
18583pub unsafe extern "C" fn getgrent() -> *mut Group {
18584 if GRP_FILE.is_null() { setgrent(); if GRP_FILE.is_null() { return core::ptr::null_mut(); } }
18585 let mut line = [0 as c_char; 1024];
18586 loop {
18587 if crate::fgets(line.as_mut_ptr(), 1024, GRP_FILE).is_null() { return core::ptr::null_mut(); }
18588 if parse_group(line.as_ptr(), &raw mut GRP_ENT, GRP_BUF.as_mut_ptr(), GRP_BUF.len()) {
18589 return &raw mut GRP_ENT;
18590 }
18591 }
18592}
18593
18594#[no_mangle]
18595pub unsafe extern "C" fn endgrent() {
18596 if !GRP_FILE.is_null() { crate::fclose(GRP_FILE); GRP_FILE = core::ptr::null_mut(); }
18597}
18598
18599#[no_mangle]
18600pub 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 {
18601 if result.is_null() { return EINVAL; }
18602 let g = getgrnam(name);
18603 if g.is_null() { *result = core::ptr::null_mut(); 0 } else { *grp = *g; *result = grp; 0 }
18604}
18605
18606#[no_mangle]
18607pub unsafe extern "C" fn getgrgid_r(gid: u32, grp: *mut Group, _buf: *mut c_char, _buflen: usize, result: *mut *mut Group) -> c_int {
18608 if result.is_null() { return EINVAL; }
18609 let g = getgrgid(gid);
18610 if g.is_null() { *result = core::ptr::null_mut(); 0 } else { *grp = *g; *result = grp; 0 }
18611}
18612
18613#[no_mangle]
18614pub unsafe extern "C" fn fgetgrent(f: *mut FILE) -> *mut Group {
18615 if f.is_null() { return core::ptr::null_mut(); }
18616 let mut line = [0 as c_char; 1024];
18617 loop {
18618 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
18619 if parse_group(line.as_ptr(), &raw mut GRP_ENT, GRP_BUF.as_mut_ptr(), GRP_BUF.len()) {
18620 return &raw mut GRP_ENT;
18621 }
18622 }
18623}
18624
18625#[no_mangle]
18626pub unsafe extern "C" fn putgrent(f: *mut FILE, g: *const Group) -> c_int {
18627 if f.is_null() || g.is_null() { return -1; }
18628 crate::fprintf(f, b"%s:%s:%u:\0".as_ptr() as *const c_char, (*g).gr_name, (*g).gr_passwd, (*g).gr_gid);
18629 if !(*g).gr_mem.is_null() {
18630 let mut i = 0;
18631 while !(*(*g).gr_mem.add(i)).is_null() {
18632 if i > 0 { crate::fputc(b',' as c_int, f); }
18633 crate::fputs(*(*g).gr_mem.add(i), f);
18634 i += 1;
18635 }
18636 }
18637 crate::fputc(b'\n' as c_int, f);
18638 0
18639}
18640
18641#[no_mangle]
18646pub unsafe extern "C" fn setgroups(ngroups: usize, gidset: *const u32) -> i32 {
18647 <Arch as Syscalls>::syscall2(SYS_SETGROUPS, ngroups as i64, gidset as i64) as i32
18648}
18649
18650#[no_mangle]
18651pub unsafe extern "C" fn setresuid(ruid: u32, euid: u32, suid: u32) -> i32 {
18652 <Arch as Syscalls>::syscall3(SYS_SETRESUID, ruid as i64, euid as i64, suid as i64) as i32
18653}
18654
18655#[no_mangle]
18656pub unsafe extern "C" fn setresgid(rgid: u32, egid: u32, sgid: u32) -> i32 {
18657 <Arch as Syscalls>::syscall3(SYS_SETRESGID, rgid as i64, egid as i64, sgid as i64) as i32
18658}
18659
18660#[no_mangle]
18661pub unsafe extern "C" fn getresuid(ruid: *mut u32, euid: *mut u32, suid: *mut u32) -> i32 {
18662 <Arch as Syscalls>::syscall3(SYS_GETRESUID, ruid as i64, euid as i64, suid as i64) as i32
18663}
18664
18665#[no_mangle]
18666pub unsafe extern "C" fn getresgid(rgid: *mut u32, egid: *mut u32, sgid: *mut u32) -> i32 {
18667 <Arch as Syscalls>::syscall3(SYS_GETRESGID, rgid as i64, egid as i64, sgid as i64) as i32
18668}
18669
18670#[no_mangle]
18675pub unsafe extern "C" fn sendmsg(fd: i32, msg: *const core::ffi::c_void, flags: i32) -> isize {
18676 <Arch as Syscalls>::syscall3(SYS_SENDMSG, fd as i64, msg as i64, flags as i64) as isize
18677}
18678
18679#[no_mangle]
18680pub unsafe extern "C" fn recvmsg(fd: i32, msg: *mut core::ffi::c_void, flags: i32) -> isize {
18681 <Arch as Syscalls>::syscall3(SYS_RECVMSG, fd as i64, msg as i64, flags as i64) as isize
18682}
18683
18684#[no_mangle]
18685pub unsafe extern "C" fn sendmmsg(fd: i32, msgvec: *mut core::ffi::c_void, vlen: u32, flags: i32) -> i32 {
18686 <Arch as Syscalls>::syscall4(sysno(307, 269), fd as i64, msgvec as i64, vlen as i64, flags as i64) as i32
18687}
18688
18689#[no_mangle]
18690pub unsafe extern "C" fn recvmmsg(fd: i32, msgvec: *mut core::ffi::c_void, vlen: u32, flags: i32, timeout: *mut core::ffi::c_void) -> i32 {
18691 <Arch as Syscalls>::syscall5(sysno(299, 243), fd as i64, msgvec as i64, vlen as i64, flags as i64, timeout as i64) as i32
18692}
18693
18694#[no_mangle]
18695pub unsafe extern "C" fn getpeername(fd: i32, addr: *mut core::ffi::c_void, addrlen: *mut u32) -> i32 {
18696 <Arch as Syscalls>::syscall3(sysno(52, 205), fd as i64, addr as i64, addrlen as i64) as i32
18697}
18698
18699#[no_mangle]
18700pub unsafe extern "C" fn getsockopt(fd: i32, level: i32, optname: i32, optval: *mut core::ffi::c_void, optlen: *mut u32) -> i32 {
18701 <Arch as Syscalls>::syscall5(sysno(55, 209), fd as i64, level as i64, optname as i64, optval as i64, optlen as i64) as i32
18702}
18703
18704#[no_mangle]
18709pub unsafe extern "C" fn ftrylockfile(file: *mut FILE) -> i32 {
18710 if file.is_null() { return EINVAL; }
18711 if (*file).lock < 0 { return 0; }
18712 let tid = sys_gettid() as c_int;
18713 let v = a_load(&raw const (*file).lock);
18714 if v == tid {
18715 (*file).lockcount += 1;
18716 return 0;
18717 }
18718 if v == 0 && a_cas(&raw mut (*file).lock, 0, tid) == 0 {
18719 (*file).lockcount = 1;
18720 return 0;
18721 }
18722 EBUSY
18723}
18724
18725#[no_mangle]
18726pub unsafe extern "C" fn getc_unlocked(file: *mut core::ffi::c_char) -> i32 {
18727 getc(file as *mut FILE)
18728}
18729
18730#[no_mangle]
18731pub unsafe extern "C" fn getchar_unlocked() -> i32 {
18732 getchar()
18733}
18734
18735#[no_mangle]
18736pub unsafe extern "C" fn putc_unlocked(c: i32, file: *mut core::ffi::c_char) -> i32 {
18737 putc(c, file as *mut FILE)
18738}
18739
18740#[no_mangle]
18741pub unsafe extern "C" fn putchar_unlocked(c: i32) -> i32 {
18742 putchar(c)
18743}
18744
18745#[no_mangle] pub static mut optarg: *mut core::ffi::c_char = core::ptr::null_mut();
18750#[no_mangle] pub static mut optind: i32 = 1;
18751#[no_mangle] pub static mut opterr: i32 = 1;
18752#[no_mangle] pub static mut optopt: i32 = '?' as i32;
18753#[no_mangle] pub static mut optreset: i32 = 0;
18754
18755#[no_mangle]
18760pub unsafe extern "C" fn getitimer(which: i32, curr_value: *mut core::ffi::c_void) -> i32 {
18761 <Arch as Syscalls>::syscall2(sysno(36, 102), which as i64, curr_value as i64) as i32
18762}
18763
18764#[no_mangle]
18765pub unsafe extern "C" fn setitimer(which: i32, new_value: *const core::ffi::c_void, old_value: *mut core::ffi::c_void) -> i32 {
18766 <Arch as Syscalls>::syscall3(sysno(38, 103), which as i64, new_value as i64, old_value as i64) as i32
18767}
18768
18769#[no_mangle]
18774pub unsafe extern "C" fn getloadavg(loadavg: *mut f64, nelem: i32) -> i32 {
18775 let fd = crate::open(b"/proc/loadavg\0".as_ptr() as *const core::ffi::c_char, 0, 0);
18776 if fd < 0 { return -1; }
18777 let mut buf: [u8; 64] = [0; 64];
18778 let n = crate::read(fd, buf.as_mut_ptr() as *mut core::ffi::c_void, 63);
18779 crate::close(fd);
18780 if n <= 0 { return -1; }
18781 buf[n as usize] = 0;
18782 let mut i = 0;
18783 while i < nelem as usize && i < 3 {
18784 let val = crate::strtod((buf.as_ptr() as *const core::ffi::c_char).add(i * 5), core::ptr::null_mut());
18785 *loadavg.add(i) = val;
18786 i += 1;
18787 }
18788 i as i32
18789}
18790
18791#[no_mangle]
18792pub unsafe extern "C" fn get_nprocs() -> i32 {
18793 sysconf(84) as i32 }
18795
18796#[no_mangle]
18797pub unsafe extern "C" fn get_nprocs_conf() -> i32 {
18798 sysconf(83) as i32 }
18800
18801#[no_mangle]
18802pub unsafe extern "C" fn get_avphys_pages() -> i64 {
18803 sysconf(86) }
18805
18806#[no_mangle]
18807pub unsafe extern "C" fn get_phys_pages() -> i64 {
18808 sysconf(85) }
18810
18811#[no_mangle]
18816pub unsafe extern "C" fn capget(header: *mut core::ffi::c_void, data: *mut core::ffi::c_void) -> i32 {
18817 <Arch as Syscalls>::syscall2(SYS_CAPGET, header as i64, data as i64) as i32
18818}
18819
18820#[no_mangle]
18821pub unsafe extern "C" fn capset(header: *const core::ffi::c_void, data: *const core::ffi::c_void) -> i32 {
18822 <Arch as Syscalls>::syscall2(SYS_CAPSET, header as i64, data as i64) as i32
18823}
18824
18825#[no_mangle]
18826pub unsafe extern "C" fn arch_prctl(code: i32, addr: u64) -> i32 {
18827 if cfg!(target_arch = "x86_64") { <Arch as Syscalls>::syscall2(158, code as i64, addr as i64) as i32 } else { ERRNO = 38; -1 }
18828}
18829
18830#[no_mangle]
18835pub unsafe extern "C" fn cfgetospeed(termios_p: *const core::ffi::c_void) -> u32 {
18836 unsafe { *(termios_p as *const u32).add(1) }
18837}
18838
18839#[no_mangle]
18840pub unsafe extern "C" fn cfgetispeed(termios_p: *const core::ffi::c_void) -> u32 {
18841 unsafe { *(termios_p as *const u32).add(2) }
18842}
18843
18844#[no_mangle]
18845pub unsafe extern "C" fn cfsetospeed(termios_p: *mut core::ffi::c_void, speed: u32) -> i32 {
18846 unsafe { *(termios_p as *mut u32).add(1) = speed; }
18847 0
18848}
18849
18850#[no_mangle]
18851pub unsafe extern "C" fn cfsetispeed(termios_p: *mut core::ffi::c_void, speed: u32) -> i32 {
18852 unsafe { *(termios_p as *mut u32).add(2) = speed; }
18853 0
18854}
18855
18856#[no_mangle]
18857pub unsafe extern "C" fn cfmakeraw(termios_p: *mut core::ffi::c_void) {
18858 unsafe {
18859 let p = termios_p as *mut u32;
18860 *p.add(0) &= !0o37;
18861 *p.add(0) &= !(0o4000 | 0o2000 | 0o10000 | 0o20);
18862 *p.add(0) |= 0o60;
18863 *p.add(3) &= !0o17;
18864 *p.add(3) &= !(0o1000 | 0o40000000);
18865 *p.add(1) = 1;
18866 *p.add(2) = 0;
18867 }
18868}
18869
18870#[no_mangle]
18875pub unsafe extern "C" fn getrusage(who: i32, usage: *mut core::ffi::c_void) -> i32 {
18876 <Arch as Syscalls>::syscall2(sysno(98, 165), who as i64, usage as i64) as i32
18877}
18878
18879#[no_mangle]
18880pub unsafe extern "C" fn getpriority(which: i32, who: u32) -> i32 {
18881 <Arch as Syscalls>::syscall2(SYS_GETPRIORITY, which as i64, who as i64) as i32
18882}
18883
18884#[no_mangle]
18885pub unsafe extern "C" fn setpriority(which: i32, who: u32, prio: i32) -> i32 {
18886 <Arch as Syscalls>::syscall3(SYS_SETPRIORITY, which as i64, who as i64, prio as i64) as i32
18887}
18888
18889#[no_mangle]
18890pub unsafe extern "C" fn prlimit(pid: u32, resource: i32, new_limit: *const core::ffi::c_void, old_limit: *mut core::ffi::c_void) -> i32 {
18891 <Arch as Syscalls>::syscall4(sysno(302, 261), pid as i64, resource as i64, new_limit as i64, old_limit as i64) as i32
18892}
18893
18894#[no_mangle]
18899pub unsafe extern "C" fn clone(flags: u32, child_stack: *mut u8, _args: ...) -> i32 {
18900 <Arch as Syscalls>::syscall5(SYS_CLONE, flags as i64, child_stack as i64, 0, 0, 0) as i32
18901}
18902
18903#[no_mangle]
18904pub unsafe extern "C" fn _Fork() -> i32 {
18905 crate::fork()
18906}
18907
18908#[no_mangle]
18909pub 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 {
18910 let mut master: i32 = 0;
18911 let mut slave: i32 = 0;
18912 if openpty(&mut master, &mut slave, name, termp, winp) < 0 { return -1; }
18913 let pid = crate::fork();
18914 if pid < 0 { crate::close(master); crate::close(slave); return -1; }
18915 if pid == 0 {
18916 crate::close(master);
18917 crate::setsid();
18918 crate::dup2(slave, 0);
18919 crate::dup2(slave, 1);
18920 crate::dup2(slave, 2);
18921 } else {
18922 crate::close(slave);
18923 if !amaster.is_null() { *amaster = master; }
18924 }
18925 pid
18926}
18927
18928#[no_mangle]
18929pub 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 {
18930 let master = crate::open(b"/dev/ptmx\0".as_ptr() as *const core::ffi::c_char, 0o2000, 0);
18931 if master < 0 { return -1; }
18932 grantpt(master);
18933 unlockpt(master);
18934 let slave_name = ptsname(master);
18935 if slave_name.is_null() { crate::close(master); return -1; }
18936 let slave = crate::open(slave_name, 0o2000, 0);
18937 if slave < 0 { crate::close(master); return -1; }
18938 if !amaster.is_null() { *amaster = master; }
18939 if !aslave.is_null() { *aslave = slave; }
18940 if !name.is_null() { crate::strcpy(name as *mut u8, slave_name as *const u8); }
18941 0
18942}
18943
18944#[no_mangle]
18945pub unsafe extern "C" fn login_tty(fd: i32) -> i32 {
18946 crate::setsid();
18947 crate::dup2(fd, 0);
18948 crate::dup2(fd, 1);
18949 crate::dup2(fd, 2);
18950 0
18951}
18952
18953#[no_mangle]
18958pub unsafe extern "C" fn __dls2b() {}
18959#[no_mangle]
18960pub unsafe extern "C" fn __dls3() {}
18961#[no_mangle]
18962pub unsafe extern "C" fn _dlstart() {}
18963
18964#[no_mangle]
18969pub unsafe extern "C" fn index(s: *const core::ffi::c_char, c: i32) -> *mut core::ffi::c_char {
18970 let mut i = 0;
18971 loop {
18972 let ch = *s.add(i);
18973 if ch == c as core::ffi::c_char { return s.add(i) as *mut core::ffi::c_char; }
18974 if ch == 0 { return core::ptr::null_mut(); }
18975 i += 1;
18976 }
18977}
18978
18979#[no_mangle]
18980pub unsafe extern "C" fn rindex(s: *const core::ffi::c_char, c: i32) -> *mut core::ffi::c_char {
18981 let mut last = core::ptr::null_mut();
18982 let mut i = 0;
18983 loop {
18984 let ch = *s.add(i);
18985 if ch == 0 { return last; }
18986 if ch == c as core::ffi::c_char { last = s.add(i) as *mut core::ffi::c_char; }
18987 i += 1;
18988 }
18989}
18990
18991#[no_mangle]
18996pub unsafe extern "C" fn imaxabs(j: i64) -> i64 {
18997 j.abs()
18998}
18999
19000#[no_mangle]
19001pub unsafe extern "C" fn imaxdiv(numer: i64, denom: i64) -> (i64, i64) {
19002 (numer / denom, numer % denom)
19003}
19004
19005#[no_mangle]
19010pub static mut h_errno: i32 = 0;
19011
19012#[no_mangle]
19013pub unsafe extern "C" fn __h_errno_location() -> *mut i32 {
19014 &mut h_errno
19015}
19016
19017#[no_mangle]
19018pub unsafe extern "C" fn herror(s: *const core::ffi::c_char) {
19019 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
19020 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
19021 crate::write(2, hstrerror(*__h_errno_location()) as *const core::ffi::c_void, crate::strlen(hstrerror(*__h_errno_location())));
19022 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
19023}
19024
19025#[no_mangle]
19026pub unsafe extern "C" fn hstrerror(_err: i32) -> *const core::ffi::c_char {
19027 b"Unknown error\0".as_ptr() as *const core::ffi::c_char
19028}
19029
19030#[no_mangle]
19035pub unsafe extern "C" fn gettid() -> i32 {
19036 <Arch as Syscalls>::syscall0(SYS_GETTID) as i32
19037}
19038
19039#[no_mangle]
19044pub unsafe extern "C" fn ioctl(fd: i32, request: u32, mut args: ...) -> i32 {
19045 let arg = args.next_arg::<i64>();
19046 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, request as i64, arg) as i32
19047}
19048
19049#[no_mangle]
19050pub unsafe extern "C" fn ioperm(from: u64, num: u64, turn_on: i32) -> i32 {
19051 #[cfg(target_arch = "x86_64")]
19052 { <Arch as Syscalls>::syscall3(SYS_IOPERM, from as i64, num as i64, turn_on as i64) as i32 }
19053 #[cfg(not(target_arch = "x86_64"))]
19054 {
19055 let _ = (from, num, turn_on);
19056 ERRNO = ENOSYS_VAL;
19057 -1
19058 }
19059}
19060
19061#[no_mangle]
19062pub unsafe extern "C" fn iopl(level: i32) -> i32 {
19063 #[cfg(target_arch = "x86_64")]
19064 { <Arch as Syscalls>::syscall1(SYS_IOPL, level as i64) as i32 }
19065 #[cfg(not(target_arch = "x86_64"))]
19066 {
19067 let _ = level;
19068 ERRNO = ENOSYS_VAL;
19069 -1
19070 }
19071}
19072
19073#[no_mangle]
19078pub unsafe extern "C" fn getxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19079 <Arch as Syscalls>::syscall4(sysno(191, 8), path as i64, name as i64, value as i64, size as i64) as isize
19080}
19081
19082#[no_mangle]
19083pub unsafe extern "C" fn lgetxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19084 <Arch as Syscalls>::syscall4(sysno(192, 9), path as i64, name as i64, value as i64, size as i64) as isize
19085}
19086
19087#[no_mangle]
19088pub unsafe extern "C" fn fgetxattr(fd: i32, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19089 <Arch as Syscalls>::syscall4(sysno(193, 10), fd as i64, name as i64, value as i64, size as i64) as isize
19090}
19091
19092#[no_mangle]
19093pub unsafe extern "C" fn listxattr(path: *const core::ffi::c_char, list: *mut u8, size: usize) -> isize {
19094 <Arch as Syscalls>::syscall3(sysno(194, 11), path as i64, list as i64, size as i64) as isize
19095}
19096
19097#[no_mangle]
19098pub unsafe extern "C" fn llistxattr(path: *const core::ffi::c_char, list: *mut u8, size: usize) -> isize {
19099 <Arch as Syscalls>::syscall3(sysno(195, 12), path as i64, list as i64, size as i64) as isize
19100}
19101
19102#[no_mangle]
19103pub unsafe extern "C" fn flistxattr(fd: i32, list: *mut u8, size: usize) -> isize {
19104 <Arch as Syscalls>::syscall3(sysno(196, 13), fd as i64, list as i64, size as i64) as isize
19105}
19106
19107#[no_mangle]
19108pub 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 {
19109 <Arch as Syscalls>::syscall5(sysno(188, 5), path as i64, name as i64, value as i64, size as i64, flags as i64) as i32
19110}
19111
19112#[no_mangle]
19113pub 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 {
19114 <Arch as Syscalls>::syscall5(sysno(189, 6), path as i64, name as i64, value as i64, size as i64, flags as i64) as i32
19115}
19116
19117#[no_mangle]
19118pub unsafe extern "C" fn fsetxattr(fd: i32, name: *const core::ffi::c_char, value: *const u8, size: usize, flags: i32) -> i32 {
19119 <Arch as Syscalls>::syscall5(sysno(190, 7), fd as i64, name as i64, value as i64, size as i64, flags as i64) as i32
19120}
19121
19122#[no_mangle]
19123pub unsafe extern "C" fn removexattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char) -> i32 {
19124 <Arch as Syscalls>::syscall2(sysno(197, 14), path as i64, name as i64) as i32
19125}
19126
19127#[no_mangle]
19128pub unsafe extern "C" fn lremovexattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char) -> i32 {
19129 <Arch as Syscalls>::syscall2(sysno(198, 15), path as i64, name as i64) as i32
19130}
19131
19132#[no_mangle]
19133pub unsafe extern "C" fn fremovexattr(fd: i32, name: *const core::ffi::c_char) -> i32 {
19134 <Arch as Syscalls>::syscall2(sysno(199, 16), fd as i64, name as i64) as i32
19135}
19136
19137#[no_mangle]
19142pub unsafe extern "C" fn adjtime(_delta: *const core::ffi::c_void, olddelta: *mut core::ffi::c_void) -> i32 {
19143 <Arch as Syscalls>::syscall1(SYS_ADJTIMEX, olddelta as i64) as i32
19144}
19145
19146#[no_mangle]
19147pub unsafe extern "C" fn adjtimex(buf: *mut core::ffi::c_void) -> i32 {
19148 <Arch as Syscalls>::syscall1(SYS_ADJTIMEX, buf as i64) as i32
19149}
19150
19151#[no_mangle]
19156pub unsafe extern "C" fn grantpt(fd: i32) -> i32 {
19157 let mut s: u32 = 0;
19159 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5410, &mut s as *mut u32 as i64);
19160 0
19161}
19162
19163#[no_mangle]
19164pub unsafe extern "C" fn unlockpt(fd: i32) -> i32 {
19165 let mut unlock: i32 = 0;
19166 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5411, &mut unlock as *mut i32 as i64);
19167 0
19168}
19169
19170#[no_mangle]
19171pub unsafe extern "C" fn ptsname(fd: i32) -> *mut core::ffi::c_char {
19172 static mut BUF: [core::ffi::c_char; 32] = [0; 32];
19173 let mut pty_nr: i32 = 0;
19174 if <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5413, &mut pty_nr as *mut i32 as i64) < 0 {
19175 return core::ptr::null_mut();
19176 }
19177 BUF[0] = '/' as c_char; BUF[1] = 'd' as c_char; BUF[2] = 'e' as c_char; BUF[3] = 'v' as c_char;
19179 BUF[4] = '/' as c_char; BUF[5] = 'p' as c_char; BUF[6] = 't' as c_char; BUF[7] = 's' as c_char;
19180 BUF[8] = '/' as c_char;
19181 let mut n = pty_nr as usize;
19182 let mut i = 9;
19183 if n == 0 { BUF[i] = '0' as c_char; i += 1; }
19184 while n > 0 && i < 31 {
19185 BUF[i] = (b'0' + (n % 10) as u8) as c_char;
19186 n /= 10;
19187 i += 1;
19188 }
19189 BUF[i] = 0;
19190 BUF.as_mut_ptr()
19191}
19192
19193#[no_mangle]
19198pub unsafe extern "C" fn finite(x: f64) -> i32 {
19199 (!x.is_nan() && !x.is_infinite()) as i32
19200}
19201
19202#[no_mangle]
19203pub unsafe extern "C" fn finitef(x: f32) -> i32 {
19204 (!x.is_nan() && !x.is_infinite()) as i32
19205}
19206
19207#[no_mangle]
19208pub unsafe extern "C" fn __fpclassifyl(x: f64) -> i32 {
19209 __fpclassify(x)
19210}
19211
19212#[no_mangle]
19213pub unsafe extern "C" fn __signbitl(x: f64) -> i32 {
19214 __signbit(x)
19215}
19216
19217#[no_mangle]
19226pub unsafe extern "C" fn j0(x: f64) -> f64 {
19227 libm::j0(x)
19228}
19229
19230#[no_mangle]
19231pub unsafe extern "C" fn j0f(x: f32) -> f32 {
19232 libm::j0f(x)
19233}
19234
19235#[no_mangle]
19236pub unsafe extern "C" fn j1(x: f64) -> f64 {
19237 libm::j1(x)
19238}
19239
19240#[no_mangle]
19241pub unsafe extern "C" fn j1f(x: f32) -> f32 {
19242 libm::j1f(x)
19243}
19244
19245#[no_mangle]
19246pub unsafe extern "C" fn jn(n: i32, x: f64) -> f64 {
19247 libm::jn(n, x)
19248}
19249
19250#[no_mangle]
19251pub unsafe extern "C" fn jnf(n: i32, x: f32) -> f32 {
19252 libm::jnf(n, x)
19253}
19254
19255#[no_mangle]
19256pub unsafe extern "C" fn y0(x: f64) -> f64 {
19257 if x.is_nan() { return x; }
19258 if x < 0.0 { return __math_invalid(x); }
19259 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f64::NEG_INFINITY; }
19260 libm::y0(x)
19261}
19262
19263#[no_mangle]
19264pub unsafe extern "C" fn y0f(x: f32) -> f32 {
19265 if x.is_nan() { return x; }
19266 if x < 0.0 { return __math_invalidf(x); }
19267 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f32::NEG_INFINITY; }
19268 libm::y0f(x)
19269}
19270
19271#[no_mangle]
19272pub unsafe extern "C" fn y1(x: f64) -> f64 {
19273 if x.is_nan() { return x; }
19274 if x < 0.0 { return __math_invalid(x); }
19275 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f64::NEG_INFINITY; }
19276 libm::y1(x)
19277}
19278
19279#[no_mangle]
19280pub unsafe extern "C" fn y1f(x: f32) -> f32 {
19281 if x.is_nan() { return x; }
19282 if x < 0.0 { return __math_invalidf(x); }
19283 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f32::NEG_INFINITY; }
19284 libm::y1f(x)
19285}
19286
19287#[no_mangle]
19288pub unsafe extern "C" fn yn(n: i32, x: f64) -> f64 {
19289 if x.is_nan() { return x; }
19290 if x < 0.0 { return __math_invalid(x); }
19291 if x == 0.0 {
19292 feraiseexcept(FE_DIVBYZERO);
19293 if n >= 0 { return f64::NEG_INFINITY; }
19294 }
19295 libm::yn(n, x)
19296}
19297
19298#[no_mangle]
19299pub unsafe extern "C" fn ynf(n: i32, x: f32) -> f32 {
19300 if x.is_nan() { return x; }
19301 if x < 0.0 { return __math_invalidf(x); }
19302 if x == 0.0 {
19303 feraiseexcept(FE_DIVBYZERO);
19304 if n >= 0 { return f32::NEG_INFINITY; }
19305 }
19306 libm::ynf(n, x)
19307}
19308
19309#[no_mangle]
19314pub unsafe extern "C" fn __ctype_b_loc() -> *mut *const u16 {
19315 static mut TABLE: *const u16 = core::ptr::null();
19316 &mut TABLE
19317}
19318
19319#[no_mangle]
19320pub unsafe extern "C" fn __ctype_tolower_loc() -> *mut *const i32 {
19321 static mut TABLE: *const i32 = core::ptr::null();
19322 &mut TABLE
19323}
19324
19325#[no_mangle]
19326pub unsafe extern "C" fn __ctype_toupper_loc() -> *mut *const i32 {
19327 static mut TABLE: *const i32 = core::ptr::null();
19328 &mut TABLE
19329}
19330
19331#[no_mangle]
19332pub unsafe extern "C" fn __isalnum_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19333 (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
19334}
19335
19336#[no_mangle]
19337pub unsafe extern "C" fn __isalpha_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19338 (c >= 'A' as i32 && c <= 'Z' as i32 || c >= 'a' as i32 && c <= 'z' as i32) as i32
19339}
19340
19341#[no_mangle]
19342pub unsafe extern "C" fn __isblank_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19343 (c == ' ' as i32 || c == '\t' as i32) as i32
19344}
19345
19346#[no_mangle]
19347pub unsafe extern "C" fn __iscntrl_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19348 (c < 0x20 || c == 0x7f) as i32
19349}
19350
19351#[no_mangle]
19352pub unsafe extern "C" fn __isdigit_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19353 (c >= '0' as i32 && c <= '9' as i32) as i32
19354}
19355
19356#[no_mangle]
19357pub unsafe extern "C" fn __isgraph_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19358 (c > 0x20 && c < 0x7f) as i32
19359}
19360
19361#[no_mangle]
19362pub unsafe extern "C" fn __islower_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19363 (c >= 'a' as i32 && c <= 'z' as i32) as i32
19364}
19365
19366#[no_mangle]
19367pub unsafe extern "C" fn __isprint_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19368 (c >= 0x20 && c < 0x7f) as i32
19369}
19370
19371#[no_mangle]
19372pub unsafe extern "C" fn __ispunct_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19373 (c >= 0x21 && c <= 0x2f || c >= 0x3a && c <= 0x40 || c >= 0x5b && c <= 0x60 || c >= 0x7b && c <= 0x7e) as i32
19374}
19375
19376#[no_mangle]
19377pub unsafe extern "C" fn __isspace_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19378 (c == ' ' as i32 || c >= 0x09 && c <= 0x0d) as i32
19379}
19380
19381#[no_mangle]
19382pub unsafe extern "C" fn __isupper_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19383 (c >= 'A' as i32 && c <= 'Z' as i32) as i32
19384}
19385
19386#[no_mangle]
19387pub unsafe extern "C" fn __isxdigit_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19388 (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
19389}
19390
19391#[no_mangle]
19396pub unsafe extern "C" fn __iswalnum_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19397 (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
19398}
19399
19400#[no_mangle]
19401pub unsafe extern "C" fn __iswalpha_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19402 (c >= 'A' as u32 && c <= 'Z' as u32 || c >= 'a' as u32 && c <= 'z' as u32) as i32
19403}
19404
19405#[no_mangle]
19406pub unsafe extern "C" fn __iswblank_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19407 (c == ' ' as u32 || c == '\t' as u32) as i32
19408}
19409
19410#[no_mangle]
19411pub unsafe extern "C" fn __iswcntrl_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19412 (c < 0x20 || c == 0x7f) as i32
19413}
19414
19415#[no_mangle]
19416pub unsafe extern "C" fn __iswdigit_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19417 (c >= '0' as u32 && c <= '9' as u32) as i32
19418}
19419
19420#[no_mangle]
19421pub unsafe extern "C" fn __iswgraph_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19422 (c > 0x20 && c < 0x7f) as i32
19423}
19424
19425#[no_mangle]
19426pub unsafe extern "C" fn __iswlower_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19427 (c >= 'a' as u32 && c <= 'z' as u32) as i32
19428}
19429
19430#[no_mangle]
19431pub unsafe extern "C" fn __iswprint_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19432 (c >= 0x20 && c < 0x7f) as i32
19433}
19434
19435#[no_mangle]
19436pub unsafe extern "C" fn __iswpunct_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19437 (c >= 0x21 && c <= 0x2f || c >= 0x3a && c <= 0x40 || c >= 0x5b && c <= 0x60 || c >= 0x7b && c <= 0x7e) as i32
19438}
19439
19440#[no_mangle]
19441pub unsafe extern "C" fn __iswspace_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19442 (c == ' ' as u32 || c >= 0x09 && c <= 0x0d) as i32
19443}
19444
19445#[no_mangle]
19446pub unsafe extern "C" fn __iswupper_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19447 (c >= 'A' as u32 && c <= 'Z' as u32) as i32
19448}
19449
19450#[no_mangle]
19451pub unsafe extern "C" fn __iswxdigit_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19452 (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
19453}
19454
19455#[no_mangle]
19456pub unsafe extern "C" fn __iswctype_l(c: u32, ctype: u32, _loc: *mut core::ffi::c_void) -> i32 {
19457 crate::iswctype(c as wint_t, ctype as wctype_t)
19458}
19459
19460#[no_mangle]
19461pub unsafe extern "C" fn __towlower_l(c: u32, _loc: *mut core::ffi::c_void) -> u32 {
19462 crate::towlower(c)
19463}
19464
19465#[no_mangle]
19466pub unsafe extern "C" fn __towupper_l(c: u32, _loc: *mut core::ffi::c_void) -> u32 {
19467 crate::towupper(c)
19468}
19469
19470#[no_mangle]
19471pub unsafe extern "C" fn __towctrans_l(c: u32, _trans: u32, _loc: *mut core::ffi::c_void) -> u32 {
19472 c
19473}
19474
19475#[no_mangle]
19488pub 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) {
19489 crate::write(2, b"Assertion failed: ".as_ptr() as *const core::ffi::c_void, 18);
19490 if !expr.is_null() { crate::write(2, expr as *const core::ffi::c_void, crate::strlen(expr)); }
19491 crate::write(2, b" (".as_ptr() as *const core::ffi::c_void, 2);
19492 if !file.is_null() { crate::write(2, file as *const core::ffi::c_void, crate::strlen(file)); }
19493 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
19494 let mut n = line as usize;
19495 let mut digits: [u8; 32] = [0; 32];
19496 let mut di = 0;
19497 if n == 0 { digits[0] = 0; di = 1; }
19498 while n > 0 && di < 32 { digits[di] = (n % 10) as u8; n /= 10; di += 1; }
19499 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); }
19500 crate::write(2, b")".as_ptr() as *const core::ffi::c_void, 1);
19501 if !func.is_null() { crate::write(2, func as *const core::ffi::c_void, crate::strlen(func)); }
19502 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
19503 crate::abort()
19504}
19505
19506#[no_mangle]
19507pub unsafe extern "C" fn at_quick_exit(_func: Option<unsafe extern "C" fn()>) -> i32 {
19508 0
19510}
19511
19512#[no_mangle]
19513pub unsafe extern "C" fn brk(addr: *mut u8) -> i32 {
19514 <Arch as Syscalls>::syscall1(sysno(12, 214), addr as i64) as i32
19515}
19516
19517#[no_mangle]
19518pub 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 {
19519 <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
19520}
19521
19522#[no_mangle]
19523pub unsafe extern "C" fn ctermid(s: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
19524 static mut BUF: [core::ffi::c_char; 20] = [0; 20];
19525 let dst = if s.is_null() { BUF.as_mut_ptr() } else { s };
19526 let src = b"/dev/tty\0".as_ptr() as *const core::ffi::c_char;
19527 let mut i = 0;
19528 while i < 9 { *dst.add(i) = *src.add(i); i += 1; }
19529 dst
19530}
19531
19532#[no_mangle]
19533pub unsafe extern "C" fn delete_module(name: *const core::ffi::c_char, flags: u32) -> i32 {
19534 <Arch as Syscalls>::syscall2(SYS_DELETE_MODULE, name as i64, flags as i64) as i32
19535}
19536
19537
19538
19539
19540
19541#[no_mangle]
19542pub unsafe extern "C" fn __duplocale(loc: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
19543 loc
19544}
19545
19546#[no_mangle]
19547pub unsafe extern "C" fn euidaccess(pathname: *const core::ffi::c_char, mode: i32) -> i32 {
19548 faccessat(AT_FDCWD, pathname, mode, 0x200)
19549}
19550
19551#[no_mangle]
19552pub unsafe extern "C" fn fgetln(f: *mut core::ffi::c_void, lenp: *mut usize) -> *mut core::ffi::c_char {
19553 static mut BUF: [core::ffi::c_char; 4096] = [0; 4096];
19554 let mut i = 0;
19555 while i < 4095 {
19556 let c = getc(f as *mut FILE);
19557 if c < 0 { break; }
19558 BUF[i] = c as c_char;
19559 i += 1;
19560 if c == '\n' as i32 { break; }
19561 }
19562 BUF[i] = 0;
19563 if !lenp.is_null() { *lenp = i; }
19564 if i == 0 { core::ptr::null_mut() } else { BUF.as_mut_ptr() }
19565}
19566
19567#[no_mangle]
19568pub unsafe extern "C" fn fgetws(ws: *mut u32, n: i32, f: *mut core::ffi::c_void) -> *mut u32 {
19569 let mut i = 0;
19570 while i < n - 1 {
19571 let c = getwc(f as *mut core::ffi::c_void);
19572 if c == 0 { break; }
19573 *ws.add(i as usize) = c;
19574 i += 1;
19575 if c == '\n' as u32 { break; }
19576 }
19577 *ws.add(i as usize) = 0;
19578 if i == 0 { core::ptr::null_mut() } else { ws }
19579}
19580
19581#[no_mangle]
19582pub 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 {
19583 if !label.is_null() { crate::write(2, label as *const core::ffi::c_void, crate::strlen(label)); }
19584 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
19585 if !text.is_null() { crate::write(2, text as *const core::ffi::c_void, crate::strlen(text)); }
19586 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
19587 0
19588}
19589
19590#[no_mangle]
19591pub unsafe extern "C" fn ftime(tp: *mut core::ffi::c_void) -> i32 {
19592 let mut tv: timeval = core::mem::zeroed();
19593 if gettimeofday(&mut tv, core::ptr::null_mut()) == 0 {
19594 let tb = tp as *mut Timeb;
19595 (*tb).time = tv.tv_sec;
19596 (*tb).millitm = (tv.tv_usec / 1000) as u16;
19597 (*tb).timezone = 0;
19598 (*tb).dstflag = 0;
19599 0
19600 } else {
19601 -1
19602 }
19603}
19604
19605#[no_mangle]
19606pub unsafe extern "C" fn getdents(fd: i32, dirp: *mut u8, count: usize) -> isize {
19607 <Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, dirp as i64, count as i64) as isize
19608}
19609
19610#[no_mangle]
19611pub unsafe extern "C" fn gethostid() -> i64 {
19612 let fd = crate::open(b"/proc/sys/kernel/random/boot_id\0".as_ptr() as *const core::ffi::c_char, 0, 0);
19614 if fd < 0 { return 0; }
19615 let mut buf: [u8; 64] = [0; 64];
19616 let n = crate::read(fd, buf.as_mut_ptr() as *mut core::ffi::c_void, 63);
19617 crate::close(fd);
19618 if n <= 0 { return 0; }
19619 buf[n as usize] = 0;
19620 crate::strtol(buf.as_ptr() as *const core::ffi::c_char, core::ptr::null_mut(), 16)
19621}
19622
19623#[no_mangle]
19624pub unsafe extern "C" fn getpass(prompt: *const core::ffi::c_char) -> *mut core::ffi::c_char {
19625 static mut BUF: [core::ffi::c_char; 128] = [0; 128];
19626 crate::write(2, prompt as *const core::ffi::c_void, crate::strlen(prompt));
19628 let n = crate::read(0, BUF.as_mut_ptr() as *mut core::ffi::c_void, 127);
19630 if n > 0 {
19631 let end = if BUF[(n - 1) as usize] == '\n' as c_char { n - 1 } else { n };
19632 BUF[end as usize] = 0;
19633 } else {
19634 BUF[0] = 0;
19635 }
19636 BUF.as_mut_ptr()
19637}
19638
19639#[no_mangle]
19640pub 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 {
19641 let s = *optionp;
19642 if s.is_null() { return -1; }
19643 let mut end = s;
19645 while *end != 0 && *end != ',' as c_char && *end != '=' as c_char { end = end.add(1); }
19646 let eq = *end == '=' as c_char;
19647 if eq { *end = 0; *valuep = end.add(1); }
19648 let mut i = 0;
19650 loop {
19651 let tok = *tokens.add(i);
19652 if tok.is_null() { break; }
19653 if crate::strcmp(s as *const u8, tok as *const u8) == 0 {
19654 while *end != 0 && *end != ',' as c_char { end = end.add(1); }
19656 if *end == ',' as c_char { end = end.add(1); }
19657 *optionp = end;
19658 return i as i32;
19659 }
19660 i += 1;
19661 }
19662 -1
19663}
19664
19665#[no_mangle]
19666pub unsafe extern "C" fn getw(f: *mut core::ffi::c_void) -> i32 {
19667 let c0 = getc(f as *mut FILE);
19668 if c0 < 0 { return -1; }
19669 let c1 = getc(f as *mut FILE);
19670 if c1 < 0 { return -1; }
19671 let c2 = getc(f as *mut FILE);
19672 if c2 < 0 { return -1; }
19673 let c3 = getc(f as *mut FILE);
19674 if c3 < 0 { return -1; }
19675 (c0 | (c1 << 8) | (c2 << 16) | (c3 << 24)) as i32
19676}
19677
19678#[no_mangle]
19679pub unsafe extern "C" fn getwc(f: *mut core::ffi::c_void) -> u32 {
19680 getc(f as *mut FILE) as u32
19681}
19682
19683#[no_mangle]
19684pub unsafe extern "C" fn init_module(module_image: *mut u8, len: usize, param_values: *const core::ffi::c_char) -> i32 {
19685 <Arch as Syscalls>::syscall3(SYS_INIT_MODULE, module_image as i64, len as i64, param_values as i64) as i32
19686}
19687
19688
19689
19690#[no_mangle]
19691pub unsafe extern "C" fn issetugid() -> i32 {
19692 let ruid = crate::getuid();
19693 let euid = crate::geteuid();
19694 let rgid = crate::getgid();
19695 let egid = crate::getegid();
19696 (ruid != euid || rgid != egid) as i32
19697}
19698
19699#[no_mangle]
19704pub unsafe extern "C" fn poll(fds: *mut core::ffi::c_void, nfds: u32, timeout: i32) -> i32 {
19705 #[cfg(target_arch = "x86_64")]
19706 { <Arch as Syscalls>::syscall3(SYS_POLL, fds as i64, nfds as i64, timeout as i64) as i32 }
19707 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
19708 {
19709 <Arch as Syscalls>::syscall5(SYS_PPOLL, fds as i64, nfds as i64, timeout as i64, 0, 0) as i32
19710 }
19711}
19712
19713#[no_mangle]
19714pub unsafe extern "C" fn ppoll(fds: *mut core::ffi::c_void, nfds: u32, timeout: *const core::ffi::c_void, sigmask: *const u64) -> i32 {
19715 <Arch as Syscalls>::syscall5(SYS_PPOLL, fds as i64, nfds as i64, timeout as i64, sigmask as i64, 8) as i32
19716}
19717
19718#[no_mangle]
19719pub 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 {
19720 <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
19721}
19722
19723#[no_mangle]
19732pub unsafe extern "C" fn quick_exit(status: i32) -> ! {
19733 crate::_exit(status)
19734}
19735
19736#[no_mangle]
19741pub unsafe extern "C" fn lstat(path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
19742 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, buf as i64, 0x100) as i32
19743}
19744
19745#[no_mangle]
19746pub unsafe extern "C" fn __xstat(_ver: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
19747 crate::stat(path, buf as *mut Stat)
19748}
19749
19750#[no_mangle]
19751pub unsafe extern "C" fn __lxstat(_ver: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
19752 crate::lstat(path, buf)
19753}
19754
19755#[no_mangle]
19756pub unsafe extern "C" fn __fxstat(_ver: i32, fd: i32, buf: *mut core::ffi::c_void) -> i32 {
19757 crate::fstat(fd, buf as *mut Stat)
19758}
19759
19760#[no_mangle]
19761pub unsafe extern "C" fn __fxstatat(_ver: i32, _dirfd: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void, _flags: i32) -> i32 {
19762 crate::stat(path, buf as *mut Stat)
19763}
19764
19765#[no_mangle]
19770pub unsafe extern "C" fn mempcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
19771 core::ptr::copy_nonoverlapping(src, dest, n);
19772 dest.add(n)
19773}
19774
19775#[no_mangle]
19780pub unsafe extern "C" fn mkostemp(template: *mut core::ffi::c_char, _flags: i32) -> i32 {
19781 mkstemp(template)
19782}
19783
19784#[no_mangle]
19785pub unsafe extern "C" fn mkstemps(template: *mut core::ffi::c_char, _suffixlen: i32) -> i32 {
19786 mkstemp(template)
19787}
19788
19789#[no_mangle]
19794pub unsafe extern "C" fn ptrace(request: i32, mut args: ...) -> i64 {
19795 let pid = args.next_arg::<i64>();
19796 let addr = args.next_arg::<i64>();
19797 let data = args.next_arg::<i64>();
19798 <Arch as Syscalls>::syscall4(sysno(101, 117), request as i64, pid, addr, data)
19799}
19800
19801#[no_mangle]
19802pub unsafe extern "C" fn personality(persona: u64) -> i64 {
19803 <Arch as Syscalls>::syscall1(sysno(135, 92), persona as i64)
19804}
19805
19806#[no_mangle]
19807pub unsafe extern "C" fn reboot(magic: i32, magic2: i32, cmd: u32, arg: *mut u8) -> i32 {
19808 <Arch as Syscalls>::syscall4(SYS_REBOOT, magic as i64, magic2 as i64, cmd as i64, arg as i64) as i32
19809}
19810
19811#[no_mangle]
19812pub unsafe extern "C" fn pivot_root(new_root: *const core::ffi::c_char, put_old: *const core::ffi::c_char) -> i32 {
19813 <Arch as Syscalls>::syscall2(SYS_PIVOT_ROOT, new_root as i64, put_old as i64) as i32
19814}
19815
19816#[no_mangle]
19817pub 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 {
19818 <Arch as Syscalls>::syscall5(SYS_MOUNT, source as i64, target as i64, filesystemtype as i64, mountflags as i64, data as i64) as i32
19819}
19820
19821#[no_mangle]
19822pub unsafe extern "C" fn umount(target: *const core::ffi::c_char) -> i32 {
19823 <Arch as Syscalls>::syscall2(SYS_UMOUNT2, target as i64, 0) as i32
19824}
19825
19826#[no_mangle]
19827pub unsafe extern "C" fn umount2(target: *const core::ffi::c_char, flags: i32) -> i32 {
19828 <Arch as Syscalls>::syscall2(SYS_UMOUNT2, target as i64, flags as i64) as i32
19829}
19830
19831#[no_mangle]
19841pub unsafe extern "C" fn psiginfo(_pinfo: *const core::ffi::c_void, s: *const core::ffi::c_char) {
19842 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
19843 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
19844}
19845
19846#[no_mangle]
19847pub unsafe extern "C" fn psignal(sig: i32, s: *const core::ffi::c_char) {
19848 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
19849 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
19850 crate::write(2, strsignal(sig) as *const core::ffi::c_void, crate::strlen(strsignal(sig)));
19851 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
19852}
19853
19854#[no_mangle]
19855pub unsafe extern "C" fn strsignal(sig: c_int) -> *const c_char {
19856 static NAMES: [&[u8]; 32] = [
19857 b"Unknown signal\0",
19858 b"Hangup\0",
19859 b"Interrupt\0",
19860 b"Quit\0",
19861 b"Illegal instruction\0",
19862 b"Trace/breakpoint trap\0",
19863 b"Aborted\0",
19864 b"Bus error\0",
19865 b"Floating point exception\0",
19866 b"Killed\0",
19867 b"User defined signal 1\0",
19868 b"Segmentation fault\0",
19869 b"User defined signal 2\0",
19870 b"Broken pipe\0",
19871 b"Alarm clock\0",
19872 b"Terminated\0",
19873 b"Stack fault\0",
19874 b"Child process status\0",
19875 b"Continued\0",
19876 b"Stopped (signal)\0",
19877 b"Stopped\0",
19878 b"Stopped (tty input)\0",
19879 b"Stopped (tty output)\0",
19880 b"Urgent I/O condition\0",
19881 b"CPU time limit exceeded\0",
19882 b"File size limit exceeded\0",
19883 b"Virtual timer expired\0",
19884 b"Profiling timer expired\0",
19885 b"Window changed\0",
19886 b"I/O possible\0",
19887 b"Power failure\0",
19888 b"Bad system call\0",
19889 ];
19890 static mut RT_BUF: [c_char; 32] = [0; 32];
19891 if sig > 0 && sig < 32 {
19892 return NAMES[sig as usize].as_ptr() as *const c_char;
19893 }
19894 if sig >= 32 && sig < 65 {
19895 let mut o = 0usize;
19896 for &c in b"Real-time signal \0" {
19897 if c == 0 { break; }
19898 RT_BUF[o] = c as c_char;
19899 o += 1;
19900 }
19901 let mut v = (sig - 32) as u32;
19902 let mut digits = [0u8; 10];
19903 let mut d = 0usize;
19904 if v == 0 { digits[0] = b'0'; d = 1; }
19905 while v > 0 { digits[d] = b'0' + (v % 10) as u8; v /= 10; d += 1; }
19906 while d > 0 { d -= 1; RT_BUF[o] = digits[d] as c_char; o += 1; }
19907 RT_BUF[o] = 0;
19908 return RT_BUF.as_ptr();
19909 }
19910 b"Unknown signal\0".as_ptr() as *const c_char
19911}
19912
19913#[no_mangle]
19914pub unsafe extern "C" fn __strerror_l(errnum: i32, _loc: *mut core::ffi::c_void) -> *const core::ffi::c_char {
19915 crate::strerror(errnum)
19916}
19917
19918#[no_mangle]
19923pub unsafe extern "C" fn preadv(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64) -> isize {
19924 <Arch as Syscalls>::syscall4(sysno(295, 69), fd as i64, iov as i64, iovcnt as i64, offset) as isize
19925}
19926
19927#[no_mangle]
19928pub unsafe extern "C" fn pwritev(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64) -> isize {
19929 <Arch as Syscalls>::syscall4(sysno(296, 70), fd as i64, iov as i64, iovcnt as i64, offset) as isize
19930}
19931
19932#[no_mangle]
19933pub unsafe extern "C" fn preadv2(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64, flags: u32) -> isize {
19934 <Arch as Syscalls>::syscall5(sysno(327, 286), fd as i64, iov as i64, iovcnt as i64, offset, flags as i64) as isize
19935}
19936
19937#[no_mangle]
19938pub unsafe extern "C" fn pwritev2(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64, flags: u32) -> isize {
19939 <Arch as Syscalls>::syscall5(sysno(328, 287), fd as i64, iov as i64, iovcnt as i64, offset, flags as i64) as isize
19940}
19941
19942#[no_mangle]
19947pub unsafe extern "C" fn nice(inc: i32) -> i32 {
19948 let r = <Arch as Syscalls>::syscall2(SYS_GETPRIORITY, 0, 0);
19949 if r < 0 { return -1; }
19950 <Arch as Syscalls>::syscall2(SYS_SETPRIORITY, 0, r + inc as i64) as i32
19951}
19952
19953#[no_mangle]
19958pub unsafe extern "C" fn l64a(value: i64) -> *mut core::ffi::c_char {
19959 static mut BUF: [core::ffi::c_char; 7] = [0; 7];
19960 let mut v = value as u64;
19961 let mut i = 0;
19962 while v > 0 && i < 6 {
19963 let c = (v & 0x3f) as u8;
19964 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;
19965 v >>= 6;
19966 i += 1;
19967 }
19968 BUF[i] = 0;
19969 BUF.as_mut_ptr()
19970}
19971
19972#[no_mangle]
19973pub unsafe extern "C" fn lchmod(path: *const core::ffi::c_char, mode: u32) -> i32 {
19974 <Arch as Syscalls>::syscall4(SYS_FCHMODAT, AT_FDCWD as i64, path as i64, mode as i64, 0x100) as i32
19975}
19976
19977#[no_mangle]
19978pub unsafe extern "C" fn lutimes(filename: *const core::ffi::c_char, times: *const core::ffi::c_void) -> i32 {
19979 utimensat(AT_FDCWD, filename, times as *const timespec, 0x100)
19980}
19981
19982#[no_mangle]
19983pub unsafe extern "C" fn mknod(pathname: *const core::ffi::c_char, mode: u32, dev: u64) -> i32 {
19984 #[cfg(target_arch = "x86_64")]
19985 { <Arch as Syscalls>::syscall3(SYS_MKNOD, pathname as i64, mode as i64, dev as i64) as i32 }
19986 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
19987 {
19988 <Arch as Syscalls>::syscall4(SYS_MKNODAT, AT_FDCWD as i64, pathname as i64, mode as i64, dev as i64) as i32
19989 }
19990}
19991
19992#[no_mangle]
19993pub unsafe extern "C" fn memfd_create(name: *const core::ffi::c_char, flags: u32) -> i32 {
19994 <Arch as Syscalls>::syscall2(sysno(319, 279), name as i64, flags as i64) as i32
19995}
19996
19997#[no_mangle]
19998pub unsafe extern "C" fn mlock2(addr: *const core::ffi::c_void, len: usize, flags: u32) -> i32 {
19999 <Arch as Syscalls>::syscall3(sysno(325, 284), addr as i64, len as i64, flags as i64) as i32
20000}
20001
20002
20003
20004#[no_mangle]
20005pub unsafe extern "C" fn remap_file_pages(addr: *mut core::ffi::c_void, size: usize, prot: i32, pgoff: usize, flags: u32) -> i32 {
20006 <Arch as Syscalls>::syscall5(sysno(216, 234), addr as i64, size as i64, prot as i64, pgoff as i64, flags as i64) as i32
20007}
20008
20009#[no_mangle]
20014pub unsafe extern "C" fn nan(_tagp: *const core::ffi::c_char) -> f64 {
20015 f64::NAN
20016}
20017
20018#[no_mangle]
20019pub unsafe extern "C" fn nanf(_tagp: *const core::ffi::c_char) -> f32 {
20020 f32::NAN
20021}
20022
20023#[no_mangle]
20028pub unsafe extern "C" fn __lgammal_r(x: f64, signgamp: *mut i32) -> f64 {
20029 *signgamp = 1;
20030 lgamma(x)
20031}
20032
20033#[no_mangle]
20034pub unsafe extern "C" fn __libc_current_sigrtmax() -> i32 {
20035 64
20036}
20037
20038#[no_mangle]
20039pub unsafe extern "C" fn _longjmp(env: *mut core::ffi::c_void, val: i32) {
20040 crate::longjmp(env as *mut u64, val)
20041}
20042
20043#[no_mangle]
20044pub unsafe extern "C" fn __newlocale(_mask: i32, _name: *const core::ffi::c_char, base: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
20045 base
20046}
20047
20048#[no_mangle]
20049pub unsafe extern "C" fn __nl_langinfo(_item: i32) -> *mut core::ffi::c_char {
20050 b"\0".as_ptr() as *mut core::ffi::c_char
20051}
20052
20053#[no_mangle]
20054pub unsafe extern "C" fn __nl_langinfo_l(_item: i32, _loc: *mut core::ffi::c_void) -> *mut core::ffi::c_char {
20055 b"\0".as_ptr() as *mut core::ffi::c_char
20056}
20057
20058#[no_mangle]
20059pub unsafe extern "C" fn ns_get16(cp: *const u8) -> u16 {
20060 ((*cp.add(0) as u16) << 8) | *cp.add(1) as u16
20061}
20062
20063#[no_mangle]
20064pub unsafe extern "C" fn ns_get32(cp: *const u8) -> u32 {
20065 ((*cp.add(0) as u32) << 24) | ((*cp.add(1) as u32) << 16) | ((*cp.add(2) as u32) << 8) | *cp.add(3) as u32
20066}
20067
20068#[no_mangle]
20069pub unsafe extern "C" fn ns_put16(s: u16, dst: *mut u8) {
20070 *dst.add(0) = (s >> 8) as u8;
20071 *dst.add(1) = (s & 0xff) as u8;
20072}
20073
20074#[no_mangle]
20075pub unsafe extern "C" fn ns_put32(l: u32, dst: *mut u8) {
20076 *dst.add(0) = (l >> 24) as u8;
20077 *dst.add(1) = ((l >> 16) & 0xff) as u8;
20078 *dst.add(2) = ((l >> 8) & 0xff) as u8;
20079 *dst.add(3) = (l & 0xff) as u8;
20080}
20081
20082#[no_mangle]
20083pub unsafe extern "C" fn posix_close(fd: i32) -> i32 {
20084 crate::close(fd)
20085}
20086
20087#[no_mangle]
20088pub unsafe extern "C" fn posix_openpt(flags: i32) -> i32 {
20089 crate::open(b"/dev/ptmx\0".as_ptr() as *const core::ffi::c_char, flags, 0)
20090}
20091
20092#[no_mangle]
20093pub unsafe extern "C" fn putw(w: i32, f: *mut core::ffi::c_void) {
20094 putc((w & 0xff) as i32, f as *mut FILE);
20095 putc(((w >> 8) & 0xff) as i32, f as *mut FILE);
20096 putc(((w >> 16) & 0xff) as i32, f as *mut FILE);
20097 putc(((w >> 24) & 0xff) as i32, f as *mut FILE);
20098}
20099
20100
20101
20102#[no_mangle]
20103pub unsafe extern "C" fn rand_r(seedp: *mut u32) -> i32 {
20104 let seed = (*seedp).wrapping_mul(1103515245).wrapping_add(12345);
20105 *seedp = seed;
20106 ((seed >> 16) & 0x7fff) as i32
20107}
20108
20109#[no_mangle]
20110pub unsafe extern "C" fn reallocarray(ptr: *mut core::ffi::c_void, nmemb: usize, size: usize) -> *mut core::ffi::c_void {
20111 crate::realloc(ptr, nmemb.wrapping_mul(size))
20112}
20113
20114#[no_mangle]
20115pub unsafe extern "C" fn __res_state() -> *mut core::ffi::c_void {
20116 static mut STATE: [u8; 512] = [0; 512];
20117 STATE.as_mut_ptr() as *mut core::ffi::c_void
20118}
20119
20120#[no_mangle]
20121pub unsafe extern "C" fn sbrk(increment: isize) -> *mut u8 {
20122 let cur = <Arch as Syscalls>::syscall1(sysno(12, 214), 0);
20123 if increment == 0 { return cur as *mut u8; }
20124 let new = cur + increment as i64;
20125 let r = <Arch as Syscalls>::syscall1(sysno(12, 214), new);
20126 if r < 0 { return -1isize as usize as *mut u8; }
20127 cur as *mut u8
20128}
20129
20130#[no_mangle]
20131pub unsafe extern "C" fn scalb(x: f64, exp: f64) -> f64 {
20132 if x.is_nan() || exp.is_nan() { return x * exp; }
20133 if !exp.is_finite() {
20134 let r = if exp > 0.0 { x * exp } else { x / (-exp) };
20135 if r.is_nan() && !x.is_nan() {
20136 feraiseexcept(FE_INVALID);
20137 }
20138 return r;
20139 }
20140 if libm::rint(exp) != exp {
20141 return __math_invalid(exp);
20142 }
20143 if exp > 65000.0 { return libm::scalbn(x, 65000); }
20144 if -exp > 65000.0 { return libm::scalbn(x, -65000); }
20145 libm::scalbn(x, exp as i32)
20146}
20147
20148#[no_mangle]
20149pub unsafe extern "C" fn scalbf(x: f32, exp: f32) -> f32 {
20150 if x.is_nan() || exp.is_nan() { return x * exp; }
20151 if !exp.is_finite() {
20152 let r = if exp > 0.0 { x * exp } else { x / (-exp) };
20153 if r.is_nan() && !x.is_nan() {
20154 feraiseexcept(FE_INVALID);
20155 }
20156 return r;
20157 }
20158 if libm::rintf(exp) != exp {
20159 return __math_invalidf(exp);
20160 }
20161 if exp > 65000.0 { return libm::scalbnf(x, 65000); }
20162 if -exp > 65000.0 { return libm::scalbnf(x, -65000); }
20163 libm::scalbnf(x, exp as i32)
20164}
20165
20166#[no_mangle]
20167pub unsafe extern "C" fn __sched_cpucount(setsize: usize, setp: *const u8) -> i32 {
20168 let mut count = 0;
20169 let mut i = 0;
20170 while i < setsize * 8 {
20171 if (*setp.add(i / 8) >> (i % 8)) & 1 != 0 { count += 1; }
20172 i += 1;
20173 }
20174 count
20175}
20176
20177
20178
20179#[no_mangle]
20180pub unsafe extern "C" fn select(nfds: i32, readfds: *mut u8, writefds: *mut u8, exceptfds: *mut u8, timeout: *mut core::ffi::c_void) -> i32 {
20181 <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
20182}
20183
20184
20185
20186#[no_mangle]
20187pub unsafe extern "C" fn sendfile(out_fd: i32, in_fd: i32, offset: *mut i64, count: usize) -> isize {
20188 <Arch as Syscalls>::syscall4(sysno(40, 71), out_fd as i64, in_fd as i64, offset as i64, count as i64) as isize
20189}
20190
20191
20192
20193
20194
20195#[no_mangle]
20196pub unsafe extern "C" fn __setjmp(env: *mut core::ffi::c_void) -> i32 {
20197 crate::setjmp(env as *mut u64)
20198}
20199
20200#[no_mangle]
20201pub unsafe extern "C" fn _setjmp(env: *mut core::ffi::c_void) -> i32 {
20202 crate::setjmp(env as *mut u64)
20203}
20204
20205#[no_mangle]
20206pub unsafe extern "C" fn setlinebuf(stream: *mut core::ffi::c_void) {
20207 setvbuf(stream as *mut FILE, core::ptr::null_mut(), 1, 0);
20208}
20209
20210
20211
20212
20213
20214
20215
20216
20217
20218
20219
20220
20221
20222
20223
20224#[no_mangle]
20225pub unsafe extern "C" fn significand(x: f64) -> f64 {
20226 let bits = x.to_bits();
20227 let exp = ((bits >> 52) & 0x7ff) as i32;
20228 if exp == 0 || exp == 0x7ff { return x; }
20229 f64::from_bits((bits & 0x000fffffffffffff) | (1023u64 << 52))
20230}
20231
20232#[no_mangle]
20233pub unsafe extern "C" fn significandf(x: f32) -> f32 {
20234 let bits = x.to_bits();
20235 let exp = ((bits >> 23) & 0xff) as i32;
20236 if exp == 0 || exp == 0xff { return x; }
20237 f32::from_bits((bits & 0x007fffff) | (127u32 << 23))
20238}
20239
20240
20241
20242
20243
20244#[no_mangle]
20245pub unsafe extern "C" fn sigset(_sig: i32, handler: Option<unsafe extern "C" fn(i32)>) -> Option<unsafe extern "C" fn(i32)> {
20246 handler
20247}
20248
20249#[no_mangle]
20250pub unsafe extern "C" fn sincos(x: f64, sin: *mut f64, cos: *mut f64) {
20251 *sin = libm::sin(x);
20252 *cos = libm::cos(x);
20253}
20254
20255#[no_mangle]
20256pub unsafe extern "C" fn sincosf(x: f32, sin: *mut f32, cos: *mut f32) {
20257 *sin = libm::sinf(x);
20258 *cos = libm::cosf(x);
20259}
20260
20261
20262
20263
20264
20265
20266
20267
20268
20269unsafe fn nd_ascii_lower(c: c_char) -> c_int {
20270 let b = c as u8;
20271 if b >= b'A' && b <= b'Z' { (b + 32) as c_int } else { b as c_int }
20272}
20273
20274unsafe fn nd_strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
20275 let mut i = 0usize;
20276 while i < n {
20277 let c1 = nd_ascii_lower(*s1.add(i));
20278 let c2 = nd_ascii_lower(*s2.add(i));
20279 if c1 != c2 || c1 == 0 { return c1 - c2; }
20280 i += 1;
20281 }
20282 0
20283}
20284
20285#[no_mangle]
20286pub unsafe extern "C" fn strcasecmp(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char) -> i32 {
20287 nd_strncasecmp(s1, s2, usize::MAX)
20288}
20289
20290#[no_mangle]
20291pub 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 {
20292 nd_strncasecmp(s1, s2, usize::MAX)
20293}
20294
20295#[no_mangle]
20296pub unsafe extern "C" fn strcasestr(haystack: *const core::ffi::c_char, needle: *const core::ffi::c_char) -> *mut core::ffi::c_char {
20297 let nlen = crate::strlen(needle);
20298 if nlen == 0 { return haystack as *mut core::ffi::c_char; }
20299 let mut i = 0;
20300 loop {
20301 let h = haystack.add(i);
20302 if *h == 0 { return core::ptr::null_mut(); }
20303 if crate::strncasecmp(h, needle, nlen) == 0 { return h as *mut core::ffi::c_char; }
20304 i += 1;
20305 }
20306}
20307
20308#[no_mangle]
20309pub 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 {
20310 crate::strcmp(s1 as *const u8, s2 as *const u8)
20311}
20312
20313#[no_mangle]
20314pub unsafe extern "C" fn strncasecmp(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char, n: usize) -> i32 {
20315 nd_strncasecmp(s1, s2, n)
20316}
20317
20318#[no_mangle]
20319pub 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 {
20320 nd_strncasecmp(s1, s2, n)
20321}
20322
20323#[no_mangle]
20324pub unsafe extern "C" fn strsep(stringp: *mut *mut core::ffi::c_char, delim: *const core::ffi::c_char) -> *mut core::ffi::c_char {
20325 let s = *stringp;
20326 if s.is_null() { return core::ptr::null_mut(); }
20327 let mut p = s;
20328 while *p != 0 {
20329 let mut d = delim;
20330 while *d != 0 {
20331 if *p == *d { *p = 0; *stringp = p.add(1); return s; }
20332 d = d.add(1);
20333 }
20334 p = p.add(1);
20335 }
20336 *stringp = core::ptr::null_mut();
20337 s
20338}
20339
20340#[no_mangle]
20341pub unsafe extern "C" fn strtoimax(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, base: i32) -> i64 {
20342 crate::strtol(nptr, endptr, base)
20343}
20344
20345#[no_mangle]
20346pub 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 {
20347 let mut s = if s.is_null() { *saveptr } else { s };
20348 if s.is_null() { return core::ptr::null_mut(); }
20349 while *s != 0 {
20351 let mut d = delim;
20352 let mut found = false;
20353 while *d != 0 {
20354 if *s == *d { found = true; break; }
20355 d = d.add(1);
20356 }
20357 if !found { break; }
20358 s = s.add(1);
20359 }
20360 if *s == 0 { *saveptr = s; return core::ptr::null_mut(); }
20361 let start = s;
20362 while *s != 0 {
20364 let mut d = delim;
20365 while *d != 0 {
20366 if *s == *d { *s = 0; *saveptr = s.add(1); return start; }
20367 d = d.add(1);
20368 }
20369 s = s.add(1);
20370 }
20371 *saveptr = s;
20372 start
20373}
20374
20375#[no_mangle]
20376pub unsafe extern "C" fn strtoumax(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, base: i32) -> u64 {
20377 crate::strtoul(nptr, endptr, base) as u64
20378}
20379
20380#[no_mangle]
20381pub 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 {
20382 crate::strlcpy(dest as *mut u8, src as *const u8, n)
20383}
20384
20385#[no_mangle]
20386pub unsafe extern "C" fn swab(src: *const u8, dest: *mut u8, nbytes: isize) {
20387 let mut i = 0;
20388 while i + 1 < nbytes {
20389 let a = *src.add(i as usize);
20390 let b = *src.add(i as usize + 1);
20391 *dest.add(i as usize) = b;
20392 *dest.add(i as usize + 1) = a;
20393 i += 2;
20394 }
20395}
20396
20397
20398
20399
20400
20401
20402
20403
20404
20405
20406
20407#[no_mangle]
20408pub unsafe extern "C" fn __tls_get_addr(ti: *mut core::ffi::c_void) -> *mut u8 {
20409 let p = ti as *mut usize;
20411 let _module_id = *p;
20412 let offset = *p.add(1);
20413 static mut TLS_BUF: [u8; 4096] = [0; 4096];
20415 TLS_BUF.as_mut_ptr().add(offset)
20416}
20417
20418#[no_mangle]
20419pub unsafe extern "C" fn __tolower_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20420 if c >= 'A' as i32 && c <= 'Z' as i32 { c + 32 } else { c }
20421}
20422
20423#[no_mangle]
20424pub unsafe extern "C" fn __toupper_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20425 if c >= 'a' as i32 && c <= 'z' as i32 { c - 32 } else { c }
20426}
20427
20428#[no_mangle]
20429pub unsafe extern "C" fn ulimit(cmd: c_int, mut args: ...) -> c_long {
20430 let mut rl: Rlimit = core::mem::zeroed();
20431 if getrlimit(RLIMIT_FSIZE, &mut rl) != 0 { return -1; }
20432 if cmd == 2 {
20433 let val = args.next_arg::<c_long>();
20434 rl.rlim_cur = 512u64.wrapping_mul(val as u64);
20435 if setrlimit(RLIMIT_FSIZE, &rl) != 0 { return -1; }
20436 }
20437 (rl.rlim_cur / 512) as c_long
20438}
20439
20440#[repr(C)]
20441struct UtsName {
20442 sysname: [u8; 65],
20443 nodename: [u8; 65],
20444 release: [u8; 65],
20445 version: [u8; 65],
20446 machine: [u8; 65],
20447 domainname: [u8; 65],
20448}
20449
20450#[no_mangle]
20451pub unsafe extern "C" fn uname(buf: *mut c_void) -> c_int {
20452 if buf.is_null() { ERRNO = EINVAL; return -1; }
20453 let mut uts: UtsName = core::mem::zeroed();
20454 let r = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
20455 if r < 0 { ERRNO = (-r) as c_int; return -1; }
20456 core::ptr::copy_nonoverlapping(&uts as *const UtsName as *const u8, buf as *mut u8, core::mem::size_of::<UtsName>());
20457 0
20458}
20459
20460#[no_mangle]
20461pub unsafe extern "C" fn unshare(flags: i32) -> i32 {
20462 let r = <Arch as Syscalls>::syscall1(SYS_UNSHARE, flags as i64);
20463 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
20464}
20465
20466#[no_mangle]
20467pub unsafe extern "C" fn updwtmpx(wtmpx_file: *const core::ffi::c_char, utx: *const core::ffi::c_void) {
20468 updwtmp(wtmpx_file, utx)
20469}
20470
20471#[no_mangle]
20472pub unsafe extern "C" fn __uselocale(loc: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
20473 loc
20474}
20475
20476#[repr(C)]
20477pub struct Utimbuf { actime: i64, modtime: i64 }
20478
20479#[no_mangle]
20480pub unsafe extern "C" fn utime(filename: *const c_char, times: *const Utimbuf) -> c_int {
20481 if times.is_null() {
20482 return utimensat(AT_FDCWD, filename, core::ptr::null(), 0);
20483 }
20484 let ts = [
20485 timespec { tv_sec: (*times).actime, tv_nsec: 0 },
20486 timespec { tv_sec: (*times).modtime, tv_nsec: 0 },
20487 ];
20488 utimensat(AT_FDCWD, filename, ts.as_ptr(), 0)
20489}
20490
20491#[no_mangle]
20492pub unsafe extern "C" fn vhangup() -> c_int {
20493 let r = <Arch as Syscalls>::syscall0(SYS_VHANGUP);
20494 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
20495}
20496
20497#[no_mangle]
20498pub unsafe extern "C" fn vmsplice(fd: i32, iov: *const c_void, nr_segs: usize, flags: u32) -> isize {
20499 let r = <Arch as Syscalls>::syscall4(SYS_VMSPLICE, fd as i64, iov as i64, nr_segs as i64, flags as i64);
20500 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
20501}
20502
20503
20504
20505#[no_mangle]
20506pub unsafe extern "C" fn wait4(pid: i32, wstatus: *mut i32, options: i32, rusage: *mut core::ffi::c_void) -> i32 {
20507 <Arch as Syscalls>::syscall4(SYS_WAIT4, pid as i64, wstatus as i64, options as i64, rusage as i64) as i32
20508}
20509
20510#[no_mangle]
20511pub unsafe extern "C" fn waitid(idtype: i32, id: u32, infop: *mut core::ffi::c_void, options: i32) -> i32 {
20512 <Arch as Syscalls>::syscall4(sysno(247, 95), idtype as i64, id as i64, infop as i64, options as i64) as i32
20513}
20514
20515#[no_mangle]
20516pub unsafe extern "C" fn __wcscoll_l(s1: *const u32, s2: *const u32, _loc: *mut core::ffi::c_void) -> i32 {
20517 crate::wcscmp(s1 as *const i32, s2 as *const i32)
20518}
20519
20520#[no_mangle]
20521pub unsafe extern "C" fn __wcsxfrm_l(dest: *mut u32, src: *const u32, n: usize, _loc: *mut core::ffi::c_void) -> usize {
20522 crate::wcscpy(dest as *mut i32, src as *const i32);
20523 n
20524}
20525
20526#[no_mangle]
20527pub unsafe extern "C" fn wcwidth(c: u32) -> i32 {
20528 if c == 0 { return 0; }
20529 if c < 32 || (c >= 0x7f && c < 0xa0) { return -1; }
20530 1
20531}
20532
20533
20534
20535
20536
20537#[no_mangle]
20544pub 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 {
20545 crate::strtod(nptr, endptr)
20546}
20547
20548#[no_mangle]
20549pub 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 {
20550 crate::strtof(nptr, endptr)
20551}
20552
20553#[no_mangle]
20554pub 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 {
20555 crate::strtod(nptr, endptr)
20556}
20557
20558#[repr(C)]
20563struct linux_dirent64 {
20564 d_ino: u64,
20565 d_off: i64,
20566 d_reclen: u16,
20567 d_type: u8,
20568 d_name: [u8; 0], }
20570
20571static mut DIR_BUF: [u8; 1024] = [0; 1024];
20572static mut DIR_FD: i32 = -1;
20573static mut DIR_POS: usize = 0;
20574static mut DIR_LEN: usize = 0;
20575
20576#[no_mangle]
20577pub unsafe extern "C" fn opendir(dirname: *const core::ffi::c_char) -> *mut core::ffi::c_void {
20578 let fd = openat(AT_FDCWD, dirname, O_DIRECTORY, 0); if fd < 0 { return core::ptr::null_mut(); }
20580 DIR_FD = fd;
20581 DIR_POS = 0;
20582 DIR_LEN = 0;
20583 &DIR_FD as *const i32 as *mut core::ffi::c_void
20584}
20585
20586#[no_mangle]
20587pub unsafe extern "C" fn closedir(dirp: *mut core::ffi::c_void) -> i32 {
20588 if dirp.is_null() { return -1; }
20589 let fd = *(dirp as *const i32);
20590 crate::close(fd)
20591}
20592
20593#[no_mangle]
20594pub unsafe extern "C" fn readdir(dirp: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
20595 if dirp.is_null() { return core::ptr::null_mut(); }
20596 let fd = *(dirp as *const i32);
20597
20598 loop {
20599 if DIR_POS >= DIR_LEN {
20600 let nread = <Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, DIR_BUF.as_mut_ptr() as i64, 1024) as isize;
20601 if nread <= 0 { return core::ptr::null_mut(); }
20602 DIR_LEN = nread as usize;
20603 DIR_POS = 0;
20604 }
20605
20606 let ent = DIR_BUF.as_ptr().add(DIR_POS) as *const linux_dirent64;
20607 let ent_ref = &*ent;
20608 DIR_POS += ent_ref.d_reclen as usize;
20609
20610 return ent as *mut core::ffi::c_void;
20612 }
20613}
20614
20615#[no_mangle]
20616pub 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 {
20617 let ent = readdir(dirp);
20618 if ent.is_null() {
20619 *result = core::ptr::null_mut();
20620 } else {
20621 *result = ent;
20622 }
20623 0
20624}
20625
20626#[no_mangle]
20627pub unsafe extern "C" fn seekdir(dirp: *mut core::ffi::c_void, loc: i64) {
20628 if dirp.is_null() { return; }
20629 let fd = *(dirp as *const i32);
20630 <Arch as Syscalls>::syscall3(SYS_LSEEK, fd as i64, loc, 0);
20631}
20632
20633#[no_mangle]
20634pub unsafe extern "C" fn telldir(_dirp: *mut core::ffi::c_void) -> i64 {
20635 DIR_POS as i64
20636}
20637
20638#[no_mangle]
20639pub unsafe extern "C" fn rewinddir(_dirp: *mut core::ffi::c_void) {
20640 DIR_POS = 0;
20641 DIR_LEN = 0;
20642}
20643
20644#[no_mangle]
20645pub unsafe extern "C" fn dirfd(dirp: *mut core::ffi::c_void) -> i32 {
20646 if dirp.is_null() { return -1; }
20647 unsafe { *(dirp as *const i32) }
20648}
20649
20650#[no_mangle]
20655pub unsafe extern "C" fn mprotect(addr: *mut u8, len: usize, prot: i32) -> i32 {
20656 <Arch as Syscalls>::syscall3(SYS_MPROTECT, addr as i64, len as i64, prot as i64) as i32
20657}
20658
20659#[no_mangle]
20660pub unsafe extern "C" fn msync(addr: *mut u8, len: usize, flags: i32) -> i32 {
20661 <Arch as Syscalls>::syscall3(sysno(26, 227), addr as i64, len as i64, flags as i64) as i32
20662}
20663
20664#[no_mangle]
20665pub unsafe extern "C" fn mlock(addr: *const u8, len: usize) -> i32 {
20666 <Arch as Syscalls>::syscall2(sysno(149, 228), addr as i64, len as i64) as i32
20667}
20668
20669#[no_mangle]
20670pub unsafe extern "C" fn munlock(addr: *const u8, len: usize) -> i32 {
20671 <Arch as Syscalls>::syscall2(sysno(150, 229), addr as i64, len as i64) as i32
20672}
20673
20674#[no_mangle]
20675pub unsafe extern "C" fn mlockall(flags: i32) -> i32 {
20676 <Arch as Syscalls>::syscall1(sysno(151, 230), flags as i64) as i32
20677}
20678
20679#[no_mangle]
20680pub unsafe extern "C" fn munlockall() -> i32 {
20681 <Arch as Syscalls>::syscall0(sysno(152, 231)) as i32
20682}
20683
20684#[no_mangle]
20685pub unsafe extern "C" fn madvise(addr: *mut u8, len: usize, advice: i32) -> i32 {
20686 <Arch as Syscalls>::syscall3(sysno(28, 233), addr as i64, len as i64, advice as i64) as i32
20687}
20688
20689#[no_mangle]
20690pub unsafe extern "C" fn mincore(addr: *mut u8, len: usize, vec: *mut u8) -> i32 {
20691 <Arch as Syscalls>::syscall3(sysno(27, 232), addr as i64, len as i64, vec as i64) as i32
20692}
20693
20694#[no_mangle]
20701pub unsafe extern "C" fn drem(x: f64, y: f64) -> f64 {
20702 remainder(x, y)
20703}
20704
20705#[no_mangle]
20706pub unsafe extern "C" fn dremf(x: f32, y: f32) -> f32 {
20707 remainderf(x, y)
20708}
20709
20710#[no_mangle]
20711pub unsafe extern "C" fn pow10(x: f64) -> f64 {
20712 libm::pow(10.0, x)
20713}
20714
20715#[no_mangle]
20716pub unsafe extern "C" fn pow10f(x: f32) -> f32 {
20717 libm::powf(10.0, x)
20718}
20719
20720#[no_mangle]
20721pub unsafe extern "C" fn pow10l(x: f64) -> f64 {
20722 libm::pow(10.0, x)
20723}
20724
20725#[no_mangle]
20726pub unsafe extern "C" fn isless(x: f64, y: f64) -> i32 {
20727 if x.is_nan() || y.is_nan() { 0 } else { (x < y) as i32 }
20728}
20729
20730#[no_mangle]
20731pub unsafe extern "C" fn islessf(x: f32, y: f32) -> i32 {
20732 if x.is_nan() || y.is_nan() { 0 } else { (x < y) as i32 }
20733}
20734
20735#[no_mangle]
20736pub unsafe extern "C" fn lgamma_r(x: f64, signgamp: *mut i32) -> f64 {
20737 if x.is_nan() {
20738 if !signgamp.is_null() { *signgamp = 1; }
20739 return x;
20740 }
20741 if x == 0.0 {
20742 if !signgamp.is_null() { *signgamp = if x.is_sign_negative() { -1 } else { 1 }; }
20743 feraiseexcept(FE_DIVBYZERO);
20744 return f64::INFINITY;
20745 }
20746 let (r, sign) = libm::lgamma_r(x);
20747 if !signgamp.is_null() { *signgamp = sign; }
20748 r
20749}
20750
20751#[no_mangle]
20752pub unsafe extern "C" fn lgammaf_r(x: f32, signgamp: *mut i32) -> f32 {
20753 if x.is_nan() {
20754 if !signgamp.is_null() { *signgamp = 1; }
20755 return x;
20756 }
20757 if x == 0.0 {
20758 if !signgamp.is_null() { *signgamp = if x.is_sign_negative() { -1 } else { 1 }; }
20759 feraiseexcept(FE_DIVBYZERO);
20760 return f32::INFINITY;
20761 }
20762 let (r, sign) = libm::lgammaf_r(x);
20763 if !signgamp.is_null() { *signgamp = sign; }
20764 r
20765}
20766
20767#[no_mangle]
20768pub unsafe extern "C" fn lgammal_r(x: f64, signgamp: *mut i32) -> f64 {
20769 lgamma_r(x, signgamp)
20770}
20771
20772#[no_mangle]
20777pub unsafe extern "C" fn islessequal(x: f64, y: f64) -> i32 {
20778 if x.is_nan() || y.is_nan() { 0 } else { (x <= y) as i32 }
20779}
20780
20781#[no_mangle]
20782pub unsafe extern "C" fn islessequalf(x: f32, y: f32) -> i32 {
20783 if x.is_nan() || y.is_nan() { 0 } else { (x <= y) as i32 }
20784}
20785
20786#[no_mangle]
20787pub unsafe extern "C" fn islessgreater(x: f64, y: f64) -> i32 {
20788 if x.is_nan() || y.is_nan() { 0 } else { (x < y || x > y) as i32 }
20789}
20790
20791#[no_mangle]
20792pub unsafe extern "C" fn islessgreaterf(x: f32, y: f32) -> i32 {
20793 if x.is_nan() || y.is_nan() { 0 } else { (x < y || x > y) as i32 }
20794}
20795
20796#[no_mangle]
20797pub unsafe extern "C" fn isgreater(x: f64, y: f64) -> i32 {
20798 if x.is_nan() || y.is_nan() { 0 } else { (x > y) as i32 }
20799}
20800
20801#[no_mangle]
20802pub unsafe extern "C" fn isgreaterf(x: f32, y: f32) -> i32 {
20803 if x.is_nan() || y.is_nan() { 0 } else { (x > y) as i32 }
20804}
20805
20806#[no_mangle]
20807pub unsafe extern "C" fn isgreaterequal(x: f64, y: f64) -> i32 {
20808 if x.is_nan() || y.is_nan() { 0 } else { (x >= y) as i32 }
20809}
20810
20811#[no_mangle]
20812pub unsafe extern "C" fn isgreaterequalf(x: f32, y: f32) -> i32 {
20813 if x.is_nan() || y.is_nan() { 0 } else { (x >= y) as i32 }
20814}
20815
20816#[no_mangle]
20821pub unsafe extern "C" fn stpcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char {
20822 let mut d = dest;
20823 let mut s = src;
20824 while *s != 0 {
20825 *d = *s;
20826 d = d.add(1);
20827 s = s.add(1);
20828 }
20829 *d = 0;
20830 d
20831}
20832
20833#[no_mangle]
20834pub unsafe extern "C" fn stpncpy(dest: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
20835 let mut i = 0;
20836 while i < n && *src.add(i) != 0 {
20837 *dest.add(i) = *src.add(i);
20838 i += 1;
20839 }
20840 let end = dest.add(i);
20841 while i < n {
20842 *dest.add(i) = 0;
20843 i += 1;
20844 }
20845 end
20846}
20847
20848#[no_mangle]
20849pub unsafe extern "C" fn strchrnul(s: *const c_char, c: c_int) -> *mut c_char {
20850 let mut p = s;
20851 while *p != 0 && *p as c_int != c {
20852 p = p.add(1);
20853 }
20854 p as *mut c_char
20855}
20856
20857#[no_mangle]
20858pub unsafe extern "C" fn fstatat(dirfd: c_int, path: *const c_char, buf: *mut Stat, flags: c_int) -> c_int {
20859 let r = sys_newfstatat(dirfd, path, buf as *mut u8, flags);
20860 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
20861}
20862
20863#[no_mangle]
20864pub unsafe extern "C" fn execvpe(
20865 file: *const c_char,
20866 argv: *const *const c_char,
20867 envp: *const *const c_char,
20868) -> c_int {
20869 if file.is_null() { return -1; }
20870 let mut has_slash = false;
20871 let mut p = file;
20872 while *p != 0 {
20873 if *p == b'/' as c_char { has_slash = true; break; }
20874 p = p.add(1);
20875 }
20876 if has_slash {
20877 return execve(file, argv, envp) as c_int;
20878 }
20879
20880 let file_len = crate::strlen(file);
20881 let path = crate::getenv(b"PATH\0".as_ptr() as *const c_char);
20882 if path.is_null() {
20883 return execve(file, argv, envp) as c_int;
20884 }
20885
20886 let mut buf = [0 as c_char; 4096];
20887 let mut dir = path;
20888 loop {
20889 let mut end = dir;
20890 while *end != 0 && *end != b':' as c_char { end = end.add(1); }
20891 let dlen = end.offset_from(dir) as usize;
20892 if dlen + 1 + file_len < buf.len() {
20893 let mut i = 0;
20894 while i < dlen {
20895 buf[i] = *dir.add(i);
20896 i += 1;
20897 }
20898 buf[i] = b'/' as c_char;
20899 i += 1;
20900 let mut j = 0;
20901 while j < file_len {
20902 buf[i + j] = *file.add(j);
20903 j += 1;
20904 }
20905 buf[i + j] = 0;
20906 execve(buf.as_ptr(), argv, envp);
20907 }
20908 if *end == 0 { break; }
20909 dir = end.add(1);
20910 }
20911 -1
20912}
20913
20914#[no_mangle]
20917pub unsafe extern "C" fn strcoll_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int {
20918 strcoll(s1, s2)
20919}
20920
20921#[no_mangle]
20922pub unsafe extern "C" fn strxfrm_l(dest: *mut c_char, src: *const c_char, n: usize, _loc: locale_t) -> usize {
20923 strxfrm(dest, src, n)
20924}
20925
20926#[no_mangle]
20927pub unsafe extern "C" fn strerror_l(errnum: c_int, _loc: locale_t) -> *mut c_char {
20928 strerror(errnum)
20929}
20930
20931#[no_mangle]
20932pub unsafe extern "C" fn strcasecmp_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int {
20933 strcasecmp(s1, s2)
20934}
20935
20936#[no_mangle]
20937pub unsafe extern "C" fn strncasecmp_l(s1: *const c_char, s2: *const c_char, n: usize, _loc: locale_t) -> c_int {
20938 strncasecmp(s1, s2, n)
20939}
20940
20941#[no_mangle]
20942pub unsafe extern "C" fn strftime_l(s: *mut c_char, max: usize, fmt: *const c_char, tm: *const tm, _loc: locale_t) -> usize {
20943 strftime(s, max, fmt, tm)
20944}
20945
20946#[no_mangle]
20947pub unsafe extern "C" fn nl_langinfo_l(item: c_int, _loc: locale_t) -> *mut c_char {
20948 nl_langinfo(item)
20949}
20950
20951#[no_mangle]
20952pub unsafe extern "C" fn wcscoll_l(s1: *const u32, s2: *const u32, _loc: locale_t) -> c_int {
20953 wcscoll(s1, s2)
20954}
20955
20956#[no_mangle]
20957pub unsafe extern "C" fn wcsxfrm_l(dst: *mut wchar_t, src: *const wchar_t, n: usize, _loc: locale_t) -> usize {
20958 wcsxfrm(dst, src, n)
20959}
20960
20961#[no_mangle]
20962pub unsafe extern "C" fn wcsftime_l(s: *mut u32, max: usize, fmt: *const u32, tm: *const c_void, _loc: locale_t) -> usize {
20963 wcsftime(s, max, fmt, tm)
20964}
20965
20966#[no_mangle]
20967pub unsafe extern "C" fn wctype_l(name: *const c_char, _loc: locale_t) -> wctype_t {
20968 wctype(name)
20969}
20970
20971#[no_mangle]
20972pub unsafe extern "C" fn wctrans_l(name: *const c_char, _loc: locale_t) -> wctrans_t {
20973 wctrans(name)
20974}
20975
20976#[no_mangle]
20977pub unsafe extern "C" fn towlower_l(c: wint_t, _loc: locale_t) -> wint_t {
20978 towlower(c)
20979}
20980
20981#[no_mangle]
20982pub unsafe extern "C" fn towupper_l(c: wint_t, _loc: locale_t) -> wint_t {
20983 towupper(c)
20984}
20985
20986#[no_mangle]
20987pub unsafe extern "C" fn towctrans_l(c: wint_t, desc: wctrans_t, _loc: locale_t) -> wint_t {
20988 towctrans(c, desc)
20989}
20990
20991#[no_mangle] pub unsafe extern "C" fn iswalnum_l(c: wint_t, _l: locale_t) -> c_int { iswalnum(c) }
20992#[no_mangle] pub unsafe extern "C" fn iswalpha_l(c: wint_t, _l: locale_t) -> c_int { iswalpha(c) }
20993#[no_mangle] pub unsafe extern "C" fn iswblank_l(c: wint_t, _l: locale_t) -> c_int { iswblank(c) }
20994#[no_mangle] pub unsafe extern "C" fn iswcntrl_l(c: wint_t, _l: locale_t) -> c_int { iswcntrl(c) }
20995#[no_mangle] pub unsafe extern "C" fn iswdigit_l(c: wint_t, _l: locale_t) -> c_int { iswdigit(c) }
20996#[no_mangle] pub unsafe extern "C" fn iswgraph_l(c: wint_t, _l: locale_t) -> c_int { iswgraph(c) }
20997#[no_mangle] pub unsafe extern "C" fn iswlower_l(c: wint_t, _l: locale_t) -> c_int { iswlower(c) }
20998#[no_mangle] pub unsafe extern "C" fn iswprint_l(c: wint_t, _l: locale_t) -> c_int { iswprint(c) }
20999#[no_mangle] pub unsafe extern "C" fn iswpunct_l(c: wint_t, _l: locale_t) -> c_int { iswpunct(c) }
21000#[no_mangle] pub unsafe extern "C" fn iswspace_l(c: wint_t, _l: locale_t) -> c_int { iswspace(c) }
21001#[no_mangle] pub unsafe extern "C" fn iswupper_l(c: wint_t, _l: locale_t) -> c_int { iswupper(c) }
21002#[no_mangle] pub unsafe extern "C" fn iswxdigit_l(c: wint_t, _l: locale_t) -> c_int { iswxdigit(c) }
21003#[no_mangle] pub unsafe extern "C" fn iswctype_l(c: wint_t, desc: wctype_t, _l: locale_t) -> c_int { iswctype(c, desc) }
21004
21005#[no_mangle] pub unsafe extern "C" fn __isoc99_scanf(fmt: *const c_char, args: ...) -> c_int { vfscanf(stdin, fmt, args) }
21007#[no_mangle] pub unsafe extern "C" fn __isoc99_fscanf(f: *mut FILE, fmt: *const c_char, args: ...) -> c_int { vfscanf(f, fmt, args) }
21008#[no_mangle] pub unsafe extern "C" fn __isoc99_sscanf(s: *const c_char, fmt: *const c_char, args: ...) -> c_int { vsscanf(s, fmt, args) }
21009#[no_mangle] pub unsafe extern "C" fn __isoc99_vscanf(fmt: *const c_char, args: VaList) -> c_int { vfscanf(stdin, fmt, args) }
21010#[no_mangle] pub unsafe extern "C" fn __isoc99_vfscanf(f: *mut FILE, fmt: *const c_char, args: VaList) -> c_int { vfscanf(f, fmt, args) }
21011#[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) }
21012#[no_mangle] pub unsafe extern "C" fn __isoc99_wscanf(fmt: *const wchar_t, args: ...) -> c_int { vfwscanf(stdin, fmt, args) }
21013#[no_mangle] pub unsafe extern "C" fn __isoc99_fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int { vfwscanf(f, fmt, args) }
21014#[no_mangle] pub unsafe extern "C" fn __isoc99_swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int { vswscanf(s, fmt, args) }
21015#[no_mangle] pub unsafe extern "C" fn __isoc99_vwscanf(fmt: *const wchar_t, args: VaList) -> c_int { vfwscanf(stdin, fmt, args) }
21016#[no_mangle] pub unsafe extern "C" fn __isoc99_vfwscanf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int { vfwscanf(f, fmt, args) }
21017#[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) }
21018
21019#[no_mangle] pub unsafe extern "C" fn clearerr_unlocked(f: *mut FILE) { clearerr(f) }
21022#[no_mangle] pub unsafe extern "C" fn feof_unlocked(f: *mut FILE) -> c_int { feof(f) }
21023#[no_mangle] pub unsafe extern "C" fn ferror_unlocked(f: *mut FILE) -> c_int { ferror(f) }
21024#[no_mangle] pub unsafe extern "C" fn fileno_unlocked(f: *mut FILE) -> c_int { fileno(f) }
21025#[no_mangle] pub unsafe extern "C" fn fflush_unlocked(f: *mut FILE) -> c_int { fflush(f) }
21026#[no_mangle] pub unsafe extern "C" fn fgetc_unlocked(f: *mut FILE) -> c_int { fgetc(f) }
21027#[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) }
21028#[no_mangle] pub unsafe extern "C" fn fputc_unlocked(c: c_int, f: *mut FILE) -> c_int { fputc(c, f) }
21029#[no_mangle] pub unsafe extern "C" fn fputs_unlocked(s: *const c_char, f: *mut FILE) -> c_int { fputs(s, f) }
21030#[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) }
21031#[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) }
21032#[no_mangle] pub unsafe extern "C" fn fgetwc_unlocked(f: *mut FILE) -> wint_t { fgetwc(f) }
21033#[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) }
21034#[no_mangle] pub unsafe extern "C" fn fputwc_unlocked(c: wchar_t, f: *mut FILE) -> wint_t { fputwc(c, f) }
21035#[no_mangle] pub unsafe extern "C" fn fputws_unlocked(s: *const wchar_t, f: *mut FILE) -> c_int { fputws(s, f) }
21036#[no_mangle] pub unsafe extern "C" fn getwc_unlocked(f: *mut c_void) -> wint_t { getwc(f) }
21037#[no_mangle] pub unsafe extern "C" fn putwc_unlocked(c: u32, f: *mut c_void) -> wint_t { putwc(c, f) }
21038#[no_mangle] pub unsafe extern "C" fn getwchar_unlocked() -> wint_t { getwchar() }
21039#[no_mangle] pub unsafe extern "C" fn putwchar_unlocked(c: wchar_t) -> wint_t { putwchar(c) }
21040#[no_mangle] pub unsafe extern "C" fn fpurge(f: *mut FILE) { clearerr(f) }
21041#[no_mangle] pub unsafe extern "C" fn _IO_getc(f: *mut FILE) -> c_int { getc(f) }
21042#[no_mangle] pub unsafe extern "C" fn _IO_putc(c: c_int, f: *mut FILE) -> c_int { putc(c, f) }
21043#[no_mangle] pub unsafe extern "C" fn _IO_getc_unlocked(f: *mut FILE) -> c_int { getc(f) }
21044#[no_mangle] pub unsafe extern "C" fn _IO_putc_unlocked(c: c_int, f: *mut FILE) -> c_int { putc(c, f) }
21045#[no_mangle] pub unsafe extern "C" fn _IO_feof_unlocked(f: *mut FILE) -> c_int { feof(f) }
21046#[no_mangle] pub unsafe extern "C" fn _IO_ferror_unlocked(f: *mut FILE) -> c_int { ferror(f) }
21047
21048#[no_mangle] pub unsafe extern "C" fn __getauxval(t: c_ulong) -> c_ulong { getauxval(t) }
21050#[no_mangle] pub unsafe extern "C" fn __longjmp(env: *const c_ulong, val: c_int) -> ! { longjmp(env, val) }
21051#[no_mangle] pub unsafe extern "C" fn bsd_signal(sig: c_int, handler: usize) -> usize { signal(sig, handler) }
21052#[no_mangle] pub unsafe extern "C" fn __sysv_signal(sig: c_int, handler: usize) -> usize { signal(sig, handler) }
21053#[no_mangle] pub unsafe extern "C" fn eaccess(path: *const c_char, mode: c_int) -> c_int { access(path, mode) }
21054#[no_mangle] pub unsafe extern "C" fn __xpg_basename(path: *mut c_char) -> *mut c_char { basename(path) }
21055#[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) }
21056#[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) }
21057
21058#[no_mangle]
21063pub unsafe extern "C" fn cfsetspeed(termios_p: *mut c_void, speed: u32) -> c_int {
21064 let r = cfsetispeed(termios_p, speed);
21065 if r != 0 { return r; }
21066 cfsetospeed(termios_p, speed)
21067}
21068
21069#[no_mangle]
21070pub unsafe extern "C" fn futimesat(dirfd: c_int, path: *const c_char, times: *const timeval) -> c_int {
21071 if times.is_null() {
21072 return utimensat(dirfd, path, core::ptr::null(), 0);
21073 }
21074 let tv = times as *const [timeval; 2];
21075 let mut ts: [timespec; 2] = [
21076 timespec { tv_sec: (*tv)[0].tv_sec, tv_nsec: (*tv)[0].tv_usec * 1000 },
21077 timespec { tv_sec: (*tv)[1].tv_sec, tv_nsec: (*tv)[1].tv_usec * 1000 },
21078 ];
21079 for t in &mut ts {
21080 if t.tv_nsec < 0 || t.tv_nsec >= 1_000_000_000 {
21081 ERRNO = EINVAL;
21082 return -1;
21083 }
21084 }
21085 utimensat(dirfd, path, ts.as_ptr(), 0)
21086}
21087
21088#[no_mangle]
21089pub unsafe extern "C" fn membarrier(cmd: c_int, flags: c_int, cpu_id: c_int) -> c_int {
21090 <Arch as Syscalls>::syscall3(SYS_MEMBARRIER, cmd as i64, flags as i64, cpu_id as i64) as c_int
21091}
21092
21093#[no_mangle]
21094pub unsafe extern "C" fn mremap(
21095 old_address: *mut c_void,
21096 old_size: usize,
21097 new_size: usize,
21098 flags: c_int,
21099 mut args: ...
21100) -> *mut c_void {
21101 let new_address = if flags & 2 != 0 { args.next_arg::<*mut c_void>() } else { core::ptr::null_mut() };
21102 let r = <Arch as Syscalls>::syscall5(
21103 SYS_MREMAP,
21104 old_address as i64,
21105 old_size as i64,
21106 new_size as i64,
21107 flags as i64,
21108 new_address as i64,
21109 );
21110 if r < 0 {
21111 ERRNO = (-r) as c_int;
21112 return (-1isize) as *mut c_void;
21113 }
21114 r as *mut c_void
21115}
21116
21117#[no_mangle]
21118pub unsafe extern "C" fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: usize) -> c_int {
21119 let name = ptsname(fd);
21120 if name.is_null() { return -1; }
21121 let n = crate::strlen(name);
21122 if n + 1 > buflen {
21123 ERRNO = ERANGE_VAL;
21124 return ERANGE_VAL;
21125 }
21126 core::ptr::copy_nonoverlapping(name, buf, n + 1);
21127 0
21128}
21129
21130#[no_mangle]
21131pub unsafe extern "C" fn posix_getdents(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize {
21132 if flags != 0 {
21133 ERRNO = EINVAL;
21134 return -1;
21135 }
21136 let r = <Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, buf as i64, len as i64);
21137 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
21138}
21139
21140#[no_mangle]
21141pub unsafe extern "C" fn riscv_flush_icache(start: *mut c_void, end: *mut c_void, flags: c_ulong) -> c_int {
21142 #[cfg(target_arch = "riscv64")]
21143 {
21144 let r = <Arch as Syscalls>::syscall3(259, start as i64, end as i64, flags as i64);
21145 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21146 }
21147 #[cfg(not(target_arch = "riscv64"))]
21148 {
21149 let _ = (start, end, flags);
21150 0
21151 }
21152}
21153
21154#[no_mangle]
21155pub unsafe extern "C" fn __riscv_flush_icache(start: *mut c_void, end: *mut c_void, flags: c_ulong) -> c_int {
21156 riscv_flush_icache(start, end, flags)
21157}
21158
21159#[no_mangle]
21160pub unsafe extern "C" fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int {
21161 let fd = mkstemps(template, suffixlen);
21162 if fd >= 0 && flags & O_CLOEXEC != 0 {
21163 sys_fcntl(fd, F_SETFD, FD_CLOEXEC as i64);
21164 }
21165 fd
21166}
21167
21168#[no_mangle]
21169pub unsafe extern "C" fn statfs(path: *const c_char, buf: *mut c_void) -> c_int {
21170 let r = <Arch as Syscalls>::syscall2(SYS_STATFS, path as i64, buf as i64);
21171 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21172}
21173
21174#[no_mangle]
21175pub unsafe extern "C" fn fstatfs(fd: c_int, buf: *mut c_void) -> c_int {
21176 let r = <Arch as Syscalls>::syscall2(SYS_FSTATFS, fd as i64, buf as i64);
21177 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21178}
21179
21180#[no_mangle]
21181pub unsafe extern "C" fn sysinfo(info: *mut c_void) -> c_int {
21182 let r = <Arch as Syscalls>::syscall1(SYS_SYSINFO, info as i64);
21183 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21184}
21185
21186#[no_mangle]
21187pub unsafe extern "C" fn pthread_tryjoin_np(thread: PthreadT, retval: *mut *mut c_void) -> c_int {
21188 let slot = thread as *mut Thread;
21189 if slot.is_null() { return EINVAL; }
21190 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
21191 let tid = core::ptr::read_volatile(&raw const (*slot).tid);
21192 if tid > 0 { return EBUSY; }
21193 if tid < 0 { return EINVAL; }
21194 pthread_join(thread, retval)
21195}
21196
21197#[no_mangle]
21198pub unsafe extern "C" fn pthread_timedjoin_np(thread: PthreadT, retval: *mut *mut c_void, abstime: *const timespec) -> c_int {
21199 let slot = thread as *mut Thread;
21200 if slot.is_null() { return EINVAL; }
21201 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
21202 loop {
21203 let r = pthread_tryjoin_np(thread, retval);
21204 if r != EBUSY { return r; }
21205 let tid = core::ptr::read_volatile(&raw const (*slot).tid);
21206 if tid <= 0 { continue; }
21207 let e = futex_timedwait(&raw mut (*slot).tid, tid, abstime);
21208 if e == ETIMEDOUT { return ETIMEDOUT; }
21209 }
21210}
21211
21212
21213#[repr(C)]
21216pub struct UtmpExit {
21217 pub e_termination: i16,
21218 pub e_exit: i16,
21219}
21220
21221#[repr(C)]
21222pub struct Utmpx {
21223 pub ut_type: i16,
21224 pub __ut_pad1: i16,
21225 pub ut_pid: i32,
21226 pub ut_line: [c_char; 32],
21227 pub ut_id: [c_char; 4],
21228 pub ut_user: [c_char; 32],
21229 pub ut_host: [c_char; 256],
21230 pub ut_exit: UtmpExit,
21231 pub ut_session: i32,
21232 pub __ut_pad2: i32,
21233 pub ut_tv: timeval,
21234 pub ut_addr_v6: [u32; 4],
21235 pub __unused: [u8; 20],
21236}
21237
21238const UTMP_SIZE: usize = 400;
21239const _: [(); UTMP_SIZE] = [(); core::mem::size_of::<Utmpx>()];
21240
21241static mut UTMP_FD: c_int = -1;
21242static mut UTMP_PATH: [u8; 256] = [0; 256];
21243static mut UTMP_PATH_SET: bool = false;
21244#[repr(align(8))]
21245struct UtmpBuf([u8; UTMP_SIZE]);
21246static mut UTMP_BUF: UtmpBuf = UtmpBuf([0; UTMP_SIZE]);
21247
21248unsafe fn utmp_path_ptr() -> *const c_char {
21249 if !UTMP_PATH_SET {
21250 let default = b"/var/run/utmp\0";
21251 let mut i = 0;
21252 while i < default.len() && i < UTMP_PATH.len() {
21253 UTMP_PATH[i] = default[i];
21254 i += 1;
21255 }
21256 UTMP_PATH_SET = true;
21257 }
21258 UTMP_PATH.as_ptr() as *const c_char
21259}
21260
21261unsafe fn utmp_open_read() -> c_int {
21262 if UTMP_FD >= 0 {
21263 crate::close(UTMP_FD);
21264 }
21265 UTMP_FD = crate::open(utmp_path_ptr(), 0, 0);
21266 UTMP_FD
21267}
21268
21269unsafe fn utmp_open_append() -> c_int {
21270 crate::open(utmp_path_ptr(), 1 | 64 | 1024, 0o644)
21271}
21272
21273#[no_mangle]
21274pub unsafe extern "C" fn setutent() {
21275 let _ = utmp_open_read();
21276}
21277
21278#[no_mangle]
21279pub unsafe extern "C" fn endutent() {
21280 if UTMP_FD >= 0 {
21281 crate::close(UTMP_FD);
21282 UTMP_FD = -1;
21283 }
21284}
21285
21286#[no_mangle]
21287pub unsafe extern "C" fn getutent() -> *mut c_void {
21288 if UTMP_FD < 0 && utmp_open_read() < 0 {
21289 return core::ptr::null_mut();
21290 }
21291 let n = crate::read(UTMP_FD, UTMP_BUF.0.as_mut_ptr() as *mut c_void, UTMP_SIZE);
21292 if n == UTMP_SIZE as isize {
21293 UTMP_BUF.0.as_mut_ptr() as *mut c_void
21294 } else {
21295 core::ptr::null_mut()
21296 }
21297}
21298
21299unsafe fn utmp_id_eq(a: &[c_char; 4], b: &[c_char; 4]) -> bool {
21300 a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]
21301}
21302
21303unsafe fn utmp_line_eq(a: &[c_char; 32], b: &[c_char; 32]) -> bool {
21304 let mut i = 0;
21305 while i < 32 {
21306 if a[i] != b[i] { return false; }
21307 if a[i] == 0 { return true; }
21308 i += 1;
21309 }
21310 true
21311}
21312
21313#[no_mangle]
21314pub unsafe extern "C" fn getutid(ut: *const c_void) -> *mut c_void {
21315 if ut.is_null() { return core::ptr::null_mut(); }
21316 let want = &*(ut as *const Utmpx);
21317 loop {
21318 let p = getutent();
21319 if p.is_null() { return p; }
21320 let cur = &*(p as *const Utmpx);
21321 let matched = match want.ut_type {
21322 1 | 2 | 3 | 4 => cur.ut_type == want.ut_type,
21323 _ => utmp_id_eq(&cur.ut_id, &want.ut_id)
21324 && (want.ut_type == 0 || cur.ut_type == want.ut_type),
21325 };
21326 if matched { return p; }
21327 }
21328}
21329
21330#[no_mangle]
21331pub unsafe extern "C" fn getutline(ut: *const c_void) -> *mut c_void {
21332 if ut.is_null() { return core::ptr::null_mut(); }
21333 let want = &*(ut as *const Utmpx);
21334 loop {
21335 let p = getutent();
21336 if p.is_null() { return p; }
21337 if utmp_line_eq(&(*(p as *const Utmpx)).ut_line, &want.ut_line) {
21338 return p;
21339 }
21340 }
21341}
21342
21343#[no_mangle]
21344pub unsafe extern "C" fn pututline(ut: *const c_void) -> *mut c_void {
21345 if ut.is_null() { return core::ptr::null_mut(); }
21346 let fd = utmp_open_append();
21347 if fd < 0 { return core::ptr::null_mut(); }
21348 let n = crate::write(fd, ut, UTMP_SIZE);
21349 crate::close(fd);
21350 if n == UTMP_SIZE as isize { ut as *mut c_void } else { core::ptr::null_mut() }
21351}
21352
21353#[no_mangle]
21354pub unsafe extern "C" fn updwtmp(file: *const c_char, ut: *const c_void) {
21355 if file.is_null() || ut.is_null() { return; }
21356 let fd = crate::open(file, 1 | 64 | 1024, 0o644);
21357 if fd >= 0 {
21358 let _ = crate::write(fd, ut, UTMP_SIZE);
21359 crate::close(fd);
21360 }
21361}
21362
21363unsafe fn utmp_set_name(file: *const c_char) -> c_int {
21364 if file.is_null() { return -1; }
21365 let len = crate::strlen(file);
21366 if len + 1 > UTMP_PATH.len() { return -1; }
21367 if UTMP_FD >= 0 {
21368 crate::close(UTMP_FD);
21369 UTMP_FD = -1;
21370 }
21371 core::ptr::copy_nonoverlapping(file, UTMP_PATH.as_mut_ptr() as *mut c_char, len + 1);
21372 UTMP_PATH_SET = true;
21373 0
21374}
21375
21376#[no_mangle]
21377pub unsafe extern "C" fn utmpname(file: *const c_char) -> c_int { utmp_set_name(file) }
21378
21379#[no_mangle]
21380pub unsafe extern "C" fn utmpxname(file: *const c_char) -> c_int { utmp_set_name(file) }
21381
21382
21383#[no_mangle] pub static mut ___environ: *mut *mut c_char = core::ptr::null_mut();
21385#[no_mangle] pub static mut _environ: *mut *mut c_char = core::ptr::null_mut();
21386#[no_mangle] pub unsafe extern "C" fn __freelocale(loc: locale_t) { freelocale(loc) }
21387#[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) }
21388#[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) }
21389#[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) }
21390#[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) }
21391
21392#[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) }
21393#[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) }
21394#[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) }
21395#[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) }
21396#[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) }
21397#[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) }
21398
21399const MAX_NS: usize = 3;
21404const MAX_SEARCH: usize = 6;
21405const HOST_NOT_FOUND: c_int = 1;
21406const TRY_AGAIN: c_int = 2;
21407const NO_RECOVERY: c_int = 3;
21408const NO_DATA: c_int = 4;
21409
21410static mut NS_COUNT: usize = 0;
21411static mut NS_ADDRS: [u32; MAX_NS] = [0; MAX_NS];
21412static mut SEARCH_COUNT: usize = 0;
21413static mut SEARCH_DOMAINS: [[u8; 256]; MAX_SEARCH] = [[0; 256]; MAX_SEARCH];
21414static mut RESOLV_INITIALIZED: bool = false;
21415
21416#[repr(C)]
21417struct SockAddrIn {
21418 sin_family: u16,
21419 sin_port: u16,
21420 sin_addr: u32,
21421 sin_zero: [u8; 8],
21422}
21423
21424#[repr(C)]
21425struct PollFd {
21426 fd: c_int,
21427 events: i16,
21428 revents: i16,
21429}
21430
21431unsafe fn resolv_skip_ws(line: &[u8], mut i: usize) -> usize {
21432 while i < line.len() && (line[i] == b' ' || line[i] == b'\t') { i += 1; }
21433 i
21434}
21435
21436unsafe fn resolv_token<'a>(line: &'a [u8], mut i: usize) -> (&'a [u8], usize) {
21437 let start = i;
21438 while i < line.len() && line[i] != b' ' && line[i] != b'\t' && line[i] != b'#' { i += 1; }
21439 (&line[start..i], i)
21440}
21441
21442unsafe fn resolv_parse_config() -> c_int {
21443 RESOLV_INITIALIZED = true;
21444 NS_COUNT = 0;
21445 SEARCH_COUNT = 0;
21446 let path = b"/etc/resolv.conf\0";
21447 let fd = crate::open(path.as_ptr() as *const c_char, 0, 0);
21448 if fd < 0 { return -1; }
21449 let mut buf = [0u8; 4096];
21450 let n = crate::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len());
21451 crate::close(fd);
21452 if n <= 0 { return -1; }
21453 let len = n as usize;
21454 let mut i = 0;
21455 while i < len {
21456 let start = i;
21457 while i < len && buf[i] != b'\n' { i += 1; }
21458 let line = &buf[start..i];
21459 i += 1;
21460 let mut j = resolv_skip_ws(line, 0);
21461 if j >= line.len() || line[j] == b'#' { continue; }
21462 let (key, next) = resolv_token(line, j);
21463 j = next;
21464 if key == b"nameserver" {
21465 j = resolv_skip_ws(line, j);
21466 let (tok, _) = resolv_token(line, j);
21467 if !tok.is_empty() && NS_COUNT < MAX_NS {
21468 let mut name = [0u8; 64];
21469 let l = core::cmp::min(tok.len(), 63);
21470 name[..l].copy_from_slice(&tok[..l]);
21471 let addr = crate::inet_addr(name.as_ptr() as *const c_char);
21472 if addr != u32::MAX {
21473 NS_ADDRS[NS_COUNT] = addr;
21474 NS_COUNT += 1;
21475 }
21476 }
21477 } else if key == b"search" || key == b"domain" {
21478 loop {
21479 j = resolv_skip_ws(line, j);
21480 if j >= line.len() || line[j] == b'#' { break; }
21481 let (tok, next) = resolv_token(line, j);
21482 j = next;
21483 if tok.is_empty() { break; }
21484 if SEARCH_COUNT < MAX_SEARCH {
21485 let l = core::cmp::min(tok.len(), 255);
21486 SEARCH_DOMAINS[SEARCH_COUNT][..l].copy_from_slice(&tok[..l]);
21487 SEARCH_DOMAINS[SEARCH_COUNT][l] = 0;
21488 SEARCH_COUNT += 1;
21489 }
21490 if key == b"domain" { break; }
21491 }
21492 }
21493 }
21494 0
21495}
21496
21497#[no_mangle]
21498pub unsafe extern "C" fn res_init() -> c_int {
21499 let _ = resolv_parse_config();
21500 0
21501}
21502
21503#[no_mangle]
21504pub unsafe extern "C" fn res_mkquery(
21505 op: c_int,
21506 dname: *const c_char,
21507 class: c_int,
21508 type_: c_int,
21509 _data: *const u8,
21510 _datalen: c_int,
21511 _newrr: *const u8,
21512 buf: *mut u8,
21513 buflen: c_int,
21514) -> c_int {
21515 if dname.is_null() || buf.is_null() { return -1; }
21516 let mut l = crate::strnlen(dname as *const u8, 255);
21517 if l > 0 && *dname.add(l - 1) == b'.' as c_char { l -= 1; }
21518 if l > 0 && *dname.add(l - 1) == b'.' as c_char { return -1; }
21519 let n = 17 + l + if l != 0 { 1 } else { 0 };
21520 if l > 253 || buflen < n as c_int || op < 0 || op > 15 || class < 0 || class > 255 || type_ < 0 || type_ > 255 {
21521 return -1;
21522 }
21523 let mut q = [0u8; 280];
21524 crate::memset(q.as_mut_ptr() as *mut c_void, 0, n);
21525 q[2] = (op * 8 + 1) as u8;
21526 q[3] = 32;
21527 q[5] = 1;
21528 core::ptr::copy_nonoverlapping(dname as *const u8, q.as_mut_ptr().add(13), l);
21529 let mut i = 13;
21530 while q[i] != 0 {
21531 let mut j = i;
21532 while q[j] != 0 && q[j] != b'.' { j += 1; }
21533 if j - i - 1 > 62 { return -1; }
21534 q[i - 1] = (j - i) as u8;
21535 i = j + 1;
21536 }
21537 q[i + 1] = type_ as u8;
21538 q[i + 3] = class as u8;
21539 let mut ts = timespec { tv_sec: 0, tv_nsec: 0 };
21540 let _ = clock_gettime(CLOCK_REALTIME, &mut ts);
21541 let id = (((ts.tv_nsec as u64) + (ts.tv_nsec as u64) / 65536) & 0xffff) as u16;
21542 q[0] = (id >> 8) as u8;
21543 q[1] = id as u8;
21544 core::ptr::copy_nonoverlapping(q.as_ptr(), buf, n);
21545 n as c_int
21546}
21547
21548unsafe fn res_send_inner(msg: *const u8, msglen: c_int, answer: *mut u8, anslen: c_int) -> c_int {
21549 if msg.is_null() || answer.is_null() || msglen < 12 || anslen < 12 { return -1; }
21550 if !RESOLV_INITIALIZED { let _ = resolv_parse_config(); }
21551 if NS_COUNT == 0 {
21552 h_errno = TRY_AGAIN;
21553 return -1;
21554 }
21555 for n in 0..NS_COUNT {
21556 let fd = crate::socket(AF_INET, SOCK_DGRAM, 0);
21557 if fd < 0 { continue; }
21558 let sa = SockAddrIn {
21559 sin_family: AF_INET as u16,
21560 sin_port: 53u16.to_be(),
21561 sin_addr: NS_ADDRS[n],
21562 sin_zero: [0; 8],
21563 };
21564 let sent = crate::sendto(fd, msg as *const c_void, msglen as usize, 0, &sa as *const SockAddrIn as *const crate::sockaddr, 16);
21565 if sent != msglen as isize {
21566 crate::close(fd);
21567 continue;
21568 }
21569 let mut pfd = PollFd { fd, events: 1, revents: 0 };
21570 let pr = crate::poll(&mut pfd as *mut PollFd as *mut c_void, 1, 5000);
21571 if pr <= 0 {
21572 crate::close(fd);
21573 continue;
21574 }
21575 let r = crate::recvfrom(fd, answer as *mut c_void, anslen as usize, 0, core::ptr::null_mut(), core::ptr::null_mut());
21576 crate::close(fd);
21577 if r >= 12 {
21578 let id_ok = *answer == *msg && *answer.add(1) == *msg.add(1);
21579 let qr = (*answer.add(2) & 0x80) != 0;
21580 if id_ok && qr {
21581 return r as c_int;
21582 }
21583 }
21584 }
21585 h_errno = TRY_AGAIN;
21586 -1
21587}
21588
21589#[no_mangle]
21590pub unsafe extern "C" fn res_send(msg: *const u8, msglen: c_int, answer: *mut u8, anslen: c_int) -> c_int {
21591 if anslen < 512 {
21592 let mut buf = [0u8; 512];
21593 let r = res_send_inner(msg, msglen, buf.as_mut_ptr(), 512);
21594 if r >= 0 {
21595 let copy = core::cmp::min(r, anslen) as usize;
21596 if copy > 0 { core::ptr::copy_nonoverlapping(buf.as_ptr(), answer, copy); }
21597 }
21598 return r;
21599 }
21600 res_send_inner(msg, msglen, answer, anslen)
21601}
21602
21603#[no_mangle]
21604pub unsafe extern "C" fn res_query(
21605 dname: *const c_char,
21606 class: c_int,
21607 type_: c_int,
21608 answer: *mut u8,
21609 anslen: c_int,
21610) -> c_int {
21611 let mut q = [0u8; 280];
21612 let ql = res_mkquery(0, dname, class, type_, core::ptr::null(), 0, core::ptr::null(), q.as_mut_ptr(), q.len() as c_int);
21613 if ql < 0 { return ql; }
21614 let r = res_send(q.as_ptr(), ql, answer, anslen);
21615 if r < 12 {
21616 h_errno = TRY_AGAIN;
21617 return -1;
21618 }
21619 let rcode = answer.add(3).read() & 0x0f;
21620 if rcode == 3 {
21621 h_errno = HOST_NOT_FOUND;
21622 return -1;
21623 }
21624 if rcode == 0 && *answer.add(6) == 0 && *answer.add(7) == 0 {
21625 h_errno = NO_DATA;
21626 return -1;
21627 }
21628 if rcode != 0 {
21629 h_errno = NO_RECOVERY;
21630 return -1;
21631 }
21632 r
21633}
21634
21635#[no_mangle]
21636pub unsafe extern "C" fn res_querydomain(
21637 name: *const c_char,
21638 domain: *const c_char,
21639 class: c_int,
21640 type_: c_int,
21641 answer: *mut u8,
21642 anslen: c_int,
21643) -> c_int {
21644 if domain.is_null() || *domain == 0 { return res_query(name, class, type_, answer, anslen); }
21645 let mut buf = [0u8; 512];
21646 let nl = crate::strlen(name);
21647 let dl = crate::strlen(domain);
21648 if nl + 1 + dl >= buf.len() { return -1; }
21649 core::ptr::copy_nonoverlapping(name, buf.as_mut_ptr() as *mut c_char, nl);
21650 buf[nl] = b'.';
21651 core::ptr::copy_nonoverlapping(domain, buf.as_mut_ptr().add(nl + 1) as *mut c_char, dl);
21652 buf[nl + 1 + dl] = 0;
21653 res_query(buf.as_ptr() as *const c_char, class, type_, answer, anslen)
21654}
21655
21656#[no_mangle]
21657pub unsafe extern "C" fn res_search(
21658 name: *const c_char,
21659 class: c_int,
21660 type_: c_int,
21661 answer: *mut u8,
21662 anslen: c_int,
21663) -> c_int {
21664 if name.is_null() { return -1; }
21665 if !RESOLV_INITIALIZED { let _ = resolv_parse_config(); }
21666 let len = crate::strlen(name);
21667 let mut dots = 0;
21668 for i in 0..len {
21669 if *name.add(i) == b'.' as c_char { dots += 1; }
21670 }
21671 let trailing_dot = len > 0 && *name.add(len - 1) == b'.' as c_char;
21672 if trailing_dot || dots >= 1 {
21673 let r = res_query(name, class, type_, answer, anslen);
21674 if r >= 0 { return r; }
21675 if trailing_dot { return -1; }
21676 }
21677 for i in 0..SEARCH_COUNT {
21678 let dom = SEARCH_DOMAINS[i].as_ptr() as *const c_char;
21679 let r = res_querydomain(name, dom, class, type_, answer, anslen);
21680 if r >= 0 { return r; }
21681 if h_errno != HOST_NOT_FOUND && h_errno != NO_DATA { return -1; }
21682 }
21683 if dots == 0 {
21684 return res_query(name, class, type_, answer, anslen);
21685 }
21686 -1
21687}
21688
21689#[repr(C)]
21694pub struct HostEnt {
21695 pub h_name: *mut c_char,
21696 pub h_aliases: *mut *mut c_char,
21697 pub h_addrtype: c_int,
21698 pub h_length: c_int,
21699 pub h_addr_list: *mut *mut c_char,
21700}
21701
21702#[repr(C)]
21703pub struct AddrInfo {
21704 pub ai_flags: c_int,
21705 pub ai_family: c_int,
21706 pub ai_socktype: c_int,
21707 pub ai_protocol: c_int,
21708 pub ai_addrlen: u32,
21709 pub ai_addr: *mut c_void,
21710 pub ai_canonname: *mut c_char,
21711 pub ai_next: *mut AddrInfo,
21712}
21713
21714static mut HOST_ENT: HostEnt = HostEnt {
21715 h_name: core::ptr::null_mut(),
21716 h_aliases: core::ptr::null_mut(),
21717 h_addrtype: 0,
21718 h_length: 0,
21719 h_addr_list: core::ptr::null_mut(),
21720};
21721static mut HOST_NAME: [c_char; 256] = [0; 256];
21722static mut HOST_ALIASES: [*mut c_char; 1] = [core::ptr::null_mut()];
21723static mut HOST_ADDR: [u8; 16] = [0; 16];
21724static mut HOST_ADDR_PTRS: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
21725
21726unsafe fn dns_skip_name(p: *const u8, end: *const u8) -> *const u8 {
21727 let mut q = p;
21728 while q < end {
21729 let c = *q;
21730 if c == 0 { return q.add(1); }
21731 if c & 0xc0 == 0xc0 { return q.add(2); }
21732 q = q.add(1 + c as usize);
21733 }
21734 end
21735}
21736
21737unsafe fn dns_read_u16(p: *const u8) -> u16 {
21738 ((*p as u16) << 8) | *p.add(1) as u16
21739}
21740
21741unsafe fn dns_expand_name(p: *const u8, msg: *const u8, out: *mut c_char, outlen: usize) -> bool {
21742 let mut q = p;
21743 let mut o = 0usize;
21744 let mut jumps = 0;
21745 loop {
21746 let c = *q;
21747 if c == 0 {
21748 if o < outlen { *out.add(o) = 0; }
21749 return true;
21750 }
21751 if c & 0xc0 == 0xc0 {
21752 let off = (((c & 0x3f) as usize) << 8) | *q.add(1) as usize;
21753 q = msg.add(off);
21754 jumps += 1;
21755 if jumps > 16 { return false; }
21756 continue;
21757 }
21758 let l = c as usize;
21759 if l > 63 { return false; }
21760 if o + l + 1 >= outlen { return false; }
21761 core::ptr::copy_nonoverlapping(q.add(1), out.add(o) as *mut u8, l);
21762 o += l;
21763 *out.add(o) = b'.' as c_char;
21764 o += 1;
21765 q = q.add(1 + l);
21766 }
21767}
21768
21769unsafe fn host_from_answer(answer: *const u8, len: c_int, af: c_int) -> *mut HostEnt {
21770 if len < 12 { return core::ptr::null_mut(); }
21771 let end = answer.add(len as usize);
21772 let qd = dns_read_u16(answer.add(4)) as usize;
21773 let an = dns_read_u16(answer.add(6)) as usize;
21774 let mut p = answer.add(12);
21775 for _ in 0..qd {
21776 p = dns_skip_name(p, end);
21777 p = p.add(4);
21778 }
21779 let want_type: u16 = if af == AF_INET6 { 28 } else { 1 };
21780 let want_len = if af == AF_INET6 { 16 } else { 4 };
21781 for _ in 0..an {
21782 p = dns_skip_name(p, end);
21783 if p.add(10) > end { break; }
21784 let typ = dns_read_u16(p);
21785 let class = dns_read_u16(p.add(2));
21786 let rdlen = dns_read_u16(p.add(8)) as usize;
21787 let rdata = p.add(10);
21788 if rdata.add(rdlen) > end { break; }
21789 if typ == want_type && class == 1 && rdlen == want_len {
21790 core::ptr::copy_nonoverlapping(rdata, HOST_ADDR.as_mut_ptr(), want_len);
21791 HOST_ENT.h_addrtype = af;
21792 HOST_ENT.h_length = want_len as c_int;
21793 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
21794 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
21795 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
21796 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
21797 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
21798 h_errno = 0;
21799 return &raw mut HOST_ENT;
21800 }
21801 p = rdata.add(rdlen);
21802 }
21803 core::ptr::null_mut()
21804}
21805
21806#[no_mangle]
21807pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut HostEnt {
21808 gethostbyname2(name, AF_INET)
21809}
21810
21811#[no_mangle]
21812pub unsafe extern "C" fn gethostbyname2(name: *const c_char, af: c_int) -> *mut HostEnt {
21813 if name.is_null() { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
21814 let mut addr = [0u8; 16];
21815 let addrlen = if af == AF_INET6 { 16 } else { 4 };
21816 if inet_pton(af, name, addr.as_mut_ptr() as *mut c_void) == 1 {
21817 core::ptr::copy_nonoverlapping(addr.as_ptr(), HOST_ADDR.as_mut_ptr(), addrlen);
21818 let n = crate::strlen(name);
21819 let l = core::cmp::min(n, 255);
21820 core::ptr::copy_nonoverlapping(name, HOST_NAME.as_mut_ptr(), l);
21821 HOST_NAME[l] = 0;
21822 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
21823 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
21824 HOST_ENT.h_addrtype = af;
21825 HOST_ENT.h_length = addrlen as c_int;
21826 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
21827 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
21828 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
21829 h_errno = 0;
21830 return &raw mut HOST_ENT;
21831 }
21832 let mut answer = [0u8; 512];
21833 let qtype = if af == AF_INET6 { 28 } else { 1 };
21834 let r = res_query(name, 1, qtype, answer.as_mut_ptr(), answer.len() as c_int);
21835 if r < 0 {
21836 if h_errno == 0 { h_errno = TRY_AGAIN; }
21837 return core::ptr::null_mut();
21838 }
21839 let ent = host_from_answer(answer.as_ptr(), r, af);
21840 if !ent.is_null() {
21841 let n = crate::strlen(name);
21842 let l = core::cmp::min(n, 255);
21843 core::ptr::copy_nonoverlapping(name, HOST_NAME.as_mut_ptr(), l);
21844 HOST_NAME[l] = 0;
21845 } else {
21846 h_errno = HOST_NOT_FOUND;
21847 }
21848 ent
21849}
21850
21851#[no_mangle]
21852pub unsafe extern "C" fn gethostbyaddr(addr: *const c_void, len: u32, type_: c_int) -> *mut HostEnt {
21853 if addr.is_null() || type_ != AF_INET || len != 4 { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
21854 let a = addr as *const u8;
21855 let mut name = [0u8; 128];
21856 let mut pos = 0;
21857 for i in 0..4 {
21858 let v = *a.add(3 - i) as u32;
21859 if v >= 100 { name[pos] = b'0' + (v / 100) as u8; pos += 1; }
21860 if v >= 10 { name[pos] = b'0' + ((v / 10) % 10) as u8; pos += 1; }
21861 name[pos] = b'0' + (v % 10) as u8; pos += 1;
21862 name[pos] = b'.'; pos += 1;
21863 }
21864 let suffix = b"in-addr.arpa";
21865 for &c in suffix { name[pos] = c; pos += 1; }
21866 name[pos] = 0;
21867 let mut answer = [0u8; 512];
21868 let r = res_query(name.as_ptr() as *const c_char, 1, 12, answer.as_mut_ptr(), answer.len() as c_int);
21869 if r < 12 { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
21870 let end = answer.as_ptr().add(r as usize);
21871 let qd = dns_read_u16(answer.as_ptr().add(4)) as usize;
21872 let an = dns_read_u16(answer.as_ptr().add(6)) as usize;
21873 let mut p = answer.as_ptr().add(12);
21874 for _ in 0..qd { p = dns_skip_name(p, end); p = p.add(4); }
21875 for _ in 0..an {
21876 p = dns_skip_name(p, end);
21877 if p.add(10) > end { break; }
21878 let typ = dns_read_u16(p);
21879 let rdlen = dns_read_u16(p.add(8)) as usize;
21880 let rdata = p.add(10);
21881 if typ == 12 && dns_expand_name(rdata, answer.as_ptr(), HOST_NAME.as_mut_ptr(), HOST_NAME.len()) {
21882 let mut o = crate::strlen(HOST_NAME.as_ptr());
21883 if o > 0 && HOST_NAME[o - 1] == b'.' as c_char { o -= 1; }
21884 HOST_NAME[o] = 0;
21885 core::ptr::copy_nonoverlapping(a, HOST_ADDR.as_mut_ptr(), 4);
21886 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
21887 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
21888 HOST_ENT.h_addrtype = AF_INET;
21889 HOST_ENT.h_length = 4;
21890 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
21891 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
21892 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
21893 h_errno = 0;
21894 return &raw mut HOST_ENT;
21895 }
21896 p = rdata.add(rdlen);
21897 }
21898 h_errno = HOST_NOT_FOUND;
21899 core::ptr::null_mut()
21900}
21901
21902#[inline]
21907fn sysno(x86_64: i64, generic: i64) -> i64 {
21908 if cfg!(target_arch = "x86_64") { x86_64 } else { generic }
21909}
21910
21911#[no_mangle]
21912pub unsafe extern "C" fn settimeofday(tv: *const c_void, tz: *const c_void) -> c_int {
21913 let r = <Arch as Syscalls>::syscall2(sysno(164, 170), tv as i64, tz as i64);
21914 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21915}
21916
21917#[no_mangle]
21918pub unsafe extern "C" fn stime(t: *const i64) -> c_int {
21919 if t.is_null() { ERRNO = EINVAL; return -1; }
21920 let tv = timeval { tv_sec: *t, tv_usec: 0 };
21921 settimeofday(&tv as *const timeval as *const c_void, core::ptr::null())
21922}
21923
21924#[no_mangle]
21925pub unsafe extern "C" fn times(buf: *mut c_void) -> c_long {
21926 let r = <Arch as Syscalls>::syscall1(sysno(100, 153), buf as i64);
21927 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_long }
21928}
21929
21930#[no_mangle]
21931pub 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 {
21932 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);
21933 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
21934}
21935
21936#[no_mangle]
21937pub unsafe extern "C" fn tee(fd_in: c_int, fd_out: c_int, len: usize, flags: u32) -> isize {
21938 let r = <Arch as Syscalls>::syscall4(sysno(276, 77), fd_in as i64, fd_out as i64, len as i64, flags as i64);
21939 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
21940}
21941
21942#[no_mangle]
21943pub unsafe extern "C" fn statx(dirfd: c_int, path: *const c_char, flags: c_int, mask: u32, buf: *mut c_void) -> c_int {
21944 let r = <Arch as Syscalls>::syscall5(sysno(332, 291), dirfd as i64, path as i64, flags as i64, mask as i64, buf as i64);
21945 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21946}
21947
21948#[no_mangle]
21949pub unsafe extern "C" fn setns(fd: c_int, nstype: c_int) -> c_int {
21950 let r = <Arch as Syscalls>::syscall2(SYS_SETNS, fd as i64, nstype as i64);
21951 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21952}
21953
21954#[no_mangle]
21955pub unsafe extern "C" fn setfsuid(uid: u32) -> c_int {
21956 <Arch as Syscalls>::syscall1(sysno(122, 151), uid as i64) as c_int
21957}
21958
21959#[no_mangle]
21960pub unsafe extern "C" fn setfsgid(gid: u32) -> c_int {
21961 <Arch as Syscalls>::syscall1(sysno(123, 152), gid as i64) as c_int
21962}
21963
21964#[no_mangle]
21965pub unsafe extern "C" fn setregid(rgid: u32, egid: u32) -> c_int {
21966 let r = <Arch as Syscalls>::syscall2(sysno(114, 143), rgid as i64, egid as i64);
21967 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21968}
21969
21970#[no_mangle]
21971pub 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 {
21972 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);
21973 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
21974}
21975
21976#[no_mangle]
21977pub 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 {
21978 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);
21979 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
21980}
21981
21982#[no_mangle]
21983pub unsafe extern "C" fn tcgetwinsize(fd: c_int, ws: *mut c_void) -> c_int {
21984 if fd < 0 || ws.is_null() { ERRNO = EINVAL; return -1; }
21985 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5413, ws as i64);
21986 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21987}
21988
21989#[no_mangle]
21990pub unsafe extern "C" fn tcsetwinsize(fd: c_int, ws: *const c_void) -> c_int {
21991 if fd < 0 || ws.is_null() { ERRNO = EINVAL; return -1; }
21992 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5414, ws as i64);
21993 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21994}
21995
21996#[no_mangle]
21997pub unsafe extern "C" fn sockatmark(fd: c_int) -> c_int {
21998 let mut at: c_int = 0;
21999 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x8905, &mut at as *mut c_int as i64);
22000 if r < 0 { ERRNO = (-r) as c_int; -1 } else { at }
22001}
22002
22003#[no_mangle]
22004pub unsafe extern "C" fn isastream(fd: c_int) -> c_int {
22005 let mut buf = [0u8; 64];
22006 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5401, buf.as_mut_ptr() as i64);
22007 if r < 0 { ERRNO = (-r) as c_int; 0 } else { 1 }
22008}
22009
22010#[no_mangle]
22011pub unsafe extern "C" fn posix_madvise(addr: *mut c_void, len: usize, advice: c_int) -> c_int {
22012 madvise(addr as *mut u8, len, advice)
22013}
22014
22015#[no_mangle]
22016pub unsafe extern "C" fn secure_getenv(name: *const c_char) -> *mut c_char {
22017 if getauxval(23) != 0 { return core::ptr::null_mut(); }
22018 getenv(name)
22019}
22020
22021#[no_mangle]
22022pub unsafe extern "C" fn sigandset(dest: *mut c_ulong, left: *const c_ulong, right: *const c_ulong) -> c_int {
22023 if dest.is_null() || left.is_null() || right.is_null() { return -1; }
22024 *dest = *left & *right;
22025 0
22026}
22027
22028#[no_mangle]
22029pub unsafe extern "C" fn sigorset(dest: *mut c_ulong, left: *const c_ulong, right: *const c_ulong) -> c_int {
22030 if dest.is_null() || left.is_null() || right.is_null() { return -1; }
22031 *dest = *left | *right;
22032 0
22033}
22034
22035#[no_mangle]
22036pub unsafe extern "C" fn sigisemptyset(set: *const c_ulong) -> c_int {
22037 if set.is_null() { return 1; }
22038 (*set == 0) as c_int
22039}
22040
22041#[no_mangle]
22042pub unsafe extern "C" fn sighold(sig: c_int) -> c_int {
22043 let set: c_ulong = 1u64 << (sig - 1) as u32;
22044 sigprocmask(0, &set, core::ptr::null_mut());
22045 0
22046}
22047
22048#[no_mangle]
22049pub unsafe extern "C" fn sigignore(sig: c_int) -> c_int {
22050 let _ = signal(sig, 1);
22051 0
22052}
22053
22054#[no_mangle]
22055pub unsafe extern "C" fn sigrelse(sig: c_int) -> c_int {
22056 let set: c_ulong = 1u64 << (sig - 1) as u32;
22057 sigprocmask(1, &set, core::ptr::null_mut());
22058 0
22059}
22060
22061#[no_mangle]
22062pub unsafe extern "C" fn siginterrupt(sig: c_int, flag: c_int) -> c_int {
22063 let mut sa: sigaction = core::mem::zeroed();
22064 if sigaction(sig, core::ptr::null(), &mut sa) != 0 { return -1; }
22065 if flag != 0 { sa.sa_flags &= !(SA_RESTART as c_ulong); } else { sa.sa_flags |= SA_RESTART as c_ulong; }
22066 sigaction(sig, &sa, core::ptr::null_mut())
22067}
22068
22069#[no_mangle]
22070pub unsafe extern "C" fn sigpause(sig: c_int) -> c_int {
22071 let set: c_ulong = 1u64 << (sig - 1) as u32;
22072 sigsuspend(&set)
22073}
22074
22075#[no_mangle]
22076pub unsafe extern "C" fn semtimedop(semid: c_int, sops: *mut c_void, nsops: usize, timeout: *const timespec) -> c_int {
22077 let r = <Arch as Syscalls>::syscall4(sysno(220, 192), semid as i64, sops as i64, nsops as i64, timeout as i64);
22078 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
22079}
22080
22081#[no_mangle]
22082pub unsafe extern "C" fn wait3(status: *mut c_int, options: c_int, rusage: *mut c_void) -> i32 {
22083 wait4(-1, status, options, rusage) as i32
22084}
22085
22086#[no_mangle]
22087pub unsafe extern "C" fn tempnam(dir: *const c_char, pfx: *const c_char) -> *mut c_char {
22088 let mut path = [0 as c_char; 256];
22089 let mut i = 0;
22090 if !dir.is_null() {
22091 while *dir.add(i) != 0 && i < 200 { path[i] = *dir.add(i); i += 1; }
22092 if i > 0 && path[i-1] != b'/' as c_char { path[i] = b'/' as c_char; i += 1; }
22093 } else {
22094 for &c in b"/tmp/" { path[i] = c as c_char; i += 1; }
22095 }
22096 if !pfx.is_null() {
22097 let mut j = 0;
22098 while *pfx.add(j) != 0 && i < 220 { path[i] = *pfx.add(j); i += 1; j += 1; }
22099 }
22100 for &c in b"XXXXXX" { path[i] = c as c_char; i += 1; }
22101 path[i] = 0;
22102 let fd = mkstemp(path.as_mut_ptr());
22103 if fd < 0 { return core::ptr::null_mut(); }
22104 close(fd);
22105 unlink(path.as_ptr());
22106 let n = strlen(path.as_ptr());
22107 let out = malloc(n + 1) as *mut c_char;
22108 if out.is_null() { return core::ptr::null_mut(); }
22109 core::ptr::copy_nonoverlapping(path.as_ptr(), out, n + 1);
22110 out
22111}
22112
22113#[no_mangle]
22114pub unsafe extern "C" fn putwc(c: u32, f: *mut c_void) -> u32 {
22115 fputwc(c as c_int, f as *mut FILE) as u32
22116}
22117
22118#[no_mangle]
22119pub unsafe extern "C" fn __uflow(f: *mut c_void) -> c_int {
22120 fgetc(f as *mut FILE)
22121}
22122
22123#[no_mangle]
22124pub unsafe extern "C" fn __xmknod(_ver: c_int, path: *const c_char, mode: c_uint, dev: u64) -> c_int {
22125 mknod(path, mode, dev)
22126}
22127
22128#[no_mangle]
22129pub unsafe extern "C" fn __xmknodat(_ver: c_int, dirfd: c_int, path: *const c_char, mode: c_uint, dev: u64) -> c_int {
22130 mknodat(dirfd, path, mode, dev)
22131}
22132
22133#[no_mangle]
22134pub 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 {
22135 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);
22136 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
22137}
22138
22139#[no_mangle]
22140pub unsafe extern "C" fn open_by_handle_at(mount_fd: c_int, handle: *mut c_void, flags: c_int) -> c_int {
22141 let r = <Arch as Syscalls>::syscall3(sysno(304, 265), mount_fd as i64, handle as i64, flags as i64);
22142 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
22143}
22144
22145#[no_mangle]
22146pub unsafe extern "C" fn dn_skipname(comp: *const u8, eom: *const u8) -> c_int {
22147 let p = dns_skip_name(comp, eom);
22148 if p <= eom { (p as isize - comp as isize) as c_int } else { -1 }
22149}
22150
22151#[no_mangle]
22152pub 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 {
22153 if exp.is_null() || dst.is_null() || dstsiz <= 0 { return -1; }
22154 let mut o = 0usize;
22155 let mut p = exp;
22156 loop {
22157 let start = p;
22158 while *p != 0 && *p != b'.' as c_char { p = p.add(1); }
22159 let l = p as usize - start as usize;
22160 if l > 63 || o + l + 2 > dstsiz as usize { return -1; }
22161 *dst.add(o) = l as u8; o += 1;
22162 core::ptr::copy_nonoverlapping(start as *const u8, dst.add(o), l);
22163 o += l;
22164 if *p == 0 { break; }
22165 p = p.add(1);
22166 }
22167 if o + 1 > dstsiz as usize { return -1; }
22168 *dst.add(o) = 0;
22169 (o + 1) as c_int
22170}
22171
22172#[repr(C)]
22177#[derive(Copy, Clone)]
22178pub struct Spwd {
22179 pub sp_namp: *mut c_char,
22180 pub sp_pwdp: *mut c_char,
22181 pub sp_lstchg: c_long,
22182 pub sp_min: c_long,
22183 pub sp_max: c_long,
22184 pub sp_warn: c_long,
22185 pub sp_inact: c_long,
22186 pub sp_expire: c_long,
22187 pub sp_flag: c_ulong,
22188}
22189
22190static mut SPWD_ENT: Spwd = Spwd {
22191 sp_namp: core::ptr::null_mut(), sp_pwdp: core::ptr::null_mut(),
22192 sp_lstchg: 0, sp_min: 0, sp_max: 0, sp_warn: 0, sp_inact: 0,
22193 sp_expire: 0, sp_flag: 0,
22194};
22195static mut SPWD_BUF: [c_char; 1024] = [0; 1024];
22196static mut SPWD_FILE: *mut FILE = core::ptr::null_mut();
22197
22198unsafe fn parse_spwd(line: *const c_char, ent: *mut Spwd, buf: *mut c_char, buflen: usize) -> bool {
22199 let mut src = line;
22200 let mut o = 0usize;
22201 let mut fields: [*mut c_char; 9] = [core::ptr::null_mut(); 9];
22202 let mut n = 0usize;
22203 while n < 9 {
22204 let start = o;
22205 while *src != 0 && *src != b':' as c_char {
22206 if o + 1 >= buflen { return false; }
22207 *buf.add(o) = *src;
22208 o += 1;
22209 src = src.add(1);
22210 }
22211 *buf.add(o) = 0;
22212 o += 1;
22213 fields[n] = buf.add(start);
22214 n += 1;
22215 if *src == 0 { break; }
22216 src = src.add(1);
22217 }
22218 if n < 9 { return false; }
22219 (*ent).sp_namp = fields[0];
22220 (*ent).sp_pwdp = fields[1];
22221 (*ent).sp_lstchg = crate::strtol(fields[2], core::ptr::null_mut(), 10) as c_long;
22222 (*ent).sp_min = crate::strtol(fields[3], core::ptr::null_mut(), 10) as c_long;
22223 (*ent).sp_max = crate::strtol(fields[4], core::ptr::null_mut(), 10) as c_long;
22224 (*ent).sp_warn = crate::strtol(fields[5], core::ptr::null_mut(), 10) as c_long;
22225 (*ent).sp_inact = crate::strtol(fields[6], core::ptr::null_mut(), 10) as c_long;
22226 (*ent).sp_expire = crate::strtol(fields[7], core::ptr::null_mut(), 10) as c_long;
22227 (*ent).sp_flag = crate::strtoul(fields[8], core::ptr::null_mut(), 10) as c_ulong;
22228 true
22229}
22230
22231#[no_mangle]
22232pub unsafe extern "C" fn setspent() {
22233 endspent();
22234 SPWD_FILE = crate::fopen(b"/etc/shadow\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
22235}
22236
22237#[no_mangle]
22238pub unsafe extern "C" fn endspent() {
22239 if !SPWD_FILE.is_null() { crate::fclose(SPWD_FILE); SPWD_FILE = core::ptr::null_mut(); }
22240}
22241
22242#[no_mangle]
22243pub unsafe extern "C" fn getspent() -> *mut Spwd {
22244 if SPWD_FILE.is_null() { setspent(); if SPWD_FILE.is_null() { return core::ptr::null_mut(); } }
22245 let mut line = [0 as c_char; 1024];
22246 loop {
22247 if crate::fgets(line.as_mut_ptr(), 1024, SPWD_FILE).is_null() { return core::ptr::null_mut(); }
22248 if parse_spwd(line.as_ptr(), &raw mut SPWD_ENT, SPWD_BUF.as_mut_ptr(), SPWD_BUF.len()) {
22249 return &raw mut SPWD_ENT;
22250 }
22251 }
22252}
22253
22254#[no_mangle]
22255pub unsafe extern "C" fn fgetspent(f: *mut FILE) -> *mut Spwd {
22256 if f.is_null() { return core::ptr::null_mut(); }
22257 let mut line = [0 as c_char; 1024];
22258 loop {
22259 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
22260 if parse_spwd(line.as_ptr(), &raw mut SPWD_ENT, SPWD_BUF.as_mut_ptr(), SPWD_BUF.len()) {
22261 return &raw mut SPWD_ENT;
22262 }
22263 }
22264}
22265
22266#[no_mangle]
22267pub unsafe extern "C" fn getspnam(name: *const c_char) -> *mut Spwd {
22268 if name.is_null() { return core::ptr::null_mut(); }
22269 setspent();
22270 loop {
22271 let sp = getspent();
22272 if sp.is_null() { break; }
22273 if crate::strcmp((*sp).sp_namp as *const u8, name as *const u8) == 0 { endspent(); return sp; }
22274 }
22275 endspent();
22276 core::ptr::null_mut()
22277}
22278
22279#[no_mangle]
22280pub 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 {
22281 if result.is_null() { return EINVAL; }
22282 let p = getspnam(name);
22283 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *sp = *p; *result = sp; 0 }
22284}
22285
22286#[no_mangle]
22287pub unsafe extern "C" fn putspent(sp: *const Spwd, f: *mut FILE) -> c_int {
22288 if sp.is_null() || f.is_null() { return -1; }
22289 crate::fprintf(f, b"%s:%s:%ld:%ld:%ld:%ld:%ld:%ld:%lu\\n\0".as_ptr() as *const c_char,
22290 (*sp).sp_namp, (*sp).sp_pwdp, (*sp).sp_lstchg, (*sp).sp_min, (*sp).sp_max,
22291 (*sp).sp_warn, (*sp).sp_inact, (*sp).sp_expire, (*sp).sp_flag)
22292}
22293
22294#[no_mangle]
22295pub unsafe extern "C" fn getgrouplist(user: *const c_char, group: u32, groups: *mut u32, ngroups: *mut i32) -> c_int {
22296 if user.is_null() || groups.is_null() || ngroups.is_null() { return -1; }
22297 let max = *ngroups as usize;
22298 let mut n = 0usize;
22299 if n < max { *groups.add(n) = group; }
22300 n += 1;
22301 setgrent();
22302 loop {
22303 let g = getgrent();
22304 if g.is_null() { break; }
22305 if (*g).gr_gid == group { continue; }
22306 let mut found = false;
22307 let mut i = 0;
22308 while !(*(*g).gr_mem.add(i)).is_null() {
22309 if crate::strcmp(*(*g).gr_mem.add(i) as *const u8, user as *const u8) == 0 {
22310 found = true;
22311 break;
22312 }
22313 i += 1;
22314 }
22315 if found {
22316 if n < max { *groups.add(n) = (*g).gr_gid; }
22317 n += 1;
22318 }
22319 }
22320 endgrent();
22321 if n > max { *ngroups = n as i32; return -1; }
22322 *ngroups = n as i32;
22323 n as c_int
22324}