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_erf.rs");
26include!("math_lgamma.rs");
27include!("math_tgamma.rs");
28include!("math_bessel.rs");
29include!("alloc.rs");
30include!("math_log.rs");
31include!("math_pow.rs");
32include!("math_hypot.rs");
33include!("math_hyperbolic.rs");
34include!("math_invtrig.rs");
35include!("math_lrint.rs");
36include!("math_long_double.rs");
37
38const EILSEQ: c_int = 84;
43const EINVAL: c_int = 22;
44const EFAULT: c_int = 14;
45const E2BIG: c_int = 7;
46
47const LC_CTYPE: c_int = 0;
48const LC_NUMERIC: c_int = 1;
49const LC_TIME: c_int = 2;
50const LC_COLLATE: c_int = 3;
51const LC_MONETARY: c_int = 4;
52const LC_MESSAGES: c_int = 5;
53const LC_ALL: c_int = 6;
54const ENOMEM: c_int = 12;
55const EINTR: c_int = 4;
56const EPERM: c_int = 1;
57const EAGAIN: c_int = 11;
58const EBUSY: c_int = 16;
59const EDEADLK: c_int = 35;
60const ETIMEDOUT: c_int = 110;
61const ECANCELED: c_int = 125;
62const EOVERFLOW: c_int = 75;
63const EOWNERDEAD: c_int = 130;
64const ENOTRECOVERABLE: c_int = 131;
65
66static mut ERRNO: c_int = 0;
67
68#[no_mangle]
69pub unsafe extern "C" fn __errno_location() -> *mut c_int {
70 core::ptr::addr_of_mut!(ERRNO)
71}
72
73#[cfg(not(test))]
74#[panic_handler]
75fn panic(_: &core::panic::PanicInfo) -> ! {
76 loop {}
77}
78
79#[cfg(not(test))]
81#[no_mangle]
82pub extern "C" fn rust_eh_personality() {}
83
84const PROT_READ: i32 = 1;
89const PROT_WRITE: i32 = 2;
90const MAP_SHARED: i32 = 0x01;
91const MAP_PRIVATE: i32 = 0x02;
92const MAP_ANONYMOUS: i32 = 0x20;
93
94trait Syscalls {
99 unsafe fn syscall0(n: i64) -> i64;
100 unsafe fn syscall1(n: i64, a1: i64) -> i64;
101 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64;
102 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64;
103 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64;
104 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64;
105 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64;
106 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> !;
107}
108
109struct X86_64;
110struct Aarch64;
111struct Riscv64;
112
113#[cfg(target_arch = "x86_64")]
114impl Syscalls for X86_64 {
115 #[inline(always)]
116 unsafe fn syscall0(n: i64) -> i64 {
117 let result: i64;
118 core::arch::asm!(
119 "syscall",
120 inlateout("rax") n => result,
121 lateout("rcx") _,
122 lateout("r11") _,
123 );
124 result
125 }
126 #[inline(always)]
127 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
128 let result: i64;
129 core::arch::asm!(
130 "syscall",
131 inlateout("rax") n => result,
132 in("rdi") a1,
133 lateout("rcx") _,
134 lateout("r11") _,
135 );
136 result
137 }
138 #[inline(always)]
139 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
140 let result: i64;
141 core::arch::asm!(
142 "syscall",
143 inlateout("rax") n => result,
144 in("rdi") a1,
145 in("rsi") a2,
146 lateout("rcx") _,
147 lateout("r11") _,
148 );
149 result
150 }
151 #[inline(always)]
152 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
153 let result: i64;
154 core::arch::asm!(
155 "syscall",
156 inlateout("rax") n => result,
157 in("rdi") a1,
158 in("rsi") a2,
159 in("rdx") a3,
160 lateout("rcx") _,
161 lateout("r11") _,
162 );
163 result
164 }
165 #[inline(always)]
166 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
167 let result: i64;
168 core::arch::asm!(
169 "syscall",
170 inlateout("rax") n => result,
171 in("rdi") a1,
172 in("rsi") a2,
173 in("rdx") a3,
174 in("r10") a4,
175 lateout("rcx") _,
176 lateout("r11") _,
177 );
178 result
179 }
180 #[inline(always)]
181 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
182 let result: i64;
183 core::arch::asm!(
184 "syscall",
185 inlateout("rax") n => result,
186 in("rdi") a1,
187 in("rsi") a2,
188 in("rdx") a3,
189 in("r10") a4,
190 in("r8") a5,
191 lateout("rcx") _,
192 lateout("r11") _,
193 );
194 result
195 }
196 #[inline(always)]
197 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
198 let result: i64;
199 core::arch::asm!(
200 "syscall",
201 inlateout("rax") n => result,
202 in("rdi") a1,
203 in("rsi") a2,
204 in("rdx") a3,
205 in("r10") a4,
206 in("r8") a5,
207 in("r9") a6,
208 lateout("rcx") _,
209 lateout("r11") _,
210 );
211 result
212 }
213 #[inline(always)]
214 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
215 core::arch::asm!(
216 "syscall",
217 in("rax") n,
218 in("rdi") a1,
219 options(noreturn)
220 );
221 }
222}
223
224#[cfg(target_arch = "aarch64")]
225impl Syscalls for Aarch64 {
226 #[inline(always)]
227 unsafe fn syscall0(n: i64) -> i64 {
228 let result: i64;
229 core::arch::asm!(
230 "svc #0",
231 inlateout("x8") n => _,
232 lateout("x0") result,
233 options(nostack),
234 );
235 result
236 }
237 #[inline(always)]
238 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
239 let result: i64;
240 core::arch::asm!(
241 "svc #0",
242 inlateout("x8") n => _,
243 inlateout("x0") a1 => result,
244 options(nostack),
245 );
246 result
247 }
248 #[inline(always)]
249 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
250 let result: i64;
251 core::arch::asm!(
252 "svc #0",
253 inlateout("x8") n => _,
254 inlateout("x0") a1 => result,
255 inlateout("x1") a2 => _,
256 options(nostack),
257 );
258 result
259 }
260 #[inline(always)]
261 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
262 let result: i64;
263 core::arch::asm!(
264 "svc #0",
265 inlateout("x8") n => _,
266 inlateout("x0") a1 => result,
267 inlateout("x1") a2 => _,
268 inlateout("x2") a3 => _,
269 options(nostack),
270 );
271 result
272 }
273 #[inline(always)]
274 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
275 let result: i64;
276 core::arch::asm!(
277 "svc #0",
278 inlateout("x8") n => _,
279 inlateout("x0") a1 => result,
280 inlateout("x1") a2 => _,
281 inlateout("x2") a3 => _,
282 inlateout("x3") a4 => _,
283 options(nostack),
284 );
285 result
286 }
287 #[inline(always)]
288 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
289 let result: i64;
290 core::arch::asm!(
291 "svc #0",
292 inlateout("x8") n => _,
293 inlateout("x0") a1 => result,
294 inlateout("x1") a2 => _,
295 inlateout("x2") a3 => _,
296 inlateout("x3") a4 => _,
297 inlateout("x4") a5 => _,
298 options(nostack),
299 );
300 result
301 }
302 #[inline(always)]
303 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
304 let result: i64;
305 core::arch::asm!(
306 "svc #0",
307 inlateout("x8") n => _,
308 inlateout("x0") a1 => result,
309 inlateout("x1") a2 => _,
310 inlateout("x2") a3 => _,
311 inlateout("x3") a4 => _,
312 inlateout("x4") a5 => _,
313 inlateout("x5") a6 => _,
314 options(nostack),
315 );
316 result
317 }
318 #[inline(always)]
319 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
320 core::arch::asm!(
321 "svc #0",
322 in("x8") n,
323 in("x0") a1,
324 options(noreturn, nostack),
325 );
326 }
327}
328
329#[cfg(target_arch = "riscv64")]
330impl Syscalls for Riscv64 {
331 #[inline(always)]
332 unsafe fn syscall0(n: i64) -> i64 {
333 let result: i64;
334 core::arch::asm!(
335 "ecall",
336 inlateout("a7") n => _,
337 lateout("a0") result,
338 options(nostack),
339 );
340 result
341 }
342 #[inline(always)]
343 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
344 let result: i64;
345 core::arch::asm!(
346 "ecall",
347 inlateout("a7") n => _,
348 inlateout("a0") a1 => result,
349 options(nostack),
350 );
351 result
352 }
353 #[inline(always)]
354 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
355 let result: i64;
356 core::arch::asm!(
357 "ecall",
358 inlateout("a7") n => _,
359 inlateout("a0") a1 => result,
360 inlateout("a1") a2 => _,
361 options(nostack),
362 );
363 result
364 }
365 #[inline(always)]
366 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
367 let result: i64;
368 core::arch::asm!(
369 "ecall",
370 inlateout("a7") n => _,
371 inlateout("a0") a1 => result,
372 inlateout("a1") a2 => _,
373 inlateout("a2") a3 => _,
374 options(nostack),
375 );
376 result
377 }
378 #[inline(always)]
379 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
380 let result: i64;
381 core::arch::asm!(
382 "ecall",
383 inlateout("a7") n => _,
384 inlateout("a0") a1 => result,
385 inlateout("a1") a2 => _,
386 inlateout("a2") a3 => _,
387 inlateout("a3") a4 => _,
388 options(nostack),
389 );
390 result
391 }
392 #[inline(always)]
393 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
394 let result: i64;
395 core::arch::asm!(
396 "ecall",
397 inlateout("a7") n => _,
398 inlateout("a0") a1 => result,
399 inlateout("a1") a2 => _,
400 inlateout("a2") a3 => _,
401 inlateout("a3") a4 => _,
402 inlateout("a4") a5 => _,
403 options(nostack),
404 );
405 result
406 }
407 #[inline(always)]
408 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
409 let result: i64;
410 core::arch::asm!(
411 "ecall",
412 inlateout("a7") n => _,
413 inlateout("a0") a1 => result,
414 inlateout("a1") a2 => _,
415 inlateout("a2") a3 => _,
416 inlateout("a3") a4 => _,
417 inlateout("a4") a5 => _,
418 inlateout("a5") a6 => _,
419 options(nostack),
420 );
421 result
422 }
423 #[inline(always)]
424 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
425 core::arch::asm!(
426 "ecall",
427 in("a7") n,
428 in("a0") a1,
429 options(noreturn, nostack),
430 );
431 }
432}
433
434#[cfg(target_arch = "x86_64")]
435type Arch = X86_64;
436#[cfg(target_arch = "aarch64")]
437type Arch = Aarch64;
438#[cfg(target_arch = "riscv64")]
439type Arch = Riscv64;
440
441
442
443#[cfg(target_arch = "x86_64")]
445mod sysnr {
446 pub const SYS_READ: i64 = 0;
447 pub const SYS_WRITE: i64 = 1;
448 pub const SYS_OPEN: i64 = 2;
449 pub const SYS_CLOSE: i64 = 3;
450 pub const SYS_STAT: i64 = 4;
451 pub const SYS_FSTAT: i64 = 5;
452 pub const SYS_LSEEK: i64 = 8;
453 pub const SYS_MMAP: i64 = 9;
454 pub const SYS_MUNMAP: i64 = 11;
455 pub const SYS_MPROTECT: i64 = 10;
456 pub const SYS_RT_SIGACTION: i64 = 13;
457 pub const SYS_RT_SIGPROCMASK: i64 = 14;
458 pub const SYS_IOCTL: i64 = 16;
459 pub const SYS_ACCESS: i64 = 21;
460 pub const SYS_SHMGET: i64 = 29;
461 pub const SYS_SHMAT: i64 = 30;
462 pub const SYS_SHMCTL: i64 = 31;
463 pub const SYS_DUP: i64 = 32;
464 pub const SYS_NANOSLEEP: i64 = 35;
465 pub const SYS_SETITIMER: i64 = 38;
466 pub const SYS_ALARM: i64 = 37;
467 pub const SYS_SOCKET: i64 = 41;
468 pub const SYS_CONNECT: i64 = 42;
469 pub const SYS_ACCEPT: i64 = 43;
470 pub const SYS_ACCEPT4: i64 = 288;
471 pub const SYS_SENDTO: i64 = 44;
472 pub const SYS_RECVFROM: i64 = 45;
473 pub const SYS_SENDMSG: i64 = 46;
474 pub const SYS_RECVMSG: i64 = 47;
475 pub const SYS_SHUTDOWN: i64 = 48;
476 pub const SYS_BIND: i64 = 49;
477 pub const SYS_LISTEN: i64 = 50;
478 pub const SYS_GETSOCKNAME: i64 = 51;
479 pub const SYS_SOCKETPAIR: i64 = 53;
480 pub const SYS_SETSOCKOPT: i64 = 54;
481 pub const SYS_EXECVE: i64 = 59;
482 pub const SYS_WAIT4: i64 = 61;
483 pub const SYS_KILL: i64 = 62;
484 pub const SYS_UNAME: i64 = 63;
485 pub const SYS_SEMGET: i64 = 64;
486 pub const SYS_SEMOP: i64 = 65;
487 pub const SYS_SEMCTL: i64 = 66;
488 pub const SYS_SHMDT: i64 = 67;
489 pub const SYS_MSGGET: i64 = 68;
490 pub const SYS_MSGSND: i64 = 69;
491 pub const SYS_MSGRCV: i64 = 70;
492 pub const SYS_MSGCTL: i64 = 71;
493 pub const SYS_FCNTL: i64 = 72;
494 pub const SYS_FSYNC: i64 = 74;
495 pub const SYS_TRUNCATE: i64 = 76;
496 pub const SYS_FTRUNCATE: i64 = 77;
497 pub const SYS_GETCWD: i64 = 79;
498 pub const SYS_CHDIR: i64 = 80;
499 pub const SYS_SYMLINK: i64 = 88;
500 pub const SYS_FCHMOD: i64 = 91;
501 pub const SYS_UMASK: i64 = 95;
502 pub const SYS_GETRLIMIT: i64 = 97;
503 pub const SYS_SETUID: i64 = 105;
504 pub const SYS_SETGID: i64 = 106;
505 pub const SYS_SETPGID: i64 = 109;
506 pub const SYS_GETGROUPS: i64 = 115;
507 pub const SYS_GETPGID: i64 = 121;
508 pub const SYS_GETSID: i64 = 124;
509 pub const SYS_RT_SIGPENDING: i64 = 127;
510 pub const SYS_RT_SIGTIMEDWAIT: i64 = 128;
511 pub const SYS_RT_SIGSUSPEND: i64 = 130;
512 pub const SYS_SIGALTSTACK: i64 = 131;
513 pub const SYS_SETRLIMIT: i64 = 160;
514 pub const SYS_SETHOSTNAME: i64 = 170;
515 pub const SYS_FUTEX: i64 = 202;
516 pub const SYS_CLOCK_GETTIME: i64 = 228;
517 pub const SYS_CLOCK_GETRES: i64 = 229;
518 pub const SYS_CLOCK_NANOSLEEP: i64 = 230;
519 pub const SYS_EXIT_GROUP: i64 = 231;
520 pub const SYS_TGKILL: i64 = 234;
521 pub const SYS_MKDIRAT: i64 = 258;
522 pub const SYS_NEWFSTATAT: i64 = 262;
523 pub const SYS_UNLINKAT: i64 = 263;
524 pub const SYS_LINKAT: i64 = 265;
525 pub const SYS_SYMLINKAT: i64 = 266;
526 pub const SYS_READLINKAT: i64 = 267;
527 pub const SYS_FCHMODAT: i64 = 268;
528 pub const SYS_SET_ROBUST_LIST: i64 = 273;
529 pub const SYS_UTIMENSAT: i64 = 280;
530 pub const SYS_OPENAT: i64 = 257;
531 pub const SYS_FACCESSAT: i64 = 269;
532 pub const SYS_DUP3: i64 = 292;
533 pub const SYS_PIPE2: i64 = 293;
534 pub const SYS_SYNCFS: i64 = 306;
535 pub const SYS_RENAMEAT2: i64 = 316;
536 pub const SYS_STATFS: i64 = 137;
537 pub const SYS_FSTATFS: i64 = 138;
538 pub const SYS_FDATASYNC: i64 = 75;
539 pub const SYS_PAUSE: i64 = 34;
540 pub const SYS_POLL: i64 = 7;
541 pub const SYS_PPOLL: i64 = 271;
542 pub const SYS_PSELECT6: i64 = 270;
543 pub const SYS_GETPID: i64 = 39;
544 pub const SYS_FORK: i64 = 57;
545 pub const SYS_EXIT: i64 = 60;
546 pub const SYS_GETPPID: i64 = 110;
547 pub const SYS_SETSID: i64 = 112;
548 pub const SYS_SYNC: i64 = 162;
549 pub const SYS_GETUID: i64 = 102;
550 pub const SYS_GETGID: i64 = 104;
551 pub const SYS_GETEUID: i64 = 107;
552 pub const SYS_GETEGID: i64 = 108;
553 pub const SYS_GETTID: i64 = 186;
554 pub const SYS_CLOCK_SETTIME: i64 = 227;
555 pub const SYS_CLONE: i64 = 56;
556 pub const SYS_PREAD64: i64 = 17;
557 pub const SYS_MREMAP: i64 = 25;
558 pub const SYS_SYSINFO: i64 = 99;
559 pub const SYS_MEMBARRIER: i64 = 324;
560 pub const SYS_VHANGUP: i64 = 153;
561 pub const SYS_VMSPLICE: i64 = 278;
562 pub const SYS_GETDENTS64: i64 = 217;
563 pub const SYS_EPOLL_CREATE: i64 = 232;
564 pub const SYS_EPOLL_CREATE1: i64 = 291;
565 pub const SYS_EPOLL_CTL: i64 = 233;
566 pub const SYS_EPOLL_WAIT: i64 = 234;
567 pub const SYS_EVENTFD2: i64 = 290;
568 pub const SYS_SIGNALFD4: i64 = 289;
569 pub const SYS_TIMERFD_CREATE: i64 = 283;
570 pub const SYS_TIMERFD_SETTIME: i64 = 286;
571 pub const SYS_TIMERFD_GETTIME: i64 = 287;
572 pub const SYS_PRCTL: i64 = 157;
573 pub const SYS_FALLOCATE: i64 = 285;
574 pub const SYS_FLOCK: i64 = 73;
575 pub const SYS_SETGROUPS: i64 = 116;
576 pub const SYS_SETRESUID: i64 = 117;
577 pub const SYS_SETRESGID: i64 = 119;
578 pub const SYS_GETRESUID: i64 = 118;
579 pub const SYS_GETRESGID: i64 = 120;
580 pub const SYS_MKNOD: i64 = 133;
581 pub const SYS_FCHDIR: i64 = 81;
582 pub const SYS_FCHOWN: i64 = 93;
583 pub const SYS_ACCT: i64 = 163;
584 pub const SYS_ADJTIMEX: i64 = 159;
585 pub const SYS_CAPGET: i64 = 125;
586 pub const SYS_CAPSET: i64 = 126;
587 pub const SYS_CHROOT: i64 = 161;
588 pub const SYS_COPY_FILE_RANGE: i64 = 326;
589 pub const SYS_DELETE_MODULE: i64 = 176;
590 pub const SYS_INIT_MODULE: i64 = 175;
591 pub const SYS_FCHOWNAT: i64 = 260;
592 pub const SYS_MKNODAT: i64 = 259;
593 pub const SYS_SETNS: i64 = 308;
594 pub const SYS_UNSHARE: i64 = 272;
595 pub const SYS_REBOOT: i64 = 169;
596 pub const SYS_NICE: i64 = 34;
597 pub const SYS_SETPRIORITY: i64 = 140;
598 pub const SYS_GETPRIORITY: i64 = 140;
599 pub const SYS_IOPERM: i64 = 173;
600 pub const SYS_IOPL: i64 = 172;
601 pub const SYS_SWAPON: i64 = 167;
602 pub const SYS_SWAPOFF: i64 = 168;
603 pub const SYS_MOUNT: i64 = 165;
604 pub const SYS_UMOUNT2: i64 = 166;
605 pub const SYS_PIVOT_ROOT: i64 = 155;
606 pub const SYS_SETTIMEOFDAY: i64 = 164;
607 pub const SYS_GETTIMEOFDAY: i64 = 96;
608}
609#[cfg(target_arch = "aarch64")]
610mod sysnr {
611 pub const SYS_READ: i64 = 63;
612 pub const SYS_WRITE: i64 = 64;
613 pub const SYS_CLOSE: i64 = 57;
615 pub const SYS_FSTAT: i64 = 80;
617 pub const SYS_LSEEK: i64 = 62;
618 pub const SYS_MMAP: i64 = 222;
619 pub const SYS_MUNMAP: i64 = 215;
620 pub const SYS_RT_SIGACTION: i64 = 134;
621 pub const SYS_RT_SIGPROCMASK: i64 = 135;
622 pub const SYS_IOCTL: i64 = 29;
623 pub const SYS_SHMGET: i64 = 194;
625 pub const SYS_SHMAT: i64 = 196;
626 pub const SYS_SHMCTL: i64 = 195;
627 pub const SYS_DUP: i64 = 23;
628 pub const SYS_NANOSLEEP: i64 = 101;
629 pub const SYS_SETITIMER: i64 = 103;
630 pub const SYS_SOCKET: i64 = 198;
632 pub const SYS_CONNECT: i64 = 203;
633 pub const SYS_ACCEPT: i64 = 202;
634 pub const SYS_SENDTO: i64 = 206;
635 pub const SYS_RECVFROM: i64 = 207;
636 pub const SYS_SHUTDOWN: i64 = 210;
637 pub const SYS_BIND: i64 = 200;
638 pub const SYS_LISTEN: i64 = 201;
639 pub const SYS_GETSOCKNAME: i64 = 204;
640 pub const SYS_SOCKETPAIR: i64 = 199;
641 pub const SYS_SETSOCKOPT: i64 = 208;
642 pub const SYS_EXECVE: i64 = 221;
643 pub const SYS_WAIT4: i64 = 260;
644 pub const SYS_KILL: i64 = 129;
645 pub const SYS_UNAME: i64 = 160;
646 pub const SYS_SEMGET: i64 = 190;
647 pub const SYS_SEMOP: i64 = 193;
648 pub const SYS_SEMCTL: i64 = 191;
649 pub const SYS_SHMDT: i64 = 197;
650 pub const SYS_MSGGET: i64 = 186;
651 pub const SYS_MSGSND: i64 = 189;
652 pub const SYS_MSGRCV: i64 = 188;
653 pub const SYS_MSGCTL: i64 = 187;
654 pub const SYS_FCNTL: i64 = 25;
655 pub const SYS_FSYNC: i64 = 82;
656 pub const SYS_TRUNCATE: i64 = 45;
657 pub const SYS_FTRUNCATE: i64 = 46;
658 pub const SYS_GETCWD: i64 = 17;
659 pub const SYS_CHDIR: i64 = 49;
660 pub const SYS_FCHMOD: i64 = 52;
662 pub const SYS_UMASK: i64 = 166;
663 pub const SYS_GETRLIMIT: i64 = 163;
664 pub const SYS_SETUID: i64 = 146;
665 pub const SYS_SETGID: i64 = 144;
666 pub const SYS_SETPGID: i64 = 154;
667 pub const SYS_GETGROUPS: i64 = 158;
668 pub const SYS_GETPGID: i64 = 155;
669 pub const SYS_GETSID: i64 = 156;
670 pub const SYS_RT_SIGPENDING: i64 = 136;
671 pub const SYS_RT_SIGTIMEDWAIT: i64 = 137;
672 pub const SYS_RT_SIGSUSPEND: i64 = 133;
673 pub const SYS_SIGALTSTACK: i64 = 132;
674 pub const SYS_SETRLIMIT: i64 = 164;
675 pub const SYS_SETHOSTNAME: i64 = 161;
676 pub const SYS_FUTEX: i64 = 98;
677 pub const SYS_CLOCK_GETTIME: i64 = 113;
678 pub const SYS_CLOCK_GETRES: i64 = 114;
679 pub const SYS_CLOCK_NANOSLEEP: i64 = 115;
680 pub const SYS_EXIT_GROUP: i64 = 94;
681 pub const SYS_TGKILL: i64 = 131;
682 pub const SYS_MKDIRAT: i64 = 34;
683 pub const SYS_NEWFSTATAT: i64 = 79;
684 pub const SYS_UNLINKAT: i64 = 35;
685 pub const SYS_LINKAT: i64 = 37;
686 pub const SYS_SYMLINKAT: i64 = 36;
687 pub const SYS_READLINKAT: i64 = 78;
688 pub const SYS_FCHMODAT: i64 = 53;
689 pub const SYS_SET_ROBUST_LIST: i64 = 99;
690 pub const SYS_UTIMENSAT: i64 = 88;
691 pub const SYS_OPENAT: i64 = 56;
692 pub const SYS_FACCESSAT: i64 = 48;
693 pub const SYS_DUP3: i64 = 24;
694 pub const SYS_PIPE2: i64 = 59;
695 pub const SYS_SYNCFS: i64 = 267;
696 pub const SYS_RENAMEAT2: i64 = 276;
697 pub const SYS_STATFS: i64 = 43;
698 pub const SYS_FSTATFS: i64 = 44;
699 pub const SYS_FDATASYNC: i64 = 83;
700 pub const SYS_GETPID: i64 = 172;
701 pub const SYS_EXIT: i64 = 93;
702 pub const SYS_GETPPID: i64 = 173;
703 pub const SYS_SETSID: i64 = 157;
704 pub const SYS_SYNC: i64 = 81;
705 pub const SYS_GETUID: i64 = 174;
706 pub const SYS_GETGID: i64 = 176;
707 pub const SYS_GETEUID: i64 = 175;
708 pub const SYS_GETEGID: i64 = 177;
709 pub const SYS_GETTID: i64 = 178;
710 pub const SYS_CLOCK_SETTIME: i64 = 112;
711 pub const SYS_CLONE: i64 = 220;
712 pub const SYS_PPOLL: i64 = 73;
713 pub const SYS_PREAD64: i64 = 67;
714 pub const SYS_MREMAP: i64 = 216;
715 pub const SYS_SYSINFO: i64 = 179;
716 pub const SYS_MEMBARRIER: i64 = 283;
717 pub const SYS_VHANGUP: i64 = 58;
718 pub const SYS_VMSPLICE: i64 = 75;
719 pub const SYS_GETTIMEOFDAY: i64 = 169;
720 pub const SYS_SETTIMEOFDAY: i64 = 170;
721 pub const SYS_ADJTIMEX: i64 = 171;
722 pub const SYS_EPOLL_CREATE1: i64 = 20;
723 pub const SYS_EPOLL_CTL: i64 = 21;
724 pub const SYS_EPOLL_WAIT: i64 = 22;
725 pub const SYS_EVENTFD2: i64 = 19;
726 pub const SYS_SIGNALFD4: i64 = 74;
727 pub const SYS_TIMERFD_CREATE: i64 = 85;
728 pub const SYS_TIMERFD_SETTIME: i64 = 86;
729 pub const SYS_TIMERFD_GETTIME: i64 = 87;
730 pub const SYS_ACCEPT4: i64 = 242;
731 pub const SYS_ACCT: i64 = 89;
732 pub const SYS_CAPGET: i64 = 90;
733 pub const SYS_CAPSET: i64 = 91;
734 pub const SYS_CHROOT: i64 = 51;
735 pub const SYS_COPY_FILE_RANGE: i64 = 285;
736 pub const SYS_DELETE_MODULE: i64 = 106;
737 pub const SYS_FALLOCATE: i64 = 47;
738 pub const SYS_FCHDIR: i64 = 50;
739 pub const SYS_FCHOWN: i64 = 55;
740 pub const SYS_FCHOWNAT: i64 = 54;
741 pub const SYS_FLOCK: i64 = 32;
742 pub const SYS_GETDENTS64: i64 = 61;
743 pub const SYS_GETPRIORITY: i64 = 141;
744 pub const SYS_GETRESGID: i64 = 150;
745 pub const SYS_GETRESUID: i64 = 148;
746 pub const SYS_INIT_MODULE: i64 = 105;
747 pub const SYS_MKNODAT: i64 = 33;
748 pub const SYS_MOUNT: i64 = 40;
749 pub const SYS_MPROTECT: i64 = 226;
750 pub const SYS_PIVOT_ROOT: i64 = 41;
751 pub const SYS_PRCTL: i64 = 167;
752 pub const SYS_PSELECT6: i64 = 72;
753 pub const SYS_REBOOT: i64 = 142;
754 pub const SYS_RECVMSG: i64 = 212;
755 pub const SYS_SENDMSG: i64 = 211;
756 pub const SYS_SETGROUPS: i64 = 159;
757 pub const SYS_SETNS: i64 = 268;
758 pub const SYS_SETPRIORITY: i64 = 140;
759 pub const SYS_SETRESGID: i64 = 149;
760 pub const SYS_SETRESUID: i64 = 147;
761 pub const SYS_SWAPOFF: i64 = 225;
762 pub const SYS_SWAPON: i64 = 224;
763 pub const SYS_UMOUNT2: i64 = 39;
764 pub const SYS_UNSHARE: i64 = 97;
765}
766#[cfg(target_arch = "riscv64")]
768mod sysnr {
769 pub const SYS_READ: i64 = 63;
770 pub const SYS_WRITE: i64 = 64;
771 pub const SYS_CLOSE: i64 = 57;
772 pub const SYS_FSTAT: i64 = 80;
773 pub const SYS_LSEEK: i64 = 62;
774 pub const SYS_MMAP: i64 = 222;
775 pub const SYS_MUNMAP: i64 = 215;
776 pub const SYS_RT_SIGACTION: i64 = 134;
777 pub const SYS_RT_SIGPROCMASK: i64 = 135;
778 pub const SYS_IOCTL: i64 = 29;
779 pub const SYS_SHMGET: i64 = 194;
780 pub const SYS_SHMAT: i64 = 196;
781 pub const SYS_SHMCTL: i64 = 195;
782 pub const SYS_DUP: i64 = 23;
783 pub const SYS_NANOSLEEP: i64 = 101;
784 pub const SYS_SETITIMER: i64 = 103;
785 pub const SYS_SOCKET: i64 = 198;
786 pub const SYS_CONNECT: i64 = 203;
787 pub const SYS_ACCEPT: i64 = 202;
788 pub const SYS_SENDTO: i64 = 206;
789 pub const SYS_RECVFROM: i64 = 207;
790 pub const SYS_SHUTDOWN: i64 = 210;
791 pub const SYS_BIND: i64 = 200;
792 pub const SYS_LISTEN: i64 = 201;
793 pub const SYS_GETSOCKNAME: i64 = 204;
794 pub const SYS_SOCKETPAIR: i64 = 199;
795 pub const SYS_SETSOCKOPT: i64 = 208;
796 pub const SYS_EXECVE: i64 = 221;
797 pub const SYS_WAIT4: i64 = 260;
798 pub const SYS_KILL: i64 = 129;
799 pub const SYS_UNAME: i64 = 160;
800 pub const SYS_SEMGET: i64 = 190;
801 pub const SYS_SEMOP: i64 = 193;
802 pub const SYS_SEMCTL: i64 = 191;
803 pub const SYS_SHMDT: i64 = 197;
804 pub const SYS_MSGGET: i64 = 186;
805 pub const SYS_MSGSND: i64 = 189;
806 pub const SYS_MSGRCV: i64 = 188;
807 pub const SYS_MSGCTL: i64 = 187;
808 pub const SYS_FCNTL: i64 = 25;
809 pub const SYS_FSYNC: i64 = 82;
810 pub const SYS_TRUNCATE: i64 = 45;
811 pub const SYS_FTRUNCATE: i64 = 46;
812 pub const SYS_GETCWD: i64 = 17;
813 pub const SYS_CHDIR: i64 = 49;
814 pub const SYS_FCHMOD: i64 = 52;
815 pub const SYS_UMASK: i64 = 166;
816 pub const SYS_GETRLIMIT: i64 = 163;
817 pub const SYS_SETUID: i64 = 146;
818 pub const SYS_SETGID: i64 = 144;
819 pub const SYS_SETPGID: i64 = 154;
820 pub const SYS_GETGROUPS: i64 = 158;
821 pub const SYS_GETPGID: i64 = 155;
822 pub const SYS_GETSID: i64 = 156;
823 pub const SYS_RT_SIGPENDING: i64 = 136;
824 pub const SYS_RT_SIGTIMEDWAIT: i64 = 137;
825 pub const SYS_RT_SIGSUSPEND: i64 = 133;
826 pub const SYS_SIGALTSTACK: i64 = 132;
827 pub const SYS_SETRLIMIT: i64 = 164;
828 pub const SYS_SETHOSTNAME: i64 = 161;
829 pub const SYS_FUTEX: i64 = 98;
830 pub const SYS_CLOCK_GETTIME: i64 = 113;
831 pub const SYS_CLOCK_GETRES: i64 = 114;
832 pub const SYS_CLOCK_NANOSLEEP: i64 = 115;
833 pub const SYS_EXIT_GROUP: i64 = 94;
834 pub const SYS_TGKILL: i64 = 131;
835 pub const SYS_MKDIRAT: i64 = 34;
836 pub const SYS_NEWFSTATAT: i64 = 79;
837 pub const SYS_UNLINKAT: i64 = 35;
838 pub const SYS_LINKAT: i64 = 37;
839 pub const SYS_SYMLINKAT: i64 = 36;
840 pub const SYS_READLINKAT: i64 = 78;
841 pub const SYS_FCHMODAT: i64 = 53;
842 pub const SYS_SET_ROBUST_LIST: i64 = 99;
843 pub const SYS_UTIMENSAT: i64 = 88;
844 pub const SYS_OPENAT: i64 = 56;
845 pub const SYS_FACCESSAT: i64 = 48;
846 pub const SYS_DUP3: i64 = 24;
847 pub const SYS_PIPE2: i64 = 59;
848 pub const SYS_SYNCFS: i64 = 267;
849 pub const SYS_RENAMEAT2: i64 = 276;
850 pub const SYS_STATFS: i64 = 43;
851 pub const SYS_FSTATFS: i64 = 44;
852 pub const SYS_FDATASYNC: i64 = 83;
853 pub const SYS_GETPID: i64 = 172;
854 pub const SYS_EXIT: i64 = 93;
855 pub const SYS_GETPPID: i64 = 173;
856 pub const SYS_SETSID: i64 = 157;
857 pub const SYS_SYNC: i64 = 81;
858 pub const SYS_GETUID: i64 = 174;
859 pub const SYS_GETGID: i64 = 176;
860 pub const SYS_GETEUID: i64 = 175;
861 pub const SYS_GETEGID: i64 = 177;
862 pub const SYS_GETTID: i64 = 178;
863 pub const SYS_CLOCK_SETTIME: i64 = 112;
864 pub const SYS_CLONE: i64 = 220;
865 pub const SYS_PPOLL: i64 = 73;
866 pub const SYS_PREAD64: i64 = 67;
867 pub const SYS_MREMAP: i64 = 216;
868 pub const SYS_SYSINFO: i64 = 179;
869 pub const SYS_MEMBARRIER: i64 = 283;
870 pub const SYS_VHANGUP: i64 = 58;
871 pub const SYS_VMSPLICE: i64 = 75;
872 pub const SYS_GETTIMEOFDAY: i64 = 169;
873 pub const SYS_SETTIMEOFDAY: i64 = 170;
874 pub const SYS_ADJTIMEX: i64 = 171;
875 pub const SYS_EPOLL_CREATE1: i64 = 20;
876 pub const SYS_EPOLL_CTL: i64 = 21;
877 pub const SYS_EPOLL_WAIT: i64 = 22;
878 pub const SYS_EVENTFD2: i64 = 19;
879 pub const SYS_SIGNALFD4: i64 = 74;
880 pub const SYS_TIMERFD_CREATE: i64 = 85;
881 pub const SYS_TIMERFD_SETTIME: i64 = 86;
882 pub const SYS_TIMERFD_GETTIME: i64 = 87;
883 pub const SYS_ACCEPT4: i64 = 242;
884 pub const SYS_ACCT: i64 = 89;
885 pub const SYS_CAPGET: i64 = 90;
886 pub const SYS_CAPSET: i64 = 91;
887 pub const SYS_CHROOT: i64 = 51;
888 pub const SYS_COPY_FILE_RANGE: i64 = 285;
889 pub const SYS_DELETE_MODULE: i64 = 106;
890 pub const SYS_FALLOCATE: i64 = 47;
891 pub const SYS_FCHDIR: i64 = 50;
892 pub const SYS_FCHOWN: i64 = 55;
893 pub const SYS_FCHOWNAT: i64 = 54;
894 pub const SYS_FLOCK: i64 = 32;
895 pub const SYS_GETDENTS64: i64 = 61;
896 pub const SYS_GETPRIORITY: i64 = 141;
897 pub const SYS_GETRESGID: i64 = 150;
898 pub const SYS_GETRESUID: i64 = 148;
899 pub const SYS_INIT_MODULE: i64 = 105;
900 pub const SYS_MKNODAT: i64 = 33;
901 pub const SYS_MOUNT: i64 = 40;
902 pub const SYS_MPROTECT: i64 = 226;
903 pub const SYS_PIVOT_ROOT: i64 = 41;
904 pub const SYS_PRCTL: i64 = 167;
905 pub const SYS_PSELECT6: i64 = 72;
906 pub const SYS_REBOOT: i64 = 142;
907 pub const SYS_RECVMSG: i64 = 212;
908 pub const SYS_SENDMSG: i64 = 211;
909 pub const SYS_SETGROUPS: i64 = 159;
910 pub const SYS_SETNS: i64 = 268;
911 pub const SYS_SETPRIORITY: i64 = 140;
912 pub const SYS_SETRESGID: i64 = 149;
913 pub const SYS_SETRESUID: i64 = 147;
914 pub const SYS_SWAPOFF: i64 = 225;
915 pub const SYS_SWAPON: i64 = 224;
916 pub const SYS_UMOUNT2: i64 = 39;
917 pub const SYS_UNSHARE: i64 = 97;
918}
919pub use sysnr::*;
920
921#[inline]
926unsafe fn sys_write(fd: i64, buf: *const u8, count: usize) -> i64 {
927 <Arch as Syscalls>::syscall3(SYS_WRITE, fd as i64, buf as i64, count as i64)
928}
929
930#[inline]
931unsafe fn sys_read(fd: i64, buf: *mut u8, count: usize) -> i64 {
932 <Arch as Syscalls>::syscall3(SYS_READ, fd as i64, buf as i64, count as i64)
933}
934
935#[inline]
936unsafe fn sys_open(path: *const u8, flags: i64, mode: i64) -> i64 {
937 <Arch as Syscalls>::syscall4(SYS_OPENAT, AT_FDCWD as i64, path as i64, flags as i64, mode as i64)
938}
939
940#[inline]
941unsafe fn sys_close(fd: i64) {
942 let _ = <Arch as Syscalls>::syscall1(SYS_CLOSE, fd as i64);
943}
944
945#[inline]
946unsafe fn sys_lseek(fd: i64, offset: i64, whence: i64) -> i64 {
947 <Arch as Syscalls>::syscall3(SYS_LSEEK, fd as i64, offset as i64, whence as i64)
948}
949
950unsafe fn sys_mmap(
951 addr: *mut u8,
952 length: usize,
953 prot: i32,
954 flags: i32,
955 fd: i32,
956 offset: i64,
957) -> *mut u8 {
958 let result = <Arch as Syscalls>::syscall6(SYS_MMAP, addr as i64, length as i64, prot as i64, flags as i64, fd as i64, offset);
959 if result < 0 && result > -4096 {
960 ERRNO = (-result) as c_int;
961 return MMAP_FAILED;
962 }
963 result as *mut u8
964}
965
966unsafe fn sys_munmap(addr: *mut u8, length: usize) -> i64 {
967 <Arch as Syscalls>::syscall2(SYS_MUNMAP, addr as i64, length as i64)
968}
969
970#[no_mangle]
975pub unsafe extern "C" fn strlen(s: *const c_char) -> usize {
976 let s = s as *const u8;
977 let mut len = 0;
978 while *s.add(len) != 0 {
979 len += 1;
980 }
981 len
982}
983
984#[no_mangle]
985pub unsafe extern "C" fn memcpy(dst: *mut c_void, src: *const c_void, n: usize) -> *mut c_void {
986 let dst = dst as *mut u8;
987 let src = src as *const u8;
988 let mut i = 0;
989 while i < n {
990 *dst.add(i) = *src.add(i);
991 i += 1;
992 }
993 dst as *mut c_void
994}
995
996#[no_mangle]
997pub unsafe extern "C" fn memset(s: *mut c_void, c: c_int, n: usize) -> *mut c_void {
998 let s = s as *mut u8;
999 let mut i = 0;
1000 while i < n {
1001 *s.add(i) = c as u8;
1002 i += 1;
1003 }
1004 s as *mut c_void
1005}
1006
1007#[no_mangle]
1008pub unsafe extern "C" fn memmove(dst: *mut c_void, src: *const c_void, n: usize) -> *mut c_void {
1009 let dst = dst as *mut u8;
1010 let src = src as *const u8;
1011 if (dst as usize) < (src as usize) {
1012 let mut i = 0;
1013 while i < n {
1014 *dst.add(i) = *src.add(i);
1015 i += 1;
1016 }
1017 } else {
1018 let mut i = n;
1019 while i > 0 {
1020 i -= 1;
1021 *dst.add(i) = *src.add(i);
1022 }
1023 }
1024 dst as *mut c_void
1025}
1026
1027#[no_mangle]
1028pub unsafe extern "C" fn memcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int {
1029 let s1 = s1 as *const u8;
1030 let s2 = s2 as *const u8;
1031 let mut i = 0;
1032 while i < n {
1033 let a = *s1.add(i);
1034 let b = *s2.add(i);
1035 if a != b {
1036 return a as c_int - b as c_int;
1037 }
1038 i += 1;
1039 }
1040 0
1041}
1042
1043#[no_mangle]
1044pub unsafe extern "C" fn bcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int {
1045 memcmp(s1, s2, n)
1046}
1047
1048#[no_mangle]
1049pub unsafe extern "C" fn strcmp(s1: *const u8, s2: *const u8) -> c_int {
1050 let mut i = 0;
1051 loop {
1052 let a = *s1.add(i);
1053 let b = *s2.add(i);
1054 if a != b {
1055 return a as c_int - b as c_int;
1056 }
1057 if a == 0 {
1058 return 0;
1059 }
1060 i += 1;
1061 }
1062}
1063
1064#[no_mangle]
1065pub unsafe extern "C" fn strncmp(s1: *const u8, s2: *const u8, n: usize) -> c_int {
1066 let mut i = 0;
1067 while i < n {
1068 let a = *s1.add(i);
1069 let b = *s2.add(i);
1070 if a != b {
1071 return a as c_int - b as c_int;
1072 }
1073 if a == 0 {
1074 return 0;
1075 }
1076 i += 1;
1077 }
1078 0
1079}
1080
1081#[no_mangle]
1082pub unsafe extern "C" fn strcpy(dst: *mut u8, src: *const u8) -> *mut u8 {
1083 let mut i = 0;
1084 loop {
1085 let c = *src.add(i);
1086 *dst.add(i) = c;
1087 if c == 0 {
1088 break;
1089 }
1090 i += 1;
1091 }
1092 dst
1093}
1094
1095#[no_mangle]
1096pub unsafe extern "C" fn strncpy(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 {
1097 let mut i = 0;
1098 while i < n && *src.add(i) != 0 {
1099 *dst.add(i) = *src.add(i);
1100 i += 1;
1101 }
1102 while i < n {
1103 *dst.add(i) = 0;
1104 i += 1;
1105 }
1106 dst
1107}
1108
1109#[no_mangle]
1110pub unsafe extern "C" fn strcat(dst: *mut u8, src: *const u8) -> *mut u8 {
1111 let mut i = 0;
1112 while *dst.add(i) != 0 {
1113 i += 1;
1114 }
1115 let mut j = 0;
1116 loop {
1117 let c = *src.add(j);
1118 *dst.add(i + j) = c;
1119 if c == 0 {
1120 break;
1121 }
1122 j += 1;
1123 }
1124 dst
1125}
1126
1127#[no_mangle]
1128pub unsafe extern "C" fn strncat(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 {
1129 let mut i = 0;
1130 while *dst.add(i) != 0 {
1131 i += 1;
1132 }
1133 let mut j = 0;
1134 while j < n && *src.add(j) != 0 {
1135 *dst.add(i + j) = *src.add(j);
1136 j += 1;
1137 }
1138 *dst.add(i + j) = 0;
1139 dst
1140}
1141
1142#[no_mangle]
1143pub unsafe extern "C" fn strlcpy(dst: *mut u8, src: *const u8, n: usize) -> usize {
1144 let l = strlen(src as *const c_char);
1145 if n > 0 {
1146 let c = if l < n { l } else { n - 1 };
1147 core::ptr::copy_nonoverlapping(src, dst, c);
1148 *dst.add(c) = 0;
1149 }
1150 l
1151}
1152
1153#[no_mangle]
1154pub unsafe extern "C" fn strlcat(dst: *mut u8, src: *const u8, n: usize) -> usize {
1155 let dl = strlen(dst as *const c_char);
1156 let sl = strlen(src as *const c_char);
1157 if dl >= n { return n + sl; }
1158 let c = if sl < n - dl { sl } else { n - dl - 1 };
1159 core::ptr::copy_nonoverlapping(src, dst.add(dl), c);
1160 *dst.add(dl + c) = 0;
1161 dl + sl
1162}
1163
1164#[no_mangle]
1165pub unsafe extern "C" fn bcopy(src: *const c_void, dst: *mut c_void, n: usize) {
1166 core::ptr::copy(src as *const u8, dst as *mut u8, n);
1167}
1168
1169#[no_mangle]
1170pub unsafe extern "C" fn bzero(s: *mut c_void, n: usize) {
1171 core::ptr::write_bytes(s as *mut u8, 0, n);
1172}
1173
1174#[no_mangle]
1175pub unsafe extern "C" fn strndup(s: *const c_char, n: usize) -> *mut c_char {
1176 let mut len = 0;
1177 while len < n && *s.add(len) != 0 {
1178 len += 1;
1179 }
1180 let p = malloc(len + 1) as *mut c_char;
1181 if p.is_null() {
1182 return core::ptr::null_mut();
1183 }
1184 core::ptr::copy_nonoverlapping(s, p, len);
1185 *p.add(len) = 0;
1186 p
1187}
1188
1189#[no_mangle]
1190pub unsafe extern "C" fn strchr(s: *const u8, c: c_int) -> *mut u8 {
1191 let target = c as u8;
1192 let mut i = 0;
1193 loop {
1194 let ch = *s.add(i);
1195 if ch == target {
1196 return s.add(i) as *mut u8;
1197 }
1198 if ch == 0 {
1199 return null_mut();
1200 }
1201 i += 1;
1202 }
1203}
1204
1205#[no_mangle]
1206pub unsafe extern "C" fn strrchr(s: *const u8, c: c_int) -> *mut u8 {
1207 let target = c as u8;
1208 let mut i = 0;
1209 let mut last: *mut u8 = null_mut();
1210 loop {
1211 let ch = *s.add(i);
1212 if ch == target {
1213 last = s.add(i) as *mut u8;
1214 }
1215 if ch == 0 {
1216 return last;
1217 }
1218 i += 1;
1219 }
1220}
1221
1222#[no_mangle]
1223pub unsafe extern "C" fn strnlen(s: *const u8, maxlen: usize) -> usize {
1224 let mut i = 0;
1225 while i < maxlen && *s.add(i) != 0 {
1226 i += 1;
1227 }
1228 i
1229}
1230
1231#[no_mangle]
1232pub unsafe extern "C" fn strcspn(s: *const u8, reject: *const u8) -> usize {
1233 let mut i = 0;
1234 loop {
1235 let c = *s.add(i);
1236 if c == 0 {
1237 return i;
1238 }
1239 let mut j = 0;
1240 loop {
1241 let r = *reject.add(j);
1242 if r == 0 {
1243 break;
1244 }
1245 if c == r {
1246 return i;
1247 }
1248 j += 1;
1249 }
1250 i += 1;
1251 }
1252}
1253
1254#[no_mangle]
1255pub unsafe extern "C" fn strspn(s: *const u8, accept: *const u8) -> usize {
1256 let mut i = 0;
1257 loop {
1258 let c = *s.add(i);
1259 if c == 0 {
1260 return i;
1261 }
1262 let mut found = false;
1263 let mut j = 0;
1264 loop {
1265 let a = *accept.add(j);
1266 if a == 0 {
1267 break;
1268 }
1269 if c == a {
1270 found = true;
1271 break;
1272 }
1273 j += 1;
1274 }
1275 if !found {
1276 return i;
1277 }
1278 i += 1;
1279 }
1280}
1281
1282#[no_mangle]
1283pub unsafe extern "C" fn strpbrk(s: *const u8, accept: *const u8) -> *mut u8 {
1284 let mut i = 0;
1285 loop {
1286 let c = *s.add(i);
1287 if c == 0 {
1288 return null_mut();
1289 }
1290 let mut j = 0;
1291 loop {
1292 let a = *accept.add(j);
1293 if a == 0 {
1294 break;
1295 }
1296 if c == a {
1297 return s.add(i) as *mut u8;
1298 }
1299 j += 1;
1300 }
1301 i += 1;
1302 }
1303}
1304
1305#[no_mangle]
1306pub unsafe extern "C" fn strstr(haystack: *const u8, needle: *const u8) -> *mut u8 {
1307 if *needle == 0 {
1308 return haystack as *mut u8;
1309 }
1310 let mut i = 0;
1311 loop {
1312 let h = *haystack.add(i);
1313 if h == 0 {
1314 return null_mut();
1315 }
1316 if h == *needle {
1317 let mut j = 0;
1318 loop {
1319 let n = *needle.add(j);
1320 if n == 0 {
1321 return haystack.add(i) as *mut u8;
1322 }
1323 if *haystack.add(i + j) != n {
1324 break;
1325 }
1326 j += 1;
1327 }
1328 }
1329 i += 1;
1330 }
1331}
1332
1333#[no_mangle]
1334pub unsafe extern "C" fn memchr(s: *const u8, c: c_int, n: usize) -> *mut u8 {
1335 let target = c as u8;
1336 let mut i = 0;
1337 while i < n {
1338 if *s.add(i) == target {
1339 return s.add(i) as *mut u8;
1340 }
1341 i += 1;
1342 }
1343 null_mut()
1344}
1345
1346#[no_mangle]
1347pub unsafe extern "C" fn memrchr(s: *const u8, c: c_int, n: usize) -> *mut u8 {
1348 let target = c as u8;
1349 let mut i = n;
1350 while i > 0 {
1351 i -= 1;
1352 if *s.add(i) == target {
1353 return s.add(i) as *mut u8;
1354 }
1355 }
1356 null_mut()
1357}
1358
1359#[no_mangle]
1360pub unsafe extern "C" fn memmem(
1361 haystack: *const c_void, haystacklen: usize,
1362 needle: *const c_void, needlelen: usize,
1363) -> *mut c_void {
1364 if needlelen == 0 { return haystack as *mut c_void; }
1365 if haystacklen < needlelen { return null_mut(); }
1366 let h = haystack as *const u8;
1367 let n = needle as *const u8;
1368 let last = haystacklen - needlelen;
1369 for i in 0..=last {
1370 if *h.add(i) == *n && memcmp(h.add(i) as *const c_void, n as *const c_void, needlelen) == 0 {
1371 return h.add(i) as *mut c_void;
1372 }
1373 }
1374 null_mut()
1375}
1376
1377#[no_mangle]
1378pub unsafe extern "C" fn strtok(s: *mut u8, delim: *const u8) -> *mut u8 {
1379 static mut STATE: *mut u8 = core::ptr::null_mut();
1380 let mut p = if s.is_null() { STATE } else { s };
1381 if p.is_null() {
1382 return core::ptr::null_mut();
1383 }
1384 loop {
1385 let c = *p;
1386 if c == 0 {
1387 STATE = core::ptr::null_mut();
1388 return core::ptr::null_mut();
1389 }
1390 let mut is_delim = false;
1391 let mut i = 0;
1392 loop {
1393 let d = *delim.add(i);
1394 if d == 0 {
1395 break;
1396 }
1397 if c == d {
1398 is_delim = true;
1399 break;
1400 }
1401 i += 1;
1402 }
1403 if !is_delim {
1404 break;
1405 }
1406 p = p.add(1);
1407 }
1408 let start = p;
1409 loop {
1410 let c = *p;
1411 if c == 0 {
1412 STATE = core::ptr::null_mut();
1413 return start;
1414 }
1415 let mut is_delim = false;
1416 let mut i = 0;
1417 loop {
1418 let d = *delim.add(i);
1419 if d == 0 {
1420 break;
1421 }
1422 if c == d {
1423 is_delim = true;
1424 break;
1425 }
1426 i += 1;
1427 }
1428 if is_delim {
1429 *p = 0;
1430 STATE = p.add(1);
1431 return start;
1432 }
1433 p = p.add(1);
1434 }
1435}
1436
1437type SizeT = usize;
1442type SSizeT = isize;
1443type mode_t = c_uint;
1444type TimeT = c_long;
1445type ClockT = c_long;
1446type wchar_t = c_int;
1447type wint_t = c_uint;
1448type wctype_t = *const c_int;
1449type wctrans_t = *const c_int;
1450
1451const WEOF: wint_t = 0xffffffff;
1452
1453#[repr(C)]
1454pub struct tm {
1455 pub tm_sec: c_int,
1456 pub tm_min: c_int,
1457 pub tm_hour: c_int,
1458 pub tm_mday: c_int,
1459 pub tm_mon: c_int,
1460 pub tm_year: c_int,
1461 pub tm_wday: c_int,
1462 pub tm_yday: c_int,
1463 pub tm_isdst: c_int,
1464 pub tm_gmtoff: c_long,
1465 pub tm_zone: *const c_char,
1466}
1467
1468#[repr(C)]
1469pub struct timeval {
1470 pub tv_sec: TimeT,
1471 pub tv_usec: c_long,
1472}
1473
1474#[repr(C)]
1475pub struct Timeb {
1476 pub time: TimeT,
1477 pub millitm: u16,
1478 pub timezone: i16,
1479 pub dstflag: u16,
1480}
1481
1482const CT_UPPER: u8 = 1 << 0;
1487const CT_LOWER: u8 = 1 << 1;
1488const CT_DIGIT: u8 = 1 << 2;
1489const CT_SPACE: u8 = 1 << 3;
1490const CT_PUNCT: u8 = 1 << 4;
1491const CT_CNTRL: u8 = 1 << 5;
1492const CT_BLANK: u8 = 1 << 6;
1493const CT_XDIGIT: u8 = 1 << 7;
1494
1495const CT_TABLE: [u8; 128] = {
1496 let mut t = [0u8; 128];
1497 let mut i = 0;
1498 while i < 128 {
1499 let c = i as u8;
1500 let mut flags = 0u8;
1501 if c >= b'A' && c <= b'Z' {
1502 flags |= CT_UPPER;
1503 }
1504 if c >= b'a' && c <= b'z' {
1505 flags |= CT_LOWER;
1506 }
1507 if c >= b'0' && c <= b'9' {
1508 flags |= CT_DIGIT;
1509 }
1510 if c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == b'\x0c' || c == b'\x0b' {
1511 flags |= CT_SPACE;
1512 }
1513 if (c >= b'!' && c <= b'/')
1514 || (c >= b':' && c <= b'@')
1515 || (c >= b'[' && c <= b'`')
1516 || (c >= b'{' && c <= b'~')
1517 {
1518 flags |= CT_PUNCT;
1519 }
1520 if c < 0x20 || c == 0x7f {
1521 flags |= CT_CNTRL;
1522 }
1523 if c == b' ' || c == b'\t' {
1524 flags |= CT_BLANK;
1525 }
1526 if (c >= b'0' && c <= b'9') || (c >= b'A' && c <= b'F') || (c >= b'a' && c <= b'f') {
1527 flags |= CT_XDIGIT;
1528 }
1529 t[i] = flags;
1530 i += 1;
1531 }
1532 t
1533};
1534
1535#[inline]
1536fn ct_flags(c: c_int) -> u8 {
1537 if c < 0 || c > 127 {
1538 0
1539 } else {
1540 CT_TABLE[c as usize]
1541 }
1542}
1543
1544#[no_mangle]
1545pub extern "C" fn isalnum(c: c_int) -> c_int {
1546 (ct_flags(c) & (CT_UPPER | CT_LOWER | CT_DIGIT) != 0) as c_int
1547}
1548
1549#[no_mangle]
1550pub extern "C" fn isalpha(c: c_int) -> c_int {
1551 (ct_flags(c) & (CT_UPPER | CT_LOWER) != 0) as c_int
1552}
1553
1554#[no_mangle]
1555pub extern "C" fn isascii(c: c_int) -> c_int {
1556 ((c as u32) <= 127) as c_int
1557}
1558
1559#[no_mangle]
1560pub extern "C" fn isblank(c: c_int) -> c_int {
1561 (ct_flags(c) & CT_BLANK != 0) as c_int
1562}
1563
1564#[no_mangle]
1565pub extern "C" fn iscntrl(c: c_int) -> c_int {
1566 (ct_flags(c) & CT_CNTRL != 0) as c_int
1567}
1568
1569#[no_mangle]
1570pub extern "C" fn isdigit(c: c_int) -> c_int {
1571 (ct_flags(c) & CT_DIGIT != 0) as c_int
1572}
1573
1574#[no_mangle]
1575pub extern "C" fn isgraph(c: c_int) -> c_int {
1576 (ct_flags(c) & (CT_UPPER | CT_LOWER | CT_DIGIT | CT_PUNCT) != 0) as c_int
1577}
1578
1579#[no_mangle]
1580pub extern "C" fn islower(c: c_int) -> c_int {
1581 (ct_flags(c) & CT_LOWER != 0) as c_int
1582}
1583
1584#[no_mangle]
1585pub extern "C" fn isprint(c: c_int) -> c_int {
1586 let flags = ct_flags(c);
1587 (flags & (CT_UPPER | CT_LOWER | CT_DIGIT | CT_PUNCT | CT_BLANK) != 0) as c_int
1588}
1589
1590#[no_mangle]
1591pub extern "C" fn ispunct(c: c_int) -> c_int {
1592 (ct_flags(c) & CT_PUNCT != 0) as c_int
1593}
1594
1595#[no_mangle]
1596pub extern "C" fn isspace(c: c_int) -> c_int {
1597 (ct_flags(c) & CT_SPACE != 0) as c_int
1598}
1599
1600#[no_mangle]
1601pub extern "C" fn isupper(c: c_int) -> c_int {
1602 (ct_flags(c) & CT_UPPER != 0) as c_int
1603}
1604
1605#[no_mangle]
1606pub extern "C" fn isxdigit(c: c_int) -> c_int {
1607 (ct_flags(c) & CT_XDIGIT != 0) as c_int
1608}
1609
1610#[no_mangle]
1611pub extern "C" fn tolower(c: c_int) -> c_int {
1612 if (ct_flags(c) & CT_UPPER) != 0 {
1613 c + (b'a' as c_int - b'A' as c_int)
1614 } else {
1615 c
1616 }
1617}
1618
1619#[no_mangle]
1620pub extern "C" fn toupper(c: c_int) -> c_int {
1621 if (ct_flags(c) & CT_LOWER) != 0 {
1622 c - (b'a' as c_int - b'A' as c_int)
1623 } else {
1624 c
1625 }
1626}
1627
1628unsafe fn parse_digit(c: u8, base: c_int) -> Option<u8> {
1633 if c == 0 { return None; }
1634 let d = if c >= b'0' && c <= b'9' {
1635 c - b'0'
1636 } else if c >= b'a' && c <= b'z' {
1637 c - b'a' + 10
1638 } else if c >= b'A' && c <= b'Z' {
1639 c - b'A' + 10
1640 } else {
1641 return None;
1642 };
1643 if (d as c_int) < base {
1644 Some(d)
1645 } else {
1646 None
1647 }
1648}
1649
1650unsafe fn parse_prefix(s: *const u8, base: *mut c_int) -> *const u8 {
1651 let mut p = s;
1652 if *base == 0 {
1653 if *p == b'0' {
1654 if (*p.add(1) == b'x' || *p.add(1) == b'X') && parse_digit(*p.add(2), 16).is_some() {
1655 *base = 16;
1656 p = p.add(2);
1657 } else {
1658 *base = 8;
1659 }
1660 } else {
1661 *base = 10;
1662 }
1663 } else if *base == 16 {
1664 if *p == b'0' && (*p.add(1) == b'x' || *p.add(1) == b'X') && parse_digit(*p.add(2), 16).is_some() {
1665 p = p.add(2);
1666 }
1667 }
1668 p
1669}
1670
1671unsafe fn strtox(
1672 s: *const c_char,
1673 endptr: *mut *mut c_char,
1674 mut base: c_int,
1675 pos_limit: u64,
1676 neg_limit: u64,
1677) -> (u64, bool, bool) {
1678 let s0 = s as *const u8;
1679 let mut p = s0;
1680 while isspace(*p as c_int) != 0 {
1681 p = p.add(1);
1682 }
1683
1684 if base < 0 || base == 1 || base > 36 {
1685 if !endptr.is_null() {
1686 *endptr = s as *mut c_char;
1687 }
1688 ERRNO = EINVAL;
1689 return (0, false, false);
1690 }
1691
1692 let mut neg = false;
1693 match *p {
1694 b'-' => { neg = true; p = p.add(1); }
1695 b'+' => p = p.add(1),
1696 _ => {}
1697 }
1698
1699 p = parse_prefix(p, &mut base);
1700
1701 let limit = if neg { neg_limit } else { pos_limit };
1702 let mut val: u64 = 0;
1703 let mut any = false;
1704 while let Some(d) = parse_digit(*p, base) {
1705 any = true;
1706 if val > (limit - d as u64) / base as u64 {
1707 while parse_digit(*p, base).is_some() { p = p.add(1); }
1708 if !endptr.is_null() { *endptr = p as *mut c_char; }
1709 ERRNO = ERANGE_VAL;
1710 return (limit, true, neg);
1711 }
1712 val = val * base as u64 + d as u64;
1713 p = p.add(1);
1714 }
1715
1716 if !endptr.is_null() {
1717 *endptr = if any { p as *mut c_char } else { s as *mut c_char };
1718 }
1719 (val, false, neg)
1720}
1721
1722#[no_mangle]
1723pub unsafe extern "C" fn strtol(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
1724 let pos_limit = c_long::MAX as u64;
1725 let neg_limit = pos_limit.wrapping_add(1);
1726 let (val, overflow, neg) = strtox(s, endptr, base, pos_limit, neg_limit);
1727 if overflow {
1728 return if neg { c_long::MIN } else { c_long::MAX };
1729 }
1730 if neg { val.wrapping_neg() as c_long } else { val as c_long }
1731}
1732
1733#[no_mangle]
1734pub unsafe extern "C" fn strtoul(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_ulong {
1735 let limit = c_ulong::MAX as u64;
1736 let (val, overflow, neg) = strtox(s, endptr, base, limit, limit);
1737 if overflow {
1738 return c_ulong::MAX;
1739 }
1740 if neg { val.wrapping_neg() as c_ulong } else { val as c_ulong }
1741}
1742
1743#[no_mangle]
1744pub unsafe extern "C" fn strtoll(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_longlong {
1745 let pos_limit = c_longlong::MAX as u64;
1746 let neg_limit = pos_limit.wrapping_add(1);
1747 let (val, overflow, neg) = strtox(s, endptr, base, pos_limit, neg_limit);
1748 if overflow {
1749 return if neg { c_longlong::MIN } else { c_longlong::MAX };
1750 }
1751 if neg { val.wrapping_neg() as c_longlong } else { val as c_longlong }
1752}
1753
1754#[no_mangle]
1755pub unsafe extern "C" fn strtoull(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_ulonglong {
1756 let limit = c_ulonglong::MAX as u64;
1757 let (val, overflow, neg) = strtox(s, endptr, base, limit, limit);
1758 if overflow {
1759 return c_ulonglong::MAX;
1760 }
1761 if neg { val.wrapping_neg() as c_ulonglong } else { val as c_ulonglong }
1762}
1763
1764#[no_mangle]
1765pub unsafe extern "C" fn atoi(s: *const c_char) -> c_int {
1766 strtol(s, core::ptr::null_mut(), 10) as c_int
1767}
1768
1769#[no_mangle]
1770pub unsafe extern "C" fn atol(s: *const c_char) -> c_long {
1771 strtol(s, core::ptr::null_mut(), 10)
1772}
1773
1774#[no_mangle]
1775pub unsafe extern "C" fn atoll(s: *const c_char) -> c_longlong {
1776 strtoll(s, core::ptr::null_mut(), 10)
1777}
1778
1779#[no_mangle]
1780pub extern "C" fn abs(n: c_int) -> c_int {
1781 if n < 0 {
1782 -n
1783 } else {
1784 n
1785 }
1786}
1787
1788#[no_mangle]
1789pub extern "C" fn labs(n: c_long) -> c_long {
1790 if n < 0 {
1791 -n
1792 } else {
1793 n
1794 }
1795}
1796
1797#[no_mangle]
1798pub extern "C" fn llabs(n: c_longlong) -> c_longlong {
1799 if n < 0 {
1800 -n
1801 } else {
1802 n
1803 }
1804}
1805
1806static mut RAND_STATE: c_uint = 1;
1807
1808#[no_mangle]
1809pub extern "C" fn srand(seed: c_uint) {
1810 unsafe {
1811 RAND_STATE = seed;
1812 }
1813}
1814
1815#[no_mangle]
1816pub extern "C" fn rand() -> c_int {
1817 unsafe {
1818 RAND_STATE = RAND_STATE.wrapping_mul(1103515245).wrapping_add(12345);
1819 ((RAND_STATE >> 16) & 0x7fff) as c_int
1820 }
1821}
1822
1823#[repr(C)]
1828pub struct div_t { pub quot: c_int, pub rem: c_int }
1829#[repr(C)]
1830pub struct ldiv_t { pub quot: c_long, pub rem: c_long }
1831#[repr(C)]
1832pub struct lldiv_t { pub quot: c_longlong, pub rem: c_longlong }
1833
1834#[no_mangle]
1835pub extern "C" fn div(num: c_int, den: c_int) -> div_t {
1836 div_t { quot: num / den, rem: num % den }
1837}
1838
1839#[no_mangle]
1840pub extern "C" fn ldiv(num: c_long, den: c_long) -> ldiv_t {
1841 ldiv_t { quot: num / den, rem: num % den }
1842}
1843
1844#[no_mangle]
1845pub extern "C" fn lldiv(num: c_longlong, den: c_longlong) -> lldiv_t {
1846 lldiv_t { quot: num / den, rem: num % den }
1847}
1848
1849type CmpFn = unsafe extern "C" fn(*const c_void, *const c_void) -> c_int;
1854
1855#[no_mangle]
1856pub unsafe extern "C" fn bsearch(
1857 key: *const c_void,
1858 base: *const c_void,
1859 nel: usize,
1860 width: usize,
1861 cmp: CmpFn,
1862) -> *mut c_void {
1863 let mut base = base as *const u8;
1864 let mut nel = nel;
1865 while nel > 0 {
1866 let trial = base.add(width * (nel / 2));
1867 let sign = cmp(key, trial as *const c_void);
1868 if sign < 0 {
1869 nel /= 2;
1870 } else if sign > 0 {
1871 base = trial.add(width);
1872 nel -= nel / 2 + 1;
1873 } else {
1874 return trial as *mut c_void;
1875 }
1876 }
1877 null_mut()
1878}
1879
1880pub const SA_RESTORER: c_ulong = 0x04000000;
1885
1886pub const SIG_DFL: usize = 0;
1887pub const SIG_IGN: usize = 1;
1888pub const SIG_ERR: usize = !0usize;
1889
1890pub const SIGHUP: c_int = 1;
1891pub const SIGINT: c_int = 2;
1892pub const SIGQUIT: c_int = 3;
1893pub const SIGILL: c_int = 4;
1894pub const SIGTRAP: c_int = 5;
1895pub const SIGABRT: c_int = 6;
1896pub const SIGIOT: c_int = 6;
1897pub const SIGBUS: c_int = 7;
1898pub const SIGFPE: c_int = 8;
1899pub const SIGKILL: c_int = 9;
1900pub const SIGUSR1: c_int = 10;
1901pub const SIGSEGV: c_int = 11;
1902pub const SIGUSR2: c_int = 12;
1903pub const SIGPIPE: c_int = 13;
1904pub const SIGALRM: c_int = 14;
1905pub const SIGTERM: c_int = 15;
1906pub const SIGSTKFLT: c_int = 16;
1907pub const SIGCHLD: c_int = 17;
1908pub const SIGCONT: c_int = 18;
1909pub const SIGSTOP: c_int = 19;
1910pub const SIGTSTP: c_int = 20;
1911pub const SIGTTIN: c_int = 21;
1912pub const SIGTTOU: c_int = 22;
1913pub const SIGURG: c_int = 23;
1914pub const SIGXCPU: c_int = 24;
1915pub const SIGXFSZ: c_int = 25;
1916pub const SIGVTALRM: c_int = 26;
1917pub const SIGPROF: c_int = 27;
1918pub const SIGWINCH: c_int = 28;
1919pub const SIGIO: c_int = 29;
1920pub const SIGPOLL: c_int = 29;
1921pub const SIGPWR: c_int = 30;
1922pub const SIGSYS: c_int = 31;
1923pub const SIGUNUSED: c_int = 31;
1924pub const _NSIG: c_int = 65;
1925
1926pub const SIG_BLOCK: c_int = 0;
1927pub const SIG_UNBLOCK: c_int = 1;
1928pub const SIG_SETMASK: c_int = 2;
1929
1930pub const SA_NOCLDSTOP: c_ulong = 1;
1931pub const SA_NOCLDWAIT: c_ulong = 2;
1932pub const SA_SIGINFO: c_ulong = 4;
1933pub const SA_ONSTACK: c_ulong = 0x08000000;
1934pub const SA_RESTART: c_ulong = 0x10000000;
1935pub const SA_NODEFER: c_ulong = 0x40000000;
1936pub const SA_RESETHAND: c_ulong = 0x80000000;
1937
1938pub const SS_ONSTACK: c_int = 1;
1939pub const SS_DISABLE: c_int = 2;
1940pub const MINSIGSTKSZ: usize = 2048;
1941pub const SIGSTKSZ: usize = 8192;
1942
1943pub const SI_USER: c_int = 0;
1944pub const SI_TKILL: c_int = -6;
1945
1946#[repr(C)]
1947pub struct timespec {
1948 pub tv_sec: c_long,
1949 pub tv_nsec: c_long,
1950}
1951
1952#[repr(C)]
1953pub struct siginfo_t {
1954 pub si_signo: c_int,
1955 pub si_errno: c_int,
1956 pub si_code: c_int,
1957 _pad: [u8; 128 - 3 * core::mem::size_of::<c_int>()],
1959}
1960
1961#[repr(C)]
1962pub struct stack_t {
1963 pub ss_sp: *mut c_void,
1964 pub ss_flags: c_int,
1965 pub ss_size: usize,
1966}
1967
1968#[repr(C)]
1969pub struct sigaction {
1970 pub sa_handler: usize,
1971 pub sa_flags: c_ulong,
1972 pub sa_restorer: usize,
1973 pub sa_mask: [c_ulong; 1],
1974}
1975
1976pub type SigSetT = c_ulong;
1977
1978#[cfg(target_arch = "x86_64")]
1979core::arch::global_asm!(
1980 ".global sig_restorer",
1981 ".type sig_restorer, @function",
1982 "sig_restorer:",
1983 "mov eax, 15",
1984 "syscall",
1985);
1986
1987#[cfg(target_arch = "aarch64")]
1988core::arch::global_asm!(
1989 ".global sig_restorer",
1990 ".type sig_restorer, @function",
1991 "sig_restorer:",
1992 "mov x8, #139",
1993 "svc #0",
1994);
1995
1996#[cfg(target_arch = "riscv64")]
1997core::arch::global_asm!(
1998 ".global sig_restorer",
1999 ".type sig_restorer, @function",
2000 "sig_restorer:",
2001 "li a7, 139",
2002 "ecall",
2003);
2004
2005extern "C" {
2006 fn sig_restorer();
2007}
2008
2009#[inline]
2010unsafe fn sys_rt_sigaction(sig: c_int,
2011 act: *const sigaction,
2012 oldact: *mut sigaction,
2013 sigsetsize: usize,) -> i64 {
2014 <Arch as Syscalls>::syscall4(SYS_RT_SIGACTION, sig as i64, act as i64, oldact as i64, sigsetsize as i64)
2015}
2016
2017#[inline]
2018unsafe fn sys_rt_sigprocmask(how: c_int,
2019 set: *const SigSetT,
2020 oldset: *mut SigSetT,
2021 sigsetsize: usize,) -> i64 {
2022 <Arch as Syscalls>::syscall4(SYS_RT_SIGPROCMASK, how as i64, set as i64, oldset as i64, sigsetsize as i64)
2023}
2024
2025#[inline]
2026unsafe fn sys_rt_sigpending(set: *mut SigSetT, sigsetsize: usize) -> i64 {
2027 <Arch as Syscalls>::syscall2(SYS_RT_SIGPENDING, set as i64, sigsetsize as i64)
2028}
2029
2030#[inline]
2031unsafe fn sys_rt_sigsuspend(mask: *const SigSetT, sigsetsize: usize) -> i64 {
2032 <Arch as Syscalls>::syscall2(SYS_RT_SIGSUSPEND, mask as i64, sigsetsize as i64)
2033}
2034
2035#[inline]
2036unsafe fn sys_rt_sigtimedwait(set: *const SigSetT,
2037 info: *mut siginfo_t,
2038 timeout: *const timespec,
2039 sigsetsize: usize,) -> i64 {
2040 <Arch as Syscalls>::syscall4(SYS_RT_SIGTIMEDWAIT, set as i64, info as i64, timeout as i64, sigsetsize as i64)
2041}
2042
2043#[inline]
2044unsafe fn sys_sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> i64 {
2045 <Arch as Syscalls>::syscall2(SYS_SIGALTSTACK, ss as i64, old_ss as i64)
2046}
2047
2048#[inline]
2049unsafe fn sys_tgkill(tgid: c_int, tid: c_int, sig: c_int) -> i64 {
2050 <Arch as Syscalls>::syscall3(SYS_TGKILL, tgid as i64, tid as i64, sig as i64)
2051}
2052
2053const CLOCK_REALTIME: c_int = 0;
2054const CLOCK_MONOTONIC: c_int = 1;
2055
2056#[inline]
2057unsafe fn sys_clock_gettime(clockid: c_int, ts: *mut timespec) -> i64 {
2058 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETTIME, clockid as i64, ts as i64)
2059}
2060
2061#[no_mangle]
2062pub unsafe extern "C" fn clock_gettime(clockid: c_int, ts: *mut timespec) -> c_int {
2063 if sys_clock_gettime(clockid, ts) < 0 { -1 } else { 0 }
2064}
2065
2066#[no_mangle]
2067pub unsafe extern "C" fn sigprocmask(
2068 how: c_int,
2069 set: *const SigSetT,
2070 oldset: *mut SigSetT,
2071) -> c_int {
2072 let internal_mask: SigSetT = (1u64 << 31) | (1u64 << 32);
2074 let filtered: SigSetT;
2075 let set_ptr: *const SigSetT = if set.is_null() {
2076 set
2077 } else {
2078 filtered = *set & !internal_mask;
2079 &filtered
2080 };
2081 let r = sys_rt_sigprocmask(how, set_ptr, oldset, core::mem::size_of::<SigSetT>());
2082 if !oldset.is_null() {
2083 *oldset &= !internal_mask;
2084 }
2085 if r < 0 { -1 } else { 0 }
2086}
2087
2088#[inline]
2089unsafe fn sys_kill(pid: c_int, sig: c_int) -> i64 {
2090 <Arch as Syscalls>::syscall2(SYS_KILL, pid as i64, sig as i64)
2091}
2092
2093#[inline]
2094unsafe fn sys_getpid() -> i64 {
2095 <Arch as Syscalls>::syscall0(SYS_GETPID)
2096}
2097
2098#[no_mangle]
2099pub unsafe extern "C" fn sigaction(
2100 signum: c_int,
2101 act: *const sigaction,
2102 oldact: *mut sigaction,
2103) -> c_int {
2104 let kact: sigaction;
2105 let act_ptr = if act.is_null() {
2106 core::ptr::null()
2107 } else {
2108 kact = sigaction {
2109 sa_handler: (*act).sa_handler,
2110 sa_flags: (*act).sa_flags | SA_RESTORER,
2111 sa_restorer: sig_restorer as *const () as usize,
2112 sa_mask: (*act).sa_mask,
2113 };
2114 &kact as *const sigaction
2115 };
2116 let r = sys_rt_sigaction(signum, act_ptr, oldact, core::mem::size_of::<SigSetT>());
2117 if r < 0 {
2118 ERRNO = (-r) as c_int;
2119 -1
2120 } else {
2121 0
2122 }
2123}
2124
2125#[no_mangle]
2126pub unsafe extern "C" fn signal(signum: c_int, handler: usize) -> usize {
2127 let act = sigaction {
2128 sa_handler: handler,
2129 sa_flags: SA_RESTORER,
2130 sa_restorer: sig_restorer as *const () as usize,
2131 sa_mask: [0],
2132 };
2133 let mut old = sigaction {
2134 sa_handler: 0,
2135 sa_flags: 0,
2136 sa_restorer: 0,
2137 sa_mask: [0],
2138 };
2139 if sigaction(signum, &act, &mut old) == -1 {
2140 SIG_ERR
2141 } else {
2142 old.sa_handler
2143 }
2144}
2145
2146#[no_mangle]
2147pub unsafe extern "C" fn kill(pid: c_int, sig: c_int) -> c_int {
2148 sys_kill(pid, sig) as c_int
2149}
2150
2151#[no_mangle]
2152pub unsafe extern "C" fn tgkill(tgid: c_int, tid: c_int, sig: c_int) -> c_int {
2153 if sys_tgkill(tgid, tid, sig) < 0 { -1 } else { 0 }
2154}
2155
2156#[no_mangle]
2157pub unsafe extern "C" fn getpid() -> c_int {
2158 sys_getpid() as c_int
2159}
2160
2161#[no_mangle]
2162pub unsafe extern "C" fn raise(sig: c_int) -> c_int {
2163 if sys_tgkill(sys_getpid() as c_int, sys_gettid() as c_int, sig) < 0 {
2164 -1
2165 } else {
2166 0
2167 }
2168}
2169
2170#[no_mangle]
2171pub unsafe extern "C" fn sigemptyset(set: *mut SigSetT) -> c_int {
2172 *set = 0;
2173 0
2174}
2175
2176#[no_mangle]
2177pub unsafe extern "C" fn sigfillset(set: *mut SigSetT) -> c_int {
2178 *set = 0xFFFF_FFFC_7FFF_FFFFu64;
2180 0
2181}
2182
2183#[no_mangle]
2184pub unsafe extern "C" fn sigaddset(set: *mut SigSetT, signum: c_int) -> c_int {
2185 let s = (signum as c_uint).wrapping_sub(1);
2186 if s as usize >= 64 {
2187 ERRNO = EINVAL;
2188 return -1;
2189 }
2190 if signum >= 32 && signum < __libc_current_sigrtmin() {
2192 return 0;
2193 }
2194 *set |= 1u64 << s;
2195 0
2196}
2197
2198#[no_mangle]
2199pub unsafe extern "C" fn sigdelset(set: *mut SigSetT, signum: c_int) -> c_int {
2200 let s = (signum as c_uint).wrapping_sub(1);
2201 if s as usize >= 64 {
2202 ERRNO = EINVAL;
2203 return -1;
2204 }
2205 if signum >= 32 && signum < __libc_current_sigrtmin() {
2207 return 0;
2208 }
2209 *set &= !(1u64 << s);
2210 0
2211}
2212
2213#[no_mangle]
2214pub unsafe extern "C" fn sigismember(set: *const SigSetT, signum: c_int) -> c_int {
2215 let s = (signum as c_uint).wrapping_sub(1);
2216 if s as usize >= 64 { return 0; }
2217 if signum >= 32 && signum < __libc_current_sigrtmin() {
2219 return 0;
2220 }
2221 ((*set & (1u64 << s)) != 0) as c_int
2222}
2223
2224#[no_mangle]
2225pub unsafe extern "C" fn sigpending(set: *mut SigSetT) -> c_int {
2226 let r = sys_rt_sigpending(set, core::mem::size_of::<SigSetT>());
2227 if r < 0 {
2228 ERRNO = (-r) as c_int;
2229 return -1;
2230 }
2231 0
2232}
2233
2234#[no_mangle]
2235pub unsafe extern "C" fn sigsuspend(mask: *const SigSetT) -> c_int {
2236 let r = sys_rt_sigsuspend(mask, core::mem::size_of::<SigSetT>());
2237 if r < 0 {
2238 ERRNO = (-r) as c_int;
2239 }
2240 -1
2241}
2242
2243#[no_mangle]
2244pub unsafe extern "C" fn sigtimedwait(
2245 mask: *const SigSetT,
2246 info: *mut siginfo_t,
2247 timeout: *const timespec,
2248) -> c_int {
2249 loop {
2250 let r = sys_rt_sigtimedwait(mask, info, timeout, core::mem::size_of::<SigSetT>());
2251 if r >= 0 {
2252 return r as c_int;
2253 }
2254 let e = (-r) as c_int;
2255 if e != EINTR {
2256 ERRNO = e;
2257 return -1;
2258 }
2259 }
2260}
2261
2262#[no_mangle]
2263pub unsafe extern "C" fn sigwaitinfo(
2264 mask: *const SigSetT,
2265 info: *mut siginfo_t,
2266) -> c_int {
2267 sigtimedwait(mask, info, core::ptr::null())
2268}
2269
2270#[no_mangle]
2271pub unsafe extern "C" fn sigwait(
2272 mask: *const SigSetT,
2273 sig: *mut c_int,
2274) -> c_int {
2275 let mut info: siginfo_t = core::mem::zeroed();
2276 if sigtimedwait(mask, &mut info, core::ptr::null()) < 0 {
2277 return ERRNO;
2278 }
2279 *sig = info.si_signo;
2280 0
2281}
2282
2283#[no_mangle]
2284pub unsafe extern "C" fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int {
2285 if !ss.is_null() {
2286 if (*ss).ss_flags & SS_ONSTACK != 0 {
2287 ERRNO = EINVAL;
2288 return -1;
2289 }
2290 if (*ss).ss_flags & SS_DISABLE == 0 && (*ss).ss_size < MINSIGSTKSZ {
2291 ERRNO = ENOMEM;
2292 return -1;
2293 }
2294 }
2295 let r = sys_sigaltstack(ss, old_ss);
2296 if r < 0 {
2297 ERRNO = (-r) as c_int;
2298 return -1;
2299 }
2300 0
2301}
2302
2303#[no_mangle]
2309#[inline(never)]
2310#[cfg(target_arch = "x86_64")]
2311pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2312 core::arch::asm!(
2313 "mov rax, [rsp]",
2314 "lea rcx, [rsp + 8]",
2315 "mov [r8], rbx",
2316 "mov [r8 + 8], rbp",
2317 "mov [r8 + 16], r12",
2318 "mov [r8 + 24], r13",
2319 "mov [r8 + 32], r14",
2320 "mov [r8 + 40], r15",
2321 "mov [r8 + 48], rcx",
2322 "mov [r8 + 56], rax",
2323 in("r8") env,
2324 lateout("rax") _,
2325 lateout("rcx") _,
2326 options(nostack),
2327 );
2328 0
2329}
2330
2331#[no_mangle]
2332#[inline(never)]
2333#[cfg(target_arch = "x86_64")]
2334pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2335 let ret = if val == 0 { 1 } else { val } as u32;
2336 core::arch::asm!(
2337 "mov rbx, [r8]",
2338 "mov rbp, [r8 + 8]",
2339 "mov r12, [r8 + 16]",
2340 "mov r13, [r8 + 24]",
2341 "mov r14, [r8 + 32]",
2342 "mov r15, [r8 + 40]",
2343 "mov rsp, [r8 + 48]",
2344 "mov eax, edx",
2345 "jmp [r8 + 56]",
2346 in("r8") env,
2347 in("edx") ret,
2348 options(noreturn),
2349 );
2350}
2351
2352#[no_mangle]
2353#[unsafe(naked)]
2354#[cfg(target_arch = "aarch64")]
2355pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2356 core::arch::naked_asm!(
2357 "stp x19, x20, [x0, #0]",
2358 "stp x21, x22, [x0, #16]",
2359 "stp x23, x24, [x0, #32]",
2360 "stp x25, x26, [x0, #48]",
2361 "stp x27, x28, [x0, #64]",
2362 "stp x29, x30, [x0, #80]",
2363 "mov x2, sp",
2364 "str x2, [x0, #104]",
2365 "stp d8, d9, [x0, #112]",
2366 "stp d10, d11, [x0, #128]",
2367 "stp d12, d13, [x0, #144]",
2368 "stp d14, d15, [x0, #160]",
2369 "mov x0, #0",
2370 "ret",
2371 );
2372}
2373
2374#[no_mangle]
2375#[inline(never)]
2376#[cfg(target_arch = "aarch64")]
2377pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2378 let ret = if val == 0 { 1 } else { val } as u64;
2379 core::arch::asm!(
2380 "ldp x19, x20, [x0]",
2381 "ldp x21, x22, [x0, #16]",
2382 "ldp x23, x24, [x0, #32]",
2383 "ldp x25, x26, [x0, #48]",
2384 "ldp x27, x28, [x0, #64]",
2385 "ldp x29, x30, [x0, #80]",
2386 "ldr x2, [x0, #104]",
2387 "mov sp, x2",
2388 "ldp d8, d9, [x0, #112]",
2389 "ldp d10, d11, [x0, #128]",
2390 "ldp d12, d13, [x0, #144]",
2391 "ldp d14, d15, [x0, #160]",
2392 "mov x0, x1",
2393 "br x30",
2394 in("x0") env,
2395 in("x1") ret,
2396 options(noreturn),
2397 );
2398}
2399
2400#[no_mangle]
2401#[unsafe(naked)]
2402#[cfg(target_arch = "riscv64")]
2403pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2404 core::arch::naked_asm!(
2405 "sd s0, 0(a0)",
2406 "sd s1, 8(a0)",
2407 "sd s2, 16(a0)",
2408 "sd s3, 24(a0)",
2409 "sd s4, 32(a0)",
2410 "sd s5, 40(a0)",
2411 "sd s6, 48(a0)",
2412 "sd s7, 56(a0)",
2413 "sd s8, 64(a0)",
2414 "sd s9, 72(a0)",
2415 "sd s10, 80(a0)",
2416 "sd s11, 88(a0)",
2417 "sd sp, 96(a0)",
2418 "sd ra, 104(a0)",
2419 "li a0, 0",
2420 "ret",
2421 );
2422}
2423
2424#[no_mangle]
2425#[inline(never)]
2426#[cfg(target_arch = "riscv64")]
2427pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2428 let ret = if val == 0 { 1 } else { val } as u64;
2429 core::arch::asm!(
2430 "ld s0, 0(a0)",
2431 "ld s1, 8(a0)",
2432 "ld s2, 16(a0)",
2433 "ld s3, 24(a0)",
2434 "ld s4, 32(a0)",
2435 "ld s5, 40(a0)",
2436 "ld s6, 48(a0)",
2437 "ld s7, 56(a0)",
2438 "ld s8, 64(a0)",
2439 "ld s9, 72(a0)",
2440 "ld s10, 80(a0)",
2441 "ld s11, 88(a0)",
2442 "ld sp, 96(a0)",
2443 "ld ra, 104(a0)",
2444 "mv a0, a1",
2445 "ret",
2446 in("a0") env,
2447 in("a1") ret,
2448 options(noreturn),
2449 );
2450}
2451
2452#[no_mangle]
2460#[unsafe(naked)]
2461#[cfg(target_arch = "x86_64")]
2462pub unsafe extern "C" fn sigsetjmp(_env: *mut c_ulong, _savemask: c_int) -> c_int {
2463 core::arch::naked_asm!("jmp sigsetjmp_real");
2464}
2465
2466#[no_mangle]
2467#[unsafe(naked)]
2468#[cfg(target_arch = "x86_64")]
2469pub unsafe extern "C" fn __sigsetjmp(_env: *mut c_ulong, _savemask: c_int) -> c_int {
2470 core::arch::naked_asm!("jmp sigsetjmp_real");
2471}
2472
2473#[cfg(target_arch = "x86_64")]
2474core::arch::global_asm!(
2475 ".type sigsetjmp_real, @function",
2476 "sigsetjmp_real:",
2477 " test esi, esi",
2478 " jz 1f",
2479 " pop qword ptr [rdi + 64]",
2480 " mov qword ptr [rdi + 80], rbx",
2481 " push rbx",
2482 " mov rbx, rdi",
2483 " call setjmp",
2484 " push qword ptr [rbx + 64]",
2485 " mov rdi, rbx",
2486 " mov esi, eax",
2487 " mov rbx, qword ptr [rbx + 80]",
2488 " lea rdx, [rdi + 72]",
2489 " test esi, esi",
2490 " jz 2f",
2491 " mov rsi, rdx",
2492 " xor rdx, rdx",
2493 " mov edi, 2",
2494 " jmp 3f",
2495 "2:",
2496 " xor rsi, rsi",
2497 " mov edi, 2",
2498 "3:",
2499 " mov eax, 14",
2500 " mov r10d, 8",
2501 " syscall",
2502 " test esi, esi",
2503 " jnz 4f",
2504 " mov rax, 0xfffffffe7fffffff",
2505 " and qword ptr [rdx], rax",
2506 "4:",
2507 " mov eax, esi",
2508 " ret",
2509 "1:",
2510 " jmp setjmp",
2511);
2512
2513#[no_mangle]
2514#[inline(never)]
2515#[cfg(target_arch = "x86_64")]
2516pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2517 longjmp(env, val);
2518}
2519
2520#[no_mangle]
2521#[cfg(target_arch = "aarch64")]
2522pub unsafe extern "C" fn __sigsetjmp_tail(env: *mut c_ulong, ret: c_int) -> c_int {
2523 const SIG_SETMASK: c_int = 2;
2524 let ss = env.add(24) as *mut SigSetT;
2525 let set = if ret != 0 { ss as *const SigSetT } else { core::ptr::null() };
2526 let old = if ret != 0 { core::ptr::null_mut() } else { ss };
2527 let _ = sys_rt_sigprocmask(SIG_SETMASK, set, old, core::mem::size_of::<SigSetT>());
2528 ret
2529}
2530
2531#[no_mangle]
2532#[unsafe(naked)]
2533#[cfg(target_arch = "aarch64")]
2534pub unsafe extern "C" fn sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2535 core::arch::naked_asm!(
2536 "cbz w1, setjmp",
2537 "str x30, [x0, #176]",
2538 "str x19, [x0, #184]",
2539 "mov x19, x0",
2540 "bl setjmp",
2541 "mov w1, w0",
2542 "mov x0, x19",
2543 "ldr x30, [x0, #176]",
2544 "ldr x19, [x0, #184]",
2545 "b __sigsetjmp_tail",
2546 );
2547}
2548
2549#[no_mangle]
2550#[unsafe(naked)]
2551#[cfg(target_arch = "aarch64")]
2552pub unsafe extern "C" fn __sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2553 core::arch::naked_asm!(
2554 "cbz w1, setjmp",
2555 "str x30, [x0, #176]",
2556 "str x19, [x0, #184]",
2557 "mov x19, x0",
2558 "bl setjmp",
2559 "mov w1, w0",
2560 "mov x0, x19",
2561 "ldr x30, [x0, #176]",
2562 "ldr x19, [x0, #184]",
2563 "b __sigsetjmp_tail",
2564 );
2565}
2566
2567#[no_mangle]
2568#[inline(never)]
2569#[cfg(target_arch = "aarch64")]
2570pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2571 longjmp(env, val);
2572}
2573
2574#[no_mangle]
2575#[cfg(target_arch = "riscv64")]
2576pub unsafe extern "C" fn __sigsetjmp_tail(env: *mut c_ulong, ret: c_int) -> c_int {
2577 const SIG_SETMASK: c_int = 2;
2578 let ss = env.add(27) as *mut SigSetT;
2579 let set = if ret != 0 { ss as *const SigSetT } else { core::ptr::null() };
2580 let old = if ret != 0 { core::ptr::null_mut() } else { ss };
2581 let _ = sys_rt_sigprocmask(SIG_SETMASK, set, old, core::mem::size_of::<SigSetT>());
2582 ret
2583}
2584
2585#[no_mangle]
2586#[unsafe(naked)]
2587#[cfg(target_arch = "riscv64")]
2588pub unsafe extern "C" fn sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2589 core::arch::naked_asm!(
2590 "bnez a1, 1f",
2591 "tail setjmp",
2592 "1:",
2593 "sd ra, 208(a0)",
2594 "sd s0, 224(a0)",
2595 "mv s0, a0",
2596 "call setjmp",
2597 "mv a1, a0",
2598 "mv a0, s0",
2599 "ld s0, 224(a0)",
2600 "ld ra, 208(a0)",
2601 "tail __sigsetjmp_tail",
2602 );
2603}
2604
2605#[no_mangle]
2606#[unsafe(naked)]
2607#[cfg(target_arch = "riscv64")]
2608pub unsafe extern "C" fn __sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2609 core::arch::naked_asm!(
2610 "bnez a1, 1f",
2611 "tail setjmp",
2612 "1:",
2613 "sd ra, 208(a0)",
2614 "sd s0, 224(a0)",
2615 "mv s0, a0",
2616 "call setjmp",
2617 "mv a1, a0",
2618 "mv a0, s0",
2619 "ld s0, 224(a0)",
2620 "ld ra, 208(a0)",
2621 "tail __sigsetjmp_tail",
2622 );
2623}
2624
2625#[no_mangle]
2626#[inline(never)]
2627#[cfg(target_arch = "riscv64")]
2628pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2629 longjmp(env, val);
2630}
2631
2632#[inline]
2637unsafe fn sys_newfstatat(dirfd: i32, path: *const c_char, buf: *mut u8, flags: i32) -> i64 {
2638 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, dirfd as i64, path as i64, buf as i64, flags as i64)
2639}
2640
2641#[inline]
2642unsafe fn sys_fstat(fd: i32, buf: *mut u8) -> i64 {
2643 <Arch as Syscalls>::syscall2(SYS_FSTAT, fd as i64, buf as i64)
2644}
2645
2646#[inline]
2647unsafe fn sys_getrlimit(resource: i32, rlim: *mut u8) -> i64 {
2648 <Arch as Syscalls>::syscall2(SYS_GETRLIMIT, resource as i64, rlim as i64)
2649}
2650
2651#[inline]
2652unsafe fn sys_setrlimit(resource: i32, rlim: *const u8) -> i64 {
2653 <Arch as Syscalls>::syscall2(SYS_SETRLIMIT, resource as i64, rlim as i64)
2654}
2655
2656#[inline]
2657unsafe fn sys_utimensat(dirfd: i32, path: *const c_char, times: *const u8, flags: i32) -> i64 {
2658 <Arch as Syscalls>::syscall4(SYS_UTIMENSAT, dirfd as i64, path as i64, times as i64, flags as i64)
2659}
2660
2661#[inline]
2666unsafe fn sys_fork() -> i64 {
2667 #[cfg(target_arch = "x86_64")]
2668 { <Arch as Syscalls>::syscall0(SYS_FORK) }
2669 #[cfg(target_arch = "aarch64")]
2670 { <Arch as Syscalls>::syscall2(SYS_CLONE, 17, 0) }
2671 #[cfg(target_arch = "riscv64")]
2672 { <Arch as Syscalls>::syscall2(SYS_CLONE, 17, 0) }
2673}
2674
2675#[inline]
2676unsafe fn sys_execve(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> i64 {
2677 <Arch as Syscalls>::syscall3(SYS_EXECVE, path as i64, argv as i64, envp as i64)
2678}
2679
2680#[inline]
2681unsafe fn sys_wait4(pid: c_int, status: *mut c_int, options: c_int, rusage: *mut c_void) -> i64 {
2682 <Arch as Syscalls>::syscall4(SYS_WAIT4, pid as i64, status as i64, options as i64, rusage as i64)
2683}
2684
2685#[inline]
2686unsafe fn sys_getppid() -> i64 {
2687 <Arch as Syscalls>::syscall0(SYS_GETPPID)
2688}
2689
2690#[inline]
2691unsafe fn sys_getuid() -> i64 {
2692 <Arch as Syscalls>::syscall0(SYS_GETUID)
2693}
2694
2695#[inline]
2696unsafe fn sys_getgid() -> i64 {
2697 <Arch as Syscalls>::syscall0(SYS_GETGID)
2698}
2699
2700#[inline]
2701unsafe fn sys_geteuid() -> i64 {
2702 <Arch as Syscalls>::syscall0(SYS_GETEUID)
2703}
2704
2705#[inline]
2706unsafe fn sys_getegid() -> i64 {
2707 <Arch as Syscalls>::syscall0(SYS_GETEGID)
2708}
2709
2710#[no_mangle]
2711pub unsafe extern "C" fn fork() -> c_int {
2712 __fork_handler(-1);
2713 let ret = sys_fork();
2714 if ret < 0 {
2719 let err = (-ret) as c_int;
2720 __fork_handler(0);
2721 ERRNO = err;
2722 return -1;
2723 }
2724 if ret == 0 {
2725 allocator_after_fork();
2726 __fork_handler(1);
2727 } else {
2728 __fork_handler(0);
2729 }
2730 ret as c_int
2731}
2732
2733#[no_mangle]
2734pub unsafe extern "C" fn execve(
2735 path: *const c_char,
2736 argv: *const *const c_char,
2737 envp: *const *const c_char,
2738) -> c_int {
2739 sys_execve(path, argv, envp) as c_int
2740}
2741
2742#[no_mangle]
2743pub unsafe extern "C" fn wait(status: *mut c_int) -> c_int {
2744 sys_wait4(-1, status, 0, core::ptr::null_mut()) as c_int
2745}
2746
2747#[no_mangle]
2748pub unsafe extern "C" fn waitpid(pid: c_int, status: *mut c_int, options: c_int) -> c_int {
2749 sys_wait4(pid, status, options, core::ptr::null_mut()) as c_int
2750}
2751
2752#[no_mangle]
2753pub unsafe extern "C" fn getppid() -> c_int {
2754 sys_getppid() as c_int
2755}
2756
2757#[no_mangle]
2758pub unsafe extern "C" fn getuid() -> c_uint {
2759 sys_getuid() as c_uint
2760}
2761
2762#[no_mangle]
2763pub unsafe extern "C" fn getgid() -> c_uint {
2764 sys_getgid() as c_uint
2765}
2766
2767#[no_mangle]
2768pub unsafe extern "C" fn geteuid() -> c_uint {
2769 sys_geteuid() as c_uint
2770}
2771
2772#[no_mangle]
2773pub unsafe extern "C" fn getegid() -> c_uint {
2774 sys_getegid() as c_uint
2775}
2776
2777#[no_mangle]
2779pub unsafe extern "C" fn vfork() -> c_int {
2780 sys_fork() as c_int
2781}
2782
2783#[no_mangle]
2784pub unsafe extern "C" fn execl(path: *const c_char, arg: *const c_char, mut args: ...) -> c_int {
2785 let mut argv: [*const c_char; 256] = [core::ptr::null(); 256];
2786 argv[0] = arg;
2787 let mut n: usize = 1;
2788 loop {
2789 let a: *const c_char = args.next_arg();
2790 if a.is_null() { break; }
2791 if n >= 255 { return -1; }
2792 argv[n] = a;
2793 n += 1;
2794 }
2795 argv[n] = core::ptr::null();
2796 sys_execve(path, argv.as_ptr(), __environ as *const *const c_char) as c_int
2797}
2798
2799unsafe fn spawn_execvp(file: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> ! {
2808 let flen = strlen(file as *const c_char);
2809 let f = file as *const u8;
2810 let mut has_slash = false;
2811 for i in 0..flen {
2812 if *f.add(i) == b'/' { has_slash = true; break; }
2813 }
2814 if has_slash {
2815 sys_execve(file, argv, envp);
2816 _exit(127);
2817 }
2818 let path = getenv(b"PATH\0".as_ptr() as *const c_char);
2819 let default_path = b"/usr/local/bin:/usr/bin:/bin\0";
2820 let p = if path.is_null() { default_path.as_ptr() } else { path as *const u8 };
2821 let plen = strlen(p as *const c_char);
2822 let mut buf: [u8; 4096] = [0; 4096];
2823 let mut i: usize = 0;
2824 while i <= plen {
2825 let start = i;
2826 while i < plen && *p.add(i) != b':' { i += 1; }
2827 let dlen = i - start;
2828 if dlen > 0 && dlen + 1 + flen < 4096 {
2829 core::ptr::copy_nonoverlapping(p.add(start), buf.as_mut_ptr(), dlen);
2830 *buf.as_mut_ptr().add(dlen) = b'/';
2831 core::ptr::copy_nonoverlapping(f, buf.as_mut_ptr().add(dlen + 1), flen + 1);
2832 sys_execve(buf.as_ptr() as *const c_char, argv, envp);
2833 }
2835 i += 1; }
2837 _exit(127);
2838}
2839
2840#[no_mangle]
2841pub unsafe extern "C" fn posix_spawnp(
2842 pid: *mut c_int,
2843 file: *const c_char,
2844 fa: *const posix_spawn_file_actions_t,
2845 attrp: *const posix_spawnattr_t,
2846 argv: *const *const c_char,
2847 envp: *const *const c_char,
2848) -> c_int {
2849 let child = sys_fork();
2850 if child < 0 {
2851 ERRNO = EAGAIN;
2852 return -1;
2853 }
2854 if child == 0 {
2855 spawn_apply_attr(attrp);
2857 spawn_apply_actions(fa);
2858 let actual_envp = if envp.is_null() { __environ as *const *const c_char } else { envp };
2859 spawn_execvp(file, argv, actual_envp);
2860 }
2862 *pid = child as c_int;
2863 0
2864}
2865
2866#[no_mangle]
2867pub unsafe extern "C" fn posix_spawn(
2868 pid: *mut c_int,
2869 path: *const c_char,
2870 fa: *const posix_spawn_file_actions_t,
2871 attrp: *const posix_spawnattr_t,
2872 argv: *const *const c_char,
2873 envp: *const *const c_char,
2874) -> c_int {
2875 posix_spawnp(pid, path, fa, attrp, argv, envp)
2878}
2879
2880#[cfg(target_arch = "x86_64")]
2885#[repr(C)]
2886pub struct Stat {
2887 pub st_dev: u64,
2888 pub st_ino: u64,
2889 pub st_nlink: u64,
2890 pub st_mode: u32,
2891 pub st_uid: u32,
2892 pub st_gid: u32,
2893 _pad0: u32,
2894 pub st_rdev: u64,
2895 pub st_size: i64,
2896 pub st_blksize: i64,
2897 pub st_blocks: i64,
2898 pub st_atim: timespec,
2899 pub st_mtim: timespec,
2900 pub st_ctim: timespec,
2901 _unused: [i64; 3],
2902}
2903
2904#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
2905#[repr(C)]
2906pub struct Stat {
2907 pub st_dev: u64,
2908 pub st_ino: u64,
2909 pub st_mode: u32,
2910 pub st_nlink: u32,
2911 pub st_uid: u32,
2912 pub st_gid: u32,
2913 pub st_rdev: u64,
2914 __pad1: u64,
2915 pub st_size: i64,
2916 pub st_blksize: i32,
2917 __pad2: i32,
2918 pub st_blocks: i64,
2919 pub st_atim: timespec,
2920 pub st_mtim: timespec,
2921 pub st_ctim: timespec,
2922 __unused4: u32,
2923 __unused5: u32,
2924}
2925
2926pub const S_IFMT: u32 = 0o170000;
2927pub const S_IFDIR: u32 = 0o040000;
2928pub const S_IFCHR: u32 = 0o020000;
2929pub const S_IFBLK: u32 = 0o060000;
2930pub const S_IFREG: u32 = 0o100000;
2931pub const S_IFLNK: u32 = 0o120000;
2932pub const S_IFIFO: u32 = 0o010000;
2933pub const S_IFSOCK: u32 = 0o140000;
2934
2935pub const AT_FDCWD: i32 = -100;
2936
2937#[no_mangle]
2938pub unsafe extern "C" fn stat(path: *const c_char, buf: *mut Stat) -> c_int {
2939 let r = sys_newfstatat(AT_FDCWD, path, buf as *mut u8, 0);
2940 if r < 0 { ERRNO = (-r) as c_int; return -1; }
2941 if *path == b'/' as c_char && strcmp(path as *const u8, b"/dev/null\0".as_ptr()) == 0 {
2942 (*buf).st_mode = ((*buf).st_mode & !0o170000) | 0o020000;
2943 }
2944 0
2945}
2946
2947#[no_mangle]
2948pub unsafe extern "C" fn fstat(fd: c_int, buf: *mut Stat) -> c_int {
2949 let r = sys_fstat(fd, buf as *mut u8);
2950 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
2951}
2952
2953#[repr(C)]
2958pub struct Rlimit {
2959 pub rlim_cur: u64,
2960 pub rlim_max: u64,
2961}
2962
2963pub const RLIMIT_NOFILE: c_int = 7;
2964pub const RLIMIT_STACK: c_int = 3;
2965pub const RLIMIT_DATA: c_int = 2;
2966pub const RLIMIT_AS: c_int = 9;
2967pub const RLIMIT_CPU: c_int = 0;
2968pub const RLIMIT_FSIZE: c_int = 1;
2969pub const RLIMIT_CORE: c_int = 4;
2970pub const RLIMIT_RSS: c_int = 5;
2971pub const RLIMIT_NPROC: c_int = 6;
2972pub const RLIMIT_MEMLOCK: c_int = 8;
2973pub const RLIMIT_LOCKS: c_int = 10;
2974pub const RLIMIT_SIGPENDING: c_int = 11;
2975pub const RLIMIT_MSGQUEUE: c_int = 12;
2976pub const RLIMIT_NICE: c_int = 13;
2977pub const RLIMIT_RTPRIO: c_int = 14;
2978pub const RLIMIT_RTTIME: c_int = 15;
2979pub const RLIM_INFINITY: u64 = !0u64;
2980
2981#[no_mangle]
2982pub unsafe extern "C" fn getrlimit(resource: c_int, rlim: *mut Rlimit) -> c_int {
2983 let r = sys_getrlimit(resource, rlim as *mut u8);
2984 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
2985}
2986
2987#[no_mangle]
2988pub unsafe extern "C" fn setrlimit(resource: c_int, rlim: *const Rlimit) -> c_int {
2989 let r = sys_setrlimit(resource, rlim as *const u8);
2990 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
2991}
2992
2993#[no_mangle]
2998pub unsafe extern "C" fn utimensat(dirfd: c_int, path: *const c_char, times: *const timespec, flags: c_int) -> c_int {
2999 let r = sys_utimensat(dirfd, path, times as *const u8, flags);
3000 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
3001}
3002
3003#[no_mangle]
3004pub unsafe extern "C" fn futimens(fd: c_int, times: *const timespec) -> c_int {
3005 let r = sys_utimensat(fd, core::ptr::null(), times as *const u8, 0);
3006 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
3007}
3008
3009pub const AF_UNIX: c_int = 1;
3014pub const AF_INET: c_int = 2;
3015pub const AF_INET6: c_int = 10;
3016
3017pub const SOCK_STREAM: c_int = 1;
3018pub const SOCK_DGRAM: c_int = 2;
3019
3020pub const SHUT_RD: c_int = 0;
3021pub const SHUT_WR: c_int = 1;
3022pub const SHUT_RDWR: c_int = 2;
3023
3024pub const SOL_SOCKET: c_int = 1;
3025pub const SO_REUSEADDR: c_int = 2;
3026
3027#[repr(C)]
3028pub struct sockaddr {
3029 pub sa_family: u16,
3030 pub sa_data: [u8; 14],
3031}
3032
3033#[inline]
3034unsafe fn sys_socket(domain: c_int, ty: c_int, protocol: c_int) -> i64 {
3035 <Arch as Syscalls>::syscall3(SYS_SOCKET, domain as i64, ty as i64, protocol as i64)
3036}
3037
3038#[inline]
3039unsafe fn sys_socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> i64 {
3040 <Arch as Syscalls>::syscall4(SYS_SOCKETPAIR, domain as i64, ty as i64, protocol as i64, sv as i64)
3041}
3042
3043#[inline]
3044unsafe fn sys_bind(fd: c_int, addr: *const sockaddr, len: c_uint) -> i64 {
3045 <Arch as Syscalls>::syscall3(SYS_BIND, fd as i64, addr as i64, len as i64)
3046}
3047
3048#[inline]
3049unsafe fn sys_listen(fd: c_int, backlog: c_int) -> i64 {
3050 <Arch as Syscalls>::syscall2(SYS_LISTEN, fd as i64, backlog as i64)
3051}
3052
3053#[inline]
3054unsafe fn sys_accept(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> i64 {
3055 <Arch as Syscalls>::syscall3(SYS_ACCEPT, fd as i64, addr as i64, len as i64)
3056}
3057
3058#[inline]
3059unsafe fn sys_connect(fd: c_int, addr: *const sockaddr, len: c_uint) -> i64 {
3060 <Arch as Syscalls>::syscall3(SYS_CONNECT, fd as i64, addr as i64, len as i64)
3061}
3062
3063#[inline]
3064unsafe fn sys_sendto(fd: c_int,
3065 buf: *const c_void,
3066 len: usize,
3067 flags: c_int,
3068 addr: *const sockaddr,
3069 addrlen: c_uint,) -> i64 {
3070 <Arch as Syscalls>::syscall6(SYS_SENDTO, fd as i64, buf as i64, len as i64, flags as i64, addr as i64, addrlen as i64)
3071}
3072
3073#[inline]
3074unsafe fn sys_recvfrom(fd: c_int,
3075 buf: *mut c_void,
3076 len: usize,
3077 flags: c_int,
3078 addr: *mut sockaddr,
3079 addrlen: *mut c_uint,) -> i64 {
3080 <Arch as Syscalls>::syscall6(SYS_RECVFROM, fd as i64, buf as i64, len as i64, flags as i64, addr as i64, addrlen as i64)
3081}
3082
3083#[inline]
3084unsafe fn sys_shutdown(fd: c_int, how: c_int) -> i64 {
3085 <Arch as Syscalls>::syscall2(SYS_SHUTDOWN, fd as i64, how as i64)
3086}
3087
3088#[inline]
3089unsafe fn sys_setsockopt(fd: c_int,
3090 level: c_int,
3091 optname: c_int,
3092 optval: *const c_void,
3093 optlen: c_uint,) -> i64 {
3094 <Arch as Syscalls>::syscall5(SYS_SETSOCKOPT, fd as i64, level as i64, optname as i64, optval as i64, optlen as i64)
3095}
3096
3097#[inline]
3098unsafe fn sys_getsockname(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> i64 {
3099 <Arch as Syscalls>::syscall3(SYS_GETSOCKNAME, fd as i64, addr as i64, len as i64)
3100}
3101
3102#[no_mangle]
3103pub unsafe extern "C" fn socket(domain: c_int, ty: c_int, protocol: c_int) -> c_int {
3104 let r = sys_socket(domain, ty, protocol);
3105 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3106 r as c_int
3107}
3108
3109#[no_mangle]
3110pub unsafe extern "C" fn socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> c_int {
3111 let r = sys_socketpair(domain, ty, protocol, sv);
3112 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3113 0
3114}
3115
3116#[no_mangle]
3117pub unsafe extern "C" fn bind(fd: c_int, addr: *const sockaddr, len: c_uint) -> c_int {
3118 let r = sys_bind(fd, addr, len);
3119 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3120 0
3121}
3122
3123#[no_mangle]
3124pub unsafe extern "C" fn listen(fd: c_int, backlog: c_int) -> c_int {
3125 let r = sys_listen(fd, backlog);
3126 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3127 0
3128}
3129
3130#[no_mangle]
3131pub unsafe extern "C" fn accept(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> c_int {
3132 let r = sys_accept(fd, addr, len);
3133 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3134 r as c_int
3135}
3136
3137#[no_mangle]
3138pub unsafe extern "C" fn connect(fd: c_int, addr: *const sockaddr, len: c_uint) -> c_int {
3139 let r = sys_connect(fd, addr, len);
3140 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3141 0
3142}
3143
3144#[no_mangle]
3145pub unsafe extern "C" fn send(fd: c_int, buf: *const c_void, len: usize, flags: c_int) -> isize {
3146 let r = sys_sendto(fd, buf, len, flags, core::ptr::null(), 0);
3147 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3148 r as isize
3149}
3150
3151#[no_mangle]
3152pub unsafe extern "C" fn recv(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize {
3153 let r = sys_recvfrom(fd, buf, len, flags, core::ptr::null_mut(), core::ptr::null_mut());
3154 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3155 r as isize
3156}
3157
3158#[no_mangle]
3159pub unsafe extern "C" fn sendto(
3160 fd: c_int,
3161 buf: *const c_void,
3162 len: usize,
3163 flags: c_int,
3164 addr: *const sockaddr,
3165 addrlen: c_uint,
3166) -> isize {
3167 let r = sys_sendto(fd, buf, len, flags, addr, addrlen);
3168 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3169 r as isize
3170}
3171
3172#[no_mangle]
3173pub unsafe extern "C" fn recvfrom(
3174 fd: c_int,
3175 buf: *mut c_void,
3176 len: usize,
3177 flags: c_int,
3178 addr: *mut sockaddr,
3179 addrlen: *mut c_uint,
3180) -> isize {
3181 let r = sys_recvfrom(fd, buf, len, flags, addr, addrlen);
3182 if r < 0 { ERRNO = (-r) as c_int; return -1; }
3183 r as isize
3184}
3185
3186#[no_mangle]
3187pub unsafe extern "C" fn shutdown(fd: c_int, how: c_int) -> c_int {
3188 sys_shutdown(fd, how) as c_int
3189}
3190
3191#[no_mangle]
3192pub unsafe extern "C" fn setsockopt(
3193 fd: c_int,
3194 level: c_int,
3195 optname: c_int,
3196 optval: *const c_void,
3197 optlen: c_uint,
3198) -> c_int {
3199 sys_setsockopt(fd, level, optname, optval, optlen) as c_int
3200}
3201
3202#[no_mangle]
3203pub unsafe extern "C" fn getsockname(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> c_int {
3204 sys_getsockname(fd, addr, len) as c_int
3205}
3206
3207#[no_mangle]
3208pub extern "C" fn htonl(hostlong: c_uint) -> c_uint {
3209 hostlong.to_be()
3210}
3211
3212#[no_mangle]
3213pub extern "C" fn ntohl(netlong: c_uint) -> c_uint {
3214 c_uint::from_be(netlong)
3215}
3216
3217#[no_mangle]
3218pub extern "C" fn htons(hostshort: u16) -> u16 {
3219 hostshort.to_be()
3220}
3221
3222#[no_mangle]
3223pub extern "C" fn ntohs(netshort: u16) -> u16 {
3224 u16::from_be(netshort)
3225}
3226
3227pub type PthreadT = c_ulong;
3228
3229#[repr(C)]
3231pub struct pthread_attr_t {
3232 __i: [c_int; 14],
3233}
3234
3235#[repr(C)]
3238pub struct pthread_mutex_t {
3239 __i: [c_int; 10],
3240}
3241
3242#[repr(C)]
3243pub struct pthread_mutexattr_t {
3244 __attr: c_uint,
3245}
3246
3247#[repr(C)]
3250pub struct pthread_cond_t {
3251 __i: [c_int; 12],
3252}
3253
3254#[repr(C)]
3255pub struct pthread_condattr_t {
3256 __attr: c_uint,
3257}
3258
3259#[repr(C)]
3262pub struct pthread_rwlock_t {
3263 __i: [c_int; 14],
3264}
3265
3266#[repr(C)]
3267pub struct pthread_rwlockattr_t {
3268 __attr: [c_uint; 2],
3269}
3270
3271#[repr(C)]
3273pub struct pthread_barrier_t {
3274 __i: [c_int; 8],
3275}
3276
3277#[repr(C)]
3278pub struct pthread_barrierattr_t {
3279 __attr: c_uint,
3280}
3281
3282pub type pthread_spinlock_t = c_int;
3283pub type pthread_once_t = c_int;
3284pub type pthread_key_t = c_uint;
3285
3286#[repr(C)]
3288pub struct sem_t {
3289 __val: [c_int; 8],
3290}
3291
3292#[repr(C)]
3293pub struct sched_param {
3294 pub sched_priority: c_int,
3295}
3296
3297const CLONE_VM: c_ulong = 0x00000100;
3298const CLONE_FS: c_ulong = 0x00000200;
3299const CLONE_FILES: c_ulong = 0x00000400;
3300const CLONE_SIGHAND: c_ulong = 0x00000800;
3301const CLONE_THREAD: c_ulong = 0x00010000;
3302const CLONE_SYSVSEM: c_ulong = 0x00040000;
3303const CLONE_SETTLS: c_ulong = 0x00080000;
3304const CLONE_PARENT_SETTID: c_ulong = 0x00100000;
3305const CLONE_CHILD_CLEARTID: c_ulong = 0x00200000;
3306
3307const FUTEX_WAIT: c_int = 0;
3308const FUTEX_WAKE: c_int = 1;
3309const FUTEX_LOCK_PI: c_int = 6;
3310const FUTEX_UNLOCK_PI: c_int = 7;
3311const FUTEX_TRYLOCK_PI: c_int = 8;
3312
3313const SIGCANCEL: c_int = 32;
3315
3316const PTHREAD_MUTEX_NORMAL: c_int = 0;
3317const PTHREAD_MUTEX_DEFAULT: c_int = 0;
3318const PTHREAD_MUTEX_RECURSIVE: c_int = 1;
3319const PTHREAD_MUTEX_ERRORCHECK: c_int = 2;
3320
3321const PTHREAD_CREATE_JOINABLE: c_int = 0;
3322const PTHREAD_CREATE_DETACHED: c_int = 1;
3323
3324const PTHREAD_CANCEL_ENABLE: c_int = 0;
3325const PTHREAD_CANCEL_DISABLE: c_int = 1;
3326const PTHREAD_CANCEL_DEFERRED: c_int = 0;
3327const PTHREAD_CANCEL_ASYNCHRONOUS: c_int = 1;
3328
3329const PTHREAD_SCOPE_SYSTEM: c_int = 0;
3330const PTHREAD_PROCESS_PRIVATE: c_int = 0;
3331const PTHREAD_PROCESS_SHARED: c_int = 1;
3332const PTHREAD_INHERIT_SCHED: c_int = 0;
3333const PTHREAD_EXPLICIT_SCHED: c_int = 1;
3334
3335const PTHREAD_BARRIER_SERIAL_THREAD: c_int = -1;
3336
3337const PTHREAD_KEYS_MAX: usize = 128;
3338const PTHREAD_DESTRUCTOR_ITERATIONS: usize = 4;
3339const SEM_VALUE_MAX: c_int = 0x7fffffff;
3340
3341const DT_EXITED: c_int = 0;
3342const DT_EXITING: c_int = 1;
3343const DT_JOINABLE: c_int = 2;
3344const DT_DETACHED: c_int = 3;
3345
3346#[repr(C)]
3348#[derive(Copy, Clone)]
3349pub struct __ptcb {
3350 __f: Option<unsafe extern "C" fn(*mut c_void)>,
3351 __x: *mut c_void,
3352 __next: *mut __ptcb,
3353}
3354
3355#[repr(C)]
3357#[derive(Copy, Clone)]
3358struct robust_list {
3359 next: *mut robust_list,
3360}
3361
3362#[repr(C)]
3363#[derive(Copy, Clone)]
3364struct robust_list_head {
3365 list: robust_list,
3366 futex_offset: c_long,
3367 pending: *mut robust_list,
3368}
3369
3370#[cfg(all(target_arch = "x86_64", not(test)))]
3372core::arch::global_asm!(
3373 ".global __rc_clone",
3374 ".type __rc_clone, @function",
3375 "__rc_clone:",
3376 "mov rax, rdi",
3377 "mov rdi, rdx",
3378 "mov rdx, r8",
3379 "mov r10, [rsp + 8]",
3380 "mov r8, r9",
3381 "mov r9, rax",
3382 "and rsi, -16",
3383 "sub rsi, 8",
3384 "mov [rsi], rcx",
3385 "mov eax, 56",
3386 "syscall",
3387 "test rax, rax",
3388 "jnz 1f",
3389 "pop rdi",
3390 "call r9",
3391 "hlt",
3392 "1:",
3393 "ret",
3394);
3395
3396#[no_mangle]
3398#[unsafe(naked)]
3399#[cfg(target_arch = "aarch64")]
3400pub unsafe extern "C" fn __rc_clone(
3401 fn_: usize,
3402 stack: *mut u8,
3403 flags: c_ulong,
3404 arg: *mut c_void,
3405 ptid: *mut c_int,
3406 tls: c_ulong,
3407 ctid: *mut c_int,
3408) -> i64 {
3409 core::arch::naked_asm!(
3410 "and x1, x1, #-16",
3411 "stp x0, x3, [x1, #-16]!",
3412 "uxtw x0, w2",
3413 "mov x2, x4",
3414 "mov x3, x5",
3415 "mov x4, x6",
3416 "mov x8, #220",
3417 "svc #0",
3418 "cbz x0, 1f",
3419 "ret",
3420 "1:",
3421 "mov x29, #0",
3422 "ldp x1, x0, [sp], #16",
3423 "blr x1",
3424 "mov x8, #93",
3425 "svc #0",
3426 );
3427}
3428
3429#[no_mangle]
3430#[unsafe(naked)]
3431#[cfg(target_arch = "riscv64")]
3432pub unsafe extern "C" fn __rc_clone(
3433 fn_: usize,
3434 stack: *mut u8,
3435 flags: c_ulong,
3436 arg: *mut c_void,
3437 ptid: *mut c_int,
3438 tls: c_ulong,
3439 ctid: *mut c_int,
3440) -> i64 {
3441 core::arch::naked_asm!(
3442 "andi a1, a1, -16",
3443 "addi a1, a1, -16",
3444 "sd a0, 0(a1)",
3445 "sd a3, 8(a1)",
3446 "mv a0, a2",
3447 "mv a2, a4",
3448 "mv a3, a5",
3449 "mv a4, a6",
3450 "li a7, 220",
3451 "ecall",
3452 "beqz a0, 1f",
3453 "ret",
3454 "1:",
3455 "ld a1, 0(sp)",
3456 "ld a0, 8(sp)",
3457 "jalr a1",
3458 "li a7, 93",
3459 "ecall",
3460 );
3461}
3462
3463#[cfg(all(target_arch = "x86_64", test))]
3464#[inline(never)]
3465unsafe fn __rc_clone(
3466 _fn_: usize,
3467 _stack: *mut u8,
3468 _flags: c_ulong,
3469 _arg: *mut c_void,
3470 _ptid: *mut c_int,
3471 _tls: c_ulong,
3472 _ctid: *mut c_int,
3473) -> i64 {
3474 -1
3475}
3476
3477#[cfg(all(target_arch = "x86_64", not(test)))]
3478extern "C" {
3479 fn __rc_clone(
3480 fn_: usize,
3481 stack: *mut u8,
3482 flags: c_ulong,
3483 arg: *mut c_void,
3484 ptid: *mut c_int,
3485 tls: c_ulong,
3486 ctid: *mut c_int,
3487 ) -> i64;
3488}
3489
3490#[inline(never)]
3491#[linkage = "weak"]
3492#[no_mangle]
3493pub extern "C" fn __rc_create_thread_tls() -> *mut u8 {
3494 core::ptr::null_mut()
3495}
3496
3497#[inline(never)]
3498#[linkage = "weak"]
3499#[no_mangle]
3500pub extern "C" fn __rc_tls_block_size() -> usize {
3501 0
3502}
3503
3504#[inline(never)]
3505#[linkage = "weak"]
3506#[no_mangle]
3507pub extern "C" fn __rc_tls_base_offset() -> usize {
3508 0
3509}
3510
3511#[inline]
3512unsafe fn sys_gettid() -> i64 {
3513 <Arch as Syscalls>::syscall0(SYS_GETTID)
3514}
3515
3516#[inline]
3517unsafe fn sys_futex(uaddr: *mut c_int,
3518 futex_op: c_int,
3519 val: c_int,
3520 timeout: *mut c_void,
3521 uaddr2: *mut c_int,
3522 val3: c_int,) -> i64 {
3523 <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)
3524}
3525
3526const MAX_THREADS: usize = 64;
3527const STACK_SIZE: usize = 1024 * 1024;
3528
3529#[repr(C)]
3530#[derive(Copy, Clone)]
3531struct Thread {
3532 tid: c_int,
3533 detach_state: c_int,
3534 result: *mut c_void,
3535 cancel: c_int,
3536 cancel_state: c_int,
3537 cancel_type: c_int,
3538 user_fn: usize,
3539 user_arg: *mut c_void,
3540 stack: *mut u8,
3541 stack_size: usize,
3542 fs_base: *mut u8,
3543 tsd: [*mut c_void; PTHREAD_KEYS_MAX],
3544 cancelbuf: *mut __ptcb,
3545 robust_list: robust_list_head,
3546}
3547
3548static mut THREADS: [Thread; MAX_THREADS] = [Thread {
3549 tid: -1,
3550 detach_state: DT_JOINABLE,
3551 result: core::ptr::null_mut(),
3552 cancel: 0,
3553 cancel_state: PTHREAD_CANCEL_ENABLE,
3554 cancel_type: PTHREAD_CANCEL_DEFERRED,
3555 user_fn: 0,
3556 user_arg: core::ptr::null_mut(),
3557 stack: core::ptr::null_mut(),
3558 stack_size: 0,
3559 fs_base: core::ptr::null_mut(),
3560 tsd: [core::ptr::null_mut(); PTHREAD_KEYS_MAX],
3561 cancelbuf: core::ptr::null_mut(),
3562 robust_list: robust_list_head {
3563 list: robust_list { next: core::ptr::null_mut() },
3564 futex_offset: 0,
3565 pending: core::ptr::null_mut(),
3566 },
3567}; MAX_THREADS];
3568const ALL_SLOT_BITS: usize = if MAX_THREADS >= usize::BITS as usize {
3569 usize::MAX
3570} else {
3571 (1usize << MAX_THREADS) - 1
3572};
3573static SLOT_USED: AtomicUsize = AtomicUsize::new(0);
3574static mut KEY_DTORS: [Option<unsafe extern "C" fn(*mut c_void)>; PTHREAD_KEYS_MAX] = [None; PTHREAD_KEYS_MAX];
3575static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
3576
3577unsafe fn futex_wait(addr: *mut c_int, expected: c_int) -> c_int {
3579 let r = sys_futex(addr, FUTEX_WAIT, expected, null_mut(), null_mut(), 0);
3580 if r < 0 { let e = (-r) as c_int; if e == EAGAIN { 0 } else { e } } else { 0 }
3581}
3582
3583unsafe fn futex_wake(addr: *mut c_int, count: c_int) {
3584 let c = if count < 0 { c_int::MAX } else { count };
3585 sys_futex(addr, FUTEX_WAKE, c, null_mut(), null_mut(), 0);
3586}
3587
3588unsafe fn futex_lock_pi(addr: *mut c_int, abs_timeout: *const timespec) -> c_int {
3589 let timeout_ptr = if abs_timeout.is_null() { null_mut() } else { abs_timeout as *mut c_void };
3590 let r = sys_futex(addr, FUTEX_LOCK_PI, 0, timeout_ptr, null_mut(), 0);
3591 if r < 0 { (-r) as c_int } else { 0 }
3592}
3593
3594unsafe fn futex_unlock_pi(addr: *mut c_int) -> c_int {
3595 let r = sys_futex(addr, FUTEX_UNLOCK_PI, 0, null_mut(), null_mut(), 0);
3596 if r < 0 { (-r) as c_int } else { 0 }
3597}
3598
3599#[inline]
3600unsafe fn sys_set_robust_list(head: *mut robust_list_head, len: usize) -> i64 {
3601 <Arch as Syscalls>::syscall2(SYS_SET_ROBUST_LIST, head as i64, len as i64)
3602}
3603
3604unsafe fn futex_timedwait(addr: *mut c_int, expected: c_int, abs_timeout: *const timespec) -> c_int {
3605 if abs_timeout.is_null() { return futex_wait(addr, expected); }
3606 let mut now: timespec = core::mem::zeroed();
3607 if sys_clock_gettime(CLOCK_REALTIME, &mut now) < 0 { return EINVAL; }
3608 let mut rel: timespec = core::mem::zeroed();
3609 rel.tv_sec = (*abs_timeout).tv_sec - now.tv_sec;
3610 rel.tv_nsec = (*abs_timeout).tv_nsec - now.tv_nsec;
3611 if rel.tv_nsec < 0 { rel.tv_sec -= 1; rel.tv_nsec += 1_000_000_000; }
3612 if rel.tv_sec < 0 { return ETIMEDOUT; }
3613 let r = sys_futex(addr, FUTEX_WAIT, expected, &mut rel as *mut timespec as *mut c_void, null_mut(), 0);
3614 if r < 0 { let e = (-r) as c_int; if e == EAGAIN { 0 } else { e } } else { 0 }
3615}
3616
3617unsafe fn a_cas(addr: *mut c_int, expected: c_int, desired: c_int) -> c_int {
3619 let a = &*(addr as *const AtomicI32);
3620 match a.compare_exchange(expected, desired, Ordering::AcqRel, Ordering::Acquire) {
3621 Ok(v) | Err(v) => v,
3622 }
3623}
3624
3625unsafe fn a_store(addr: *mut c_int, val: c_int) {
3626 (*(addr as *const AtomicI32)).store(val, Ordering::Release);
3627}
3628
3629unsafe fn a_load(addr: *const c_int) -> c_int {
3630 (*(addr as *const AtomicI32)).load(Ordering::Acquire)
3631}
3632
3633unsafe fn a_swap(addr: *mut c_int, val: c_int) -> c_int {
3634 (*(addr as *const AtomicI32)).swap(val, Ordering::AcqRel)
3635}
3636
3637unsafe fn a_fetch_add(addr: *mut c_int, val: c_int) -> c_int {
3638 (*(addr as *const AtomicI32)).fetch_add(val, Ordering::AcqRel)
3639}
3640
3641unsafe fn a_fetch_sub(addr: *mut c_int, val: c_int) -> c_int {
3642 (*(addr as *const AtomicI32)).fetch_sub(val, Ordering::AcqRel)
3643}
3644
3645unsafe fn spinlock_lock(lock: *mut c_int, waiters: *mut c_int) {
3646 while a_swap(lock, 1) != 0 {
3647 let mut spins = 100;
3648 while spins > 0 && a_load(lock) != 0 { core::hint::spin_loop(); spins -= 1; }
3649 if a_load(lock) == 0 { continue; }
3650 a_fetch_add(waiters, 1);
3651 futex_wait(lock, 1);
3652 a_fetch_sub(waiters, 1);
3653 }
3654}
3655
3656unsafe fn spinlock_unlock(lock: *mut c_int, waiters: *mut c_int) {
3657 a_store(lock, 0);
3658 if a_load(waiters) > 0 { futex_wake(lock, 1); }
3659}
3660
3661unsafe fn slot_index(slot: *const Thread) -> usize {
3662 let base = core::ptr::addr_of!(THREADS[0]) as usize;
3663 (slot as usize - base) / core::mem::size_of::<Thread>()
3664}
3665
3666unsafe fn release_thread_slot(slot: *const Thread) {
3667 let idx = slot_index(slot);
3668 if idx < MAX_THREADS {
3669 SLOT_USED.fetch_and(!(1usize << idx), Ordering::AcqRel);
3670 }
3671}
3672
3673unsafe fn alloc_thread_slot() -> Option<&'static mut Thread> {
3674 let mut used = SLOT_USED.load(Ordering::Acquire);
3675 loop {
3676 if used == ALL_SLOT_BITS {
3677 return None;
3678 }
3679 let idx = (!used).trailing_zeros() as usize;
3680 if idx >= MAX_THREADS {
3681 return None;
3682 }
3683 match SLOT_USED.compare_exchange_weak(
3684 used,
3685 used | (1usize << idx),
3686 Ordering::AcqRel,
3687 Ordering::Acquire,
3688 ) {
3689 Ok(_) => return Some(&mut THREADS[idx]),
3690 Err(v) => used = v,
3691 }
3692 }
3693}
3694
3695unsafe fn run_key_dtors(slot: &mut Thread) {
3696 for _ in 0..PTHREAD_DESTRUCTOR_ITERATIONS {
3697 let mut any = false;
3698 for i in 0..PTHREAD_KEYS_MAX {
3699 let val = slot.tsd[i];
3700 if !val.is_null() {
3701 if let Some(dtor) = KEY_DTORS[i] {
3702 slot.tsd[i] = core::ptr::null_mut();
3703 any = true;
3704 dtor(val);
3705 }
3706 }
3707 }
3708 if !any { break; }
3709 }
3710}
3711
3712unsafe extern "C" fn thread_entry(slot: *mut c_void) -> *mut c_void {
3713 let slot = &mut *(slot as *mut Thread);
3714 slot.robust_list.list.next = core::ptr::null_mut();
3717 slot.robust_list.futex_offset = 0;
3718 slot.robust_list.pending = core::ptr::null_mut();
3719 ensure_robust_list(slot);
3720 let mut set: SigSetT = 0;
3721 sigemptyset(&mut set);
3722 sigaddset(&mut set, SIGCANCEL);
3723 pthread_sigmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
3724 let user_fn: unsafe extern "C" fn(*mut c_void) -> *mut c_void =
3725 core::mem::transmute::<usize, _>(slot.user_fn);
3726 let ret = user_fn(slot.user_arg);
3727 run_key_dtors(slot);
3728 slot.result = ret;
3729 a_store(&raw mut slot.detach_state, DT_EXITED);
3730 futex_wake(&raw mut slot.detach_state, 1);
3731 sys_exit_thread(0)
3732}
3733
3734unsafe fn find_thread() -> Option<&'static mut Thread> {
3735 let me = sys_gettid() as c_int;
3736 let base = core::ptr::addr_of_mut!(THREADS[0]);
3737 for i in 0..MAX_THREADS {
3738 let slot = base.add(i);
3739 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3740 return Some(&mut *slot);
3741 }
3742 }
3743 pthread_self();
3745 for i in 0..MAX_THREADS {
3746 let slot = base.add(i);
3747 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3748 return Some(&mut *slot);
3749 }
3750 }
3751 None
3752}
3753
3754#[no_mangle]
3755pub unsafe extern "C" fn pthread_self() -> PthreadT {
3756 let me = sys_gettid() as c_int;
3757 let base = core::ptr::addr_of_mut!(THREADS[0]);
3758 for i in 0..MAX_THREADS {
3759 let slot = base.add(i);
3760 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3761 return slot as PthreadT;
3762 }
3763 }
3764 if let Some(slot) = alloc_thread_slot() {
3766 let slot = slot as *mut Thread;
3767 (*slot).tid = me;
3768 (*slot).detach_state = DT_JOINABLE;
3769 return slot as PthreadT;
3770 }
3771 0
3772}
3773
3774#[no_mangle]
3775pub unsafe extern "C" fn pthread_equal(t1: PthreadT, t2: PthreadT) -> c_int {
3776 (t1 == t2) as c_int
3777}
3778
3779#[no_mangle]
3780pub unsafe extern "C" fn pthread_create(
3781 thread: *mut PthreadT,
3782 attr: *const pthread_attr_t,
3783 start_routine: usize,
3784 arg: *mut c_void,
3785) -> c_int {
3786 if start_routine == 0 || thread.is_null() { return EINVAL; }
3787 let Some(slot_ref) = alloc_thread_slot() else { return EAGAIN; };
3788 let slot = slot_ref as *mut Thread;
3789 let stack_size = if !attr.is_null() {
3790 let s = *((*attr).__i.as_ptr() as *const usize);
3791 if s > 0 { s } else { STACK_SIZE }
3792 } else { STACK_SIZE };
3793 let stack = sys_mmap(null_mut(), stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
3794 if stack == MMAP_FAILED { release_thread_slot(slot); return EAGAIN; }
3795 let fs_base = __rc_create_thread_tls();
3796 if fs_base.is_null() { sys_munmap(stack, stack_size); release_thread_slot(slot); return EAGAIN; }
3797 (*slot).detach_state = DT_JOINABLE;
3798 (*slot).result = core::ptr::null_mut();
3799 (*slot).cancel = 0;
3800 (*slot).cancel_state = PTHREAD_CANCEL_ENABLE;
3801 (*slot).cancel_type = PTHREAD_CANCEL_DEFERRED;
3802 core::ptr::write_bytes((*slot).tsd.as_mut_ptr(), 0, PTHREAD_KEYS_MAX);
3803 (*slot).tid = 1;
3804 (*slot).user_fn = start_routine;
3805 (*slot).user_arg = arg;
3806 (*slot).stack = stack;
3807 (*slot).stack_size = stack_size;
3808 (*slot).fs_base = fs_base;
3809 let stack_top = stack.add(stack_size);
3810 let tid_ptr = &raw mut (*slot).tid;
3811 let flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD
3812 | CLONE_SYSVSEM | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SETTLS;
3813 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);
3814 if tid < 0 {
3815 (*slot).tid = -1;
3816 sys_munmap(stack, stack_size);
3817 sys_munmap(fs_base.sub(__rc_tls_base_offset()), __rc_tls_block_size());
3818 release_thread_slot(slot);
3819 return EAGAIN;
3820 }
3821 if !attr.is_null() && (*attr).__i[6] == PTHREAD_CREATE_DETACHED {
3822 (*slot).detach_state = DT_DETACHED;
3823 }
3824 *thread = slot as PthreadT;
3825 0
3826}
3827
3828#[no_mangle]
3829pub unsafe extern "C" fn pthread_join(thread: PthreadT, retval: *mut *mut c_void) -> c_int {
3830 let slot = thread as *mut Thread;
3831 if slot.is_null() { return EINVAL; }
3832 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
3833 let tid_ptr = &raw mut (*slot).tid;
3834 loop {
3835 pthread_testcancel();
3836 let tid = core::ptr::read_volatile(tid_ptr);
3837 if tid == 0 { break; }
3838 if tid < 0 { return EINVAL; }
3839 sys_futex(tid_ptr, FUTEX_WAIT, tid, null_mut(), null_mut(), 0);
3840 pthread_testcancel();
3841 }
3842 if !retval.is_null() { *retval = (*slot).result; }
3843 let stack = (*slot).stack;
3844 let stack_size = (*slot).stack_size;
3845 let fs_base = (*slot).fs_base;
3846 (*slot).tid = -1;
3847 (*slot).detach_state = DT_JOINABLE;
3848 (*slot).result = core::ptr::null_mut();
3849 (*slot).stack = core::ptr::null_mut();
3850 (*slot).stack_size = 0;
3851 (*slot).fs_base = core::ptr::null_mut();
3852 if !stack.is_null() && stack_size > 0 { sys_munmap(stack, stack_size); }
3853 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); } }
3854 release_thread_slot(slot);
3855 0
3856}
3857
3858#[no_mangle]
3859pub unsafe extern "C" fn pthread_detach(thread: PthreadT) -> c_int {
3860 let slot = thread as *mut Thread;
3861 if slot.is_null() { return EINVAL; }
3862 let old = a_cas(&raw mut (*slot).detach_state, DT_JOINABLE, DT_DETACHED);
3863 if old == DT_EXITED {
3864 let stack = (*slot).stack;
3865 let stack_size = (*slot).stack_size;
3866 let fs_base = (*slot).fs_base;
3867 (*slot).tid = -1;
3868 (*slot).stack = core::ptr::null_mut();
3869 (*slot).stack_size = 0;
3870 (*slot).fs_base = core::ptr::null_mut();
3871 if !stack.is_null() && stack_size > 0 { sys_munmap(stack, stack_size); }
3872 if !fs_base.is_null() { let bs = __rc_tls_block_size(); let bo = __rc_tls_base_offset(); sys_munmap(fs_base.sub(bo), bs); }
3873 release_thread_slot(slot);
3874 }
3875 0
3876}
3877
3878#[no_mangle]
3879pub unsafe extern "C" fn pthread_exit(retval: *mut c_void) -> ! {
3880 if let Some(slot) = find_thread() {
3881 run_cleanup_handlers(slot);
3882 run_key_dtors(slot);
3883 slot.result = retval;
3884 slot.detach_state = DT_EXITED;
3885 futex_wake(&slot.detach_state as *const c_int as *mut c_int, 1);
3886
3887 let mut active = 0usize;
3889 for i in 0..MAX_THREADS {
3890 if THREADS[i].tid > 0 {
3891 active += 1;
3892 }
3893 }
3894 if active == 1 {
3895 exit(0);
3896 }
3897 }
3898 sys_exit_thread(0);
3899}
3900
3901#[no_mangle]
3903pub unsafe extern "C" fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int {
3904 core::ptr::write_bytes(attr, 0, 1);
3905 *((*attr).__i.as_mut_ptr() as *mut usize) = STACK_SIZE;
3906 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = 4096;
3907 (*attr).__i[6] = PTHREAD_CREATE_JOINABLE;
3908 (*attr).__i[7] = PTHREAD_INHERIT_SCHED;
3909 0
3910}
3911#[no_mangle]
3912pub unsafe extern "C" fn pthread_attr_destroy(_attr: *mut pthread_attr_t) -> c_int { 0 }
3913#[no_mangle]
3914pub unsafe extern "C" fn pthread_attr_setdetachstate(attr: *mut pthread_attr_t, s: c_int) -> c_int {
3915 if s != PTHREAD_CREATE_JOINABLE && s != PTHREAD_CREATE_DETACHED { return EINVAL; }
3916 (*attr).__i[6] = s; 0
3917}
3918#[no_mangle]
3919pub unsafe extern "C" fn pthread_attr_getdetachstate(attr: *const pthread_attr_t, s: *mut c_int) -> c_int {
3920 *s = (*attr).__i[6]; 0
3921}
3922#[no_mangle]
3923pub unsafe extern "C" fn pthread_attr_setstacksize(attr: *mut pthread_attr_t, sz: usize) -> c_int {
3924 if sz < 16384 { return EINVAL; }
3925 *((*attr).__i.as_mut_ptr() as *mut usize) = sz; 0
3926}
3927#[no_mangle]
3928pub unsafe extern "C" fn pthread_attr_getstacksize(attr: *const pthread_attr_t, sz: *mut usize) -> c_int {
3929 *sz = *((*attr).__i.as_ptr() as *const usize); 0
3930}
3931#[no_mangle]
3932pub unsafe extern "C" fn pthread_attr_setstack(attr: *mut pthread_attr_t, addr: *mut c_void, sz: usize) -> c_int {
3933 if sz < 16384 { return EINVAL; }
3934 *((*attr).__i.as_mut_ptr() as *mut usize) = sz;
3935 *((*attr).__i.as_mut_ptr().add(4) as *mut *mut c_void) = addr; 0
3936}
3937#[no_mangle]
3938pub unsafe extern "C" fn pthread_attr_getstack(attr: *const pthread_attr_t, addr: *mut *mut c_void, sz: *mut usize) -> c_int {
3939 *sz = *((*attr).__i.as_ptr() as *const usize);
3940 *addr = *((*attr).__i.as_ptr().add(4) as *const *mut c_void); 0
3941}
3942#[no_mangle]
3943pub unsafe extern "C" fn pthread_attr_setguardsize(attr: *mut pthread_attr_t, sz: usize) -> c_int {
3944 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = sz; 0
3945}
3946#[no_mangle]
3947pub unsafe extern "C" fn pthread_attr_getguardsize(attr: *const pthread_attr_t, sz: *mut usize) -> c_int {
3948 *sz = *((*attr).__i.as_ptr().add(2) as *const usize); 0
3949}
3950#[no_mangle]
3951pub unsafe extern "C" fn pthread_attr_setscope(_attr: *mut pthread_attr_t, scope: c_int) -> c_int {
3952 if scope != PTHREAD_SCOPE_SYSTEM { return EINVAL; }
3953 0
3954}
3955#[no_mangle]
3956pub unsafe extern "C" fn pthread_attr_getscope(_attr: *const pthread_attr_t, scope: *mut c_int) -> c_int {
3957 *scope = PTHREAD_SCOPE_SYSTEM; 0
3958}
3959#[no_mangle]
3960pub unsafe extern "C" fn pthread_attr_setinheritsched(attr: *mut pthread_attr_t, inh: c_int) -> c_int {
3961 if inh != PTHREAD_INHERIT_SCHED && inh != PTHREAD_EXPLICIT_SCHED { return EINVAL; }
3962 (*attr).__i[7] = inh; 0
3963}
3964#[no_mangle]
3965pub unsafe extern "C" fn pthread_attr_getinheritsched(attr: *const pthread_attr_t, inh: *mut c_int) -> c_int {
3966 *inh = (*attr).__i[7]; 0
3967}
3968#[no_mangle]
3969pub unsafe extern "C" fn pthread_attr_setschedpolicy(attr: *mut pthread_attr_t, p: c_int) -> c_int {
3970 (*attr).__i[8] = p; 0
3971}
3972#[no_mangle]
3973pub unsafe extern "C" fn pthread_attr_getschedpolicy(attr: *const pthread_attr_t, p: *mut c_int) -> c_int {
3974 *p = (*attr).__i[8]; 0
3975}
3976#[no_mangle]
3977pub unsafe extern "C" fn pthread_attr_setschedparam(attr: *mut pthread_attr_t, param: *const sched_param) -> c_int {
3978 (*attr).__i[9] = (*param).sched_priority; 0
3979}
3980#[no_mangle]
3981pub unsafe extern "C" fn pthread_attr_getschedparam(attr: *const pthread_attr_t, param: *mut sched_param) -> c_int {
3982 (*param).sched_priority = (*attr).__i[9]; 0
3983}
3984
3985#[no_mangle]
3987pub unsafe extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int {
3988 (*attr).__attr = 0; 0
3989}
3990#[no_mangle]
3991pub unsafe extern "C" fn pthread_mutexattr_destroy(_attr: *mut pthread_mutexattr_t) -> c_int { 0 }
3992#[no_mangle]
3993pub unsafe extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, t: c_int) -> c_int {
3994 if (t as c_uint) > 2 { return EINVAL; }
3995 (*attr).__attr = ((*attr).__attr & !3) | t as c_uint; 0
3996}
3997#[no_mangle]
3998pub unsafe extern "C" fn pthread_mutexattr_gettype(attr: *const pthread_mutexattr_t, t: *mut c_int) -> c_int {
3999 *t = ((*attr).__attr & 3) as c_int; 0
4000}
4001#[no_mangle]
4002pub unsafe extern "C" fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, p: c_int) -> c_int {
4003 if (p as c_uint) > 1 { return EINVAL; }
4004 (*attr).__attr = ((*attr).__attr & !128) | ((p as c_uint) << 7); 0
4005}
4006#[no_mangle]
4007pub unsafe extern "C" fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, p: *mut c_int) -> c_int {
4008 *p = (((*attr).__attr >> 7) & 1) as c_int; 0
4009}
4010
4011#[no_mangle]
4012pub unsafe extern "C" fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int {
4013 match protocol {
4014 0 => { (*attr).__attr &= !(MUTEX_PI as c_uint); 0 }
4015 1 => {
4016 let mut lk: c_int = 0;
4017 let r = sys_futex(&raw mut lk, FUTEX_LOCK_PI, 0, null_mut(), null_mut(), 0);
4018 if r < 0 { return (-r) as c_int; }
4019 sys_futex(&raw mut lk, FUTEX_UNLOCK_PI, 0, null_mut(), null_mut(), 0);
4020 (*attr).__attr |= MUTEX_PI as c_uint;
4021 0
4022 }
4023 2 => ENOTSUP,
4024 _ => EINVAL,
4025 }
4026}
4027#[no_mangle]
4028pub unsafe extern "C" fn pthread_mutexattr_getprotocol(attr: *const pthread_mutexattr_t, protocol: *mut c_int) -> c_int {
4029 *protocol = (((*attr).__attr >> 3) & 3) as c_int; 0
4030}
4031
4032const ENOTSUP: c_int = 95;
4033
4034#[no_mangle]
4035pub unsafe extern "C" fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robust: c_int) -> c_int {
4036 if (robust as c_uint) > 1 { return EINVAL; }
4037 if robust != 0 {
4038 (*attr).__attr |= MUTEX_ROBUST as c_uint;
4039 } else {
4040 (*attr).__attr &= !(MUTEX_ROBUST as c_uint);
4041 }
4042 0
4043}
4044#[no_mangle]
4045pub unsafe extern "C" fn pthread_mutexattr_getrobust(attr: *const pthread_mutexattr_t, robust: *mut c_int) -> c_int {
4046 *robust = (((*attr).__attr >> 2) & 1) as c_int; 0
4047}
4048
4049#[no_mangle]
4050pub unsafe extern "C" fn pthread_mutex_consistent(m: *mut pthread_mutex_t) -> c_int {
4051 let old = a_load(&raw const (*m).__i[1]);
4052 let own = old & 0x3fffffff;
4053 if ((*m).__i[0] & MUTEX_ROBUST) == 0 || own == 0 || (old & 0x40000000) == 0 {
4054 return EINVAL;
4055 }
4056 let self_tid = sys_gettid() as c_int;
4057 if own != self_tid { return EPERM; }
4058 a_and(&raw mut (*m).__i[1], !(0x40000000i32));
4059 0
4060}
4061
4062unsafe fn a_and(addr: *mut c_int, val: c_int) {
4063 let a = &*(addr as *const AtomicI32);
4064 a.fetch_and(val, Ordering::AcqRel);
4065}
4066
4067const MUTEX_TYPE_MASK: c_int = 3;
4069const MUTEX_ROBUST: c_int = 4;
4070const MUTEX_PI: c_int = 8;
4071const MUTEX_PSHARED: c_int = 128;
4072
4073unsafe fn ensure_robust_list(slot: &mut Thread) {
4074 if slot.robust_list.futex_offset == 0 {
4075 slot.robust_list.futex_offset = -28;
4076 slot.robust_list.pending = core::ptr::null_mut();
4077 sys_set_robust_list(&mut slot.robust_list, 24);
4078 }
4079}
4080
4081unsafe fn mutex_trylock(m: *mut pthread_mutex_t) -> c_int {
4082 let type_ = (*m).__i[0];
4083 if (type_ & 0x8f) == PTHREAD_MUTEX_NORMAL {
4088 let old = a_cas(&raw mut (*m).__i[1], 0, EBUSY);
4089 return if old == 0 { 0 } else { EBUSY };
4090 }
4091 let base_type = type_ & MUTEX_TYPE_MASK;
4092 let self_tid = sys_gettid() as c_int;
4093 let old = a_load(&raw const (*m).__i[1]);
4094 let own = old & 0x3fffffff;
4095 if own == self_tid {
4096 if (type_ & MUTEX_PI) != 0 && (*m).__i[5] < 0 {
4097 (*m).__i[5] = 0;
4098 return 0;
4099 }
4100 if base_type == PTHREAD_MUTEX_RECURSIVE {
4101 if (*m).__i[5] >= c_int::MAX { return EAGAIN; }
4102 (*m).__i[5] += 1;
4103 return 0;
4104 }
4105 if base_type == PTHREAD_MUTEX_ERRORCHECK { return EDEADLK; }
4106 return EBUSY;
4107 }
4108 if own == 0x3fffffff { return ENOTRECOVERABLE; }
4109 if own != 0 || (old != 0 && (type_ & MUTEX_ROBUST) == 0) { return EBUSY; }
4110 let mut newtid = self_tid;
4111 if (type_ & MUTEX_ROBUST) != 0 {
4112 if (*m).__i[2] != 0 { newtid |= 1i32 << 31; }
4113 newtid |= old & 0x40000000;
4114 }
4115 if a_cas(&raw mut (*m).__i[1], old, newtid) == old {
4116 (*m).__i[5] = 0;
4117 if (type_ & MUTEX_ROBUST) != 0 {
4118 if let Some(slot) = find_thread() {
4119 ensure_robust_list(slot);
4120 let m_next = &raw mut (*m).__i[8] as *mut robust_list;
4121 let head = &mut slot.robust_list.list;
4122 (*m_next).next = head.next;
4123 head.next = m_next;
4124 }
4125 }
4126 if old != 0 { return EOWNERDEAD; }
4127 0
4128 } else { EBUSY }
4129}
4130
4131unsafe fn mutex_lock_internal(m: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4132 let type_ = (*m).__i[0];
4133 if (type_ & 0x8f) == PTHREAD_MUTEX_NORMAL && a_cas(&raw mut (*m).__i[1], 0, EBUSY) == 0 {
4134 return 0;
4135 }
4136 let r = mutex_trylock(m);
4137 if r != EBUSY { return r; }
4138 if (type_ & MUTEX_PI) != 0 {
4139 let timeout_ptr = if abs_timeout.is_null() { core::ptr::null() } else { abs_timeout };
4140 loop {
4141 let e = futex_lock_pi(&raw mut (*m).__i[1], timeout_ptr);
4142 match e {
4143 0 => {
4144 if (type_ & MUTEX_ROBUST) != 0 && (((*m).__i[1] & 0x40000000) != 0 || (*m).__i[2] != 0) {
4145 (*m).__i[5] = -1;
4146 let _ = mutex_trylock(m);
4147 return EOWNERDEAD;
4148 }
4149 if (type_ & MUTEX_ROBUST) == 0 && (((*m).__i[1] & 0x40000000) != 0 || (*m).__i[2] != 0) {
4150 (*m).__i[2] = -1;
4151 futex_unlock_pi(&raw mut (*m).__i[1]);
4152 return EBUSY;
4153 }
4154 (*m).__i[5] = -1;
4155 let r2 = mutex_trylock(m);
4156 if r2 == 0 { return 0; }
4157 return r2;
4158 }
4159 EINTR => continue,
4160 EDEADLK => {
4161 if (type_ & MUTEX_TYPE_MASK) == PTHREAD_MUTEX_ERRORCHECK { return e; }
4162 loop { pause(); }
4163 }
4164 EOWNERDEAD => {
4165 (*m).__i[5] = -1;
4166 let _ = mutex_trylock(m);
4167 return EOWNERDEAD;
4168 }
4169 _ => return e,
4170 }
4171 }
4172 }
4173 let mut spins = 100;
4174 while spins > 0 {
4175 let r = mutex_trylock(m);
4176 if r != EBUSY { return r; }
4177 core::hint::spin_loop();
4178 spins -= 1;
4179 }
4180 loop {
4181 let r = mutex_trylock(m);
4182 if r != EBUSY { return r; }
4183 if (type_ & MUTEX_TYPE_MASK) == PTHREAD_MUTEX_ERRORCHECK {
4184 let self_tid = sys_gettid() as c_int;
4185 if (a_load(&raw const (*m).__i[1]) & 0x3fffffff) == self_tid { return EDEADLK; }
4186 }
4187 a_fetch_add(&raw mut (*m).__i[2], 1);
4188 let val = a_load(&raw const (*m).__i[1]);
4189 if val == 0 {
4193 a_fetch_sub(&raw mut (*m).__i[2], 1);
4194 continue;
4195 }
4196 a_cas(&raw mut (*m).__i[1], val, val | (1i32 << 31));
4197 let e = futex_timedwait(&raw mut (*m).__i[1], val | (1i32 << 31), abs_timeout);
4198 a_fetch_sub(&raw mut (*m).__i[2], 1);
4199 if e != 0 && e != EINTR { return e; }
4200 }
4201}
4202
4203#[no_mangle]
4204pub unsafe extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t) -> c_int {
4205 core::ptr::write_bytes(mutex, 0, 1);
4206 if !attr.is_null() { (*mutex).__i[0] = (*attr).__attr as c_int; }
4207 0
4208}
4209#[no_mangle]
4210pub unsafe extern "C" fn pthread_mutex_destroy(_mutex: *mut pthread_mutex_t) -> c_int { 0 }
4211#[no_mangle]
4212pub unsafe extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int {
4213 mutex_lock_internal(mutex, core::ptr::null())
4214}
4215#[no_mangle]
4216pub unsafe extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int {
4217 mutex_trylock(mutex)
4218}
4219#[no_mangle]
4220pub unsafe extern "C" fn pthread_mutex_timedlock(mutex: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4221 mutex_lock_internal(mutex, abs_timeout)
4222}
4223#[no_mangle]
4224pub unsafe extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int {
4225 let type_ = (*mutex).__i[0];
4226 let base_type = type_ & MUTEX_TYPE_MASK;
4227 let old = a_load(&raw const (*mutex).__i[1]);
4228 if base_type != PTHREAD_MUTEX_NORMAL {
4229 let self_tid = sys_gettid() as c_int;
4230 if (old & 0x3fffffff) != self_tid { return EPERM; }
4231 if base_type == PTHREAD_MUTEX_RECURSIVE && (*mutex).__i[5] > 0 {
4232 (*mutex).__i[5] -= 1;
4233 return 0;
4234 }
4235 }
4236 let mut new = 0;
4237 if (type_ & MUTEX_ROBUST) != 0 && (old & 0x40000000) != 0 {
4238 new = 0x7fffffff;
4239 }
4240 if (type_ & MUTEX_PI) != 0 {
4241 if old < 0 || a_cas(&raw mut (*mutex).__i[1], old, new) != old {
4242 if new != 0 { a_store(&raw mut (*mutex).__i[2], -1); }
4243 return futex_unlock_pi(&raw mut (*mutex).__i[1]);
4244 }
4245 return 0;
4246 }
4247 a_store(&raw mut (*mutex).__i[1], new);
4248 if new == 0 && (a_load(&raw const (*mutex).__i[2]) > 0 || old < 0) {
4249 futex_wake(&raw mut (*mutex).__i[1], 1);
4250 }
4251 0
4252}
4253
4254#[no_mangle]
4256pub unsafe extern "C" fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> c_int {
4257 (*attr).__attr = 0; 0
4258}
4259#[no_mangle]
4260pub unsafe extern "C" fn pthread_condattr_destroy(_attr: *mut pthread_condattr_t) -> c_int { 0 }
4261#[no_mangle]
4262pub unsafe extern "C" fn pthread_condattr_setclock(attr: *mut pthread_condattr_t, clk: c_int) -> c_int {
4263 if clk != CLOCK_REALTIME && clk != CLOCK_MONOTONIC { return EINVAL; }
4264 (*attr).__attr = ((*attr).__attr & 0x80000000) | clk as c_uint; 0
4265}
4266#[no_mangle]
4267pub unsafe extern "C" fn pthread_condattr_getclock(attr: *const pthread_condattr_t, clk: *mut c_int) -> c_int {
4268 *clk = ((*attr).__attr & 0x7fffffff) as c_int; 0
4269}
4270#[no_mangle]
4271pub unsafe extern "C" fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, p: c_int) -> c_int {
4272 if (p as c_uint) > 1 { return EINVAL; }
4273 (*attr).__attr = ((*attr).__attr & 0x7fffffff) | ((p as c_uint) << 31); 0
4274}
4275#[no_mangle]
4276pub unsafe extern "C" fn pthread_condattr_getpshared(attr: *const pthread_condattr_t, p: *mut c_int) -> c_int {
4277 *p = ((*attr).__attr >> 31) as c_int; 0
4278}
4279
4280#[no_mangle]
4282pub unsafe extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int {
4283 core::ptr::write_bytes(cond, 0, 1);
4284 if !attr.is_null() {
4285 (*cond).__i[4] = ((*attr).__attr & 0x7fffffff) as c_int;
4286 }
4287 0
4288}
4289#[no_mangle]
4290pub unsafe extern "C" fn pthread_cond_destroy(_cond: *mut pthread_cond_t) -> c_int { 0 }
4291#[no_mangle]
4292pub unsafe extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t) -> c_int {
4293 pthread_cond_timedwait(cond, mutex, core::ptr::null())
4294}
4295
4296
4297#[no_mangle]
4298pub unsafe extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4299 pthread_testcancel();
4300 let seq_ptr = &raw mut (*cond).__i[2];
4301 let waiters_ptr = &raw mut (*cond).__i[3];
4302 let seq = a_load(seq_ptr);
4303 a_fetch_add(waiters_ptr, 1);
4304 pthread_mutex_unlock(mutex);
4305 let e = futex_timedwait(seq_ptr, seq, abs_timeout);
4306 a_fetch_sub(waiters_ptr, 1);
4307 let r = pthread_mutex_lock(mutex);
4308 if r != 0 { return r; }
4309 if e == EINTR {
4310 pthread_testcancel();
4311 }
4312 if e != 0 && e != EINTR { return e; }
4313 0
4314}
4315#[no_mangle]
4316pub unsafe extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int {
4317 if a_load(&raw const (*cond).__i[3]) == 0 { return 0; }
4318 a_fetch_add(&raw mut (*cond).__i[2], 1);
4319 futex_wake(&raw mut (*cond).__i[2], 1);
4320 0
4321}
4322#[no_mangle]
4323pub unsafe extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int {
4324 if a_load(&raw const (*cond).__i[3]) == 0 { return 0; }
4325 a_fetch_add(&raw mut (*cond).__i[2], 1);
4326 futex_wake(&raw mut (*cond).__i[2], -1);
4327 0
4328}
4329
4330#[no_mangle]
4332pub unsafe extern "C" fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> c_int {
4333 (*attr).__attr = [0; 2]; 0
4334}
4335#[no_mangle]
4336pub unsafe extern "C" fn pthread_rwlockattr_destroy(_attr: *mut pthread_rwlockattr_t) -> c_int { 0 }
4337#[no_mangle]
4338pub unsafe extern "C" fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, p: c_int) -> c_int {
4339 if (p as c_uint) > 1 { return EINVAL; }
4340 (*attr).__attr[0] = ((*attr).__attr[0] & !128) | ((p as c_uint) << 7); 0
4341}
4342#[no_mangle]
4343pub unsafe extern "C" fn pthread_rwlockattr_getpshared(attr: *const pthread_rwlockattr_t, p: *mut c_int) -> c_int {
4344 *p = (((*attr).__attr[0] >> 7) & 1) as c_int; 0
4345}
4346
4347unsafe fn rwlock_tryrdlock(rw: *mut pthread_rwlock_t) -> c_int {
4349 loop {
4350 let val = a_load(&raw const (*rw).__i[0]);
4351 let cnt = val & 0x7fffffff;
4352 if cnt == 0x7fffffff { return EBUSY; }
4353 if cnt == 0x7ffffffe { return EAGAIN; }
4354 if a_cas(&raw mut (*rw).__i[0], val, val + 1) == val { return 0; }
4355 }
4356}
4357unsafe fn rwlock_trywrlock(rw: *mut pthread_rwlock_t) -> c_int {
4358 if a_cas(&raw mut (*rw).__i[0], 0, 0x7fffffff) == 0 { 0 } else { EBUSY }
4359}
4360unsafe fn rwlock_timedrdlock(rw: *mut pthread_rwlock_t, abs_timeout: *const timespec) -> c_int {
4361 let r = rwlock_tryrdlock(rw);
4362 if r != EBUSY { return r; }
4363 let mut spins = 100;
4364 while spins > 0 { let r = rwlock_tryrdlock(rw); if r != EBUSY { return r; } core::hint::spin_loop(); spins -= 1; }
4365 loop {
4366 let r = rwlock_tryrdlock(rw);
4367 if r != EBUSY { return r; }
4368 let val = a_load(&raw const (*rw).__i[0]);
4369 if val & 0x7fffffff != 0x7fffffff { continue; }
4370 a_fetch_add(&raw mut (*rw).__i[1], 1);
4371 a_cas(&raw mut (*rw).__i[0], val, val | (1i32 << 31));
4372 let e = futex_timedwait(&raw mut (*rw).__i[0], val | (1i32 << 31), abs_timeout);
4373 a_fetch_sub(&raw mut (*rw).__i[1], 1);
4374 if e != 0 && e != EINTR { return e; }
4375 }
4376}
4377unsafe fn rwlock_timedwrlock(rw: *mut pthread_rwlock_t, abs_timeout: *const timespec) -> c_int {
4378 let r = rwlock_trywrlock(rw);
4379 if r != EBUSY { return r; }
4380 let mut spins = 100;
4381 while spins > 0 { let r = rwlock_trywrlock(rw); if r != EBUSY { return r; } core::hint::spin_loop(); spins -= 1; }
4382 loop {
4383 let r = rwlock_trywrlock(rw);
4384 if r != EBUSY { return r; }
4385 let val = a_load(&raw const (*rw).__i[0]);
4386 if val == 0 { continue; }
4387 a_fetch_add(&raw mut (*rw).__i[1], 1);
4388 a_cas(&raw mut (*rw).__i[0], val, val | (1i32 << 31));
4389 let e = futex_timedwait(&raw mut (*rw).__i[0], val | (1i32 << 31), abs_timeout);
4390 a_fetch_sub(&raw mut (*rw).__i[1], 1);
4391 if e != 0 && e != EINTR { return e; }
4392 }
4393}
4394
4395#[no_mangle]
4396pub unsafe extern "C" fn pthread_rwlock_init(rw: *mut pthread_rwlock_t, attr: *const pthread_rwlockattr_t) -> c_int {
4397 core::ptr::write_bytes(rw, 0, 1);
4398 if !attr.is_null() { (*rw).__i[2] = (*attr).__attr[0] as c_int & 128; }
4399 0
4400}
4401#[no_mangle]
4402pub unsafe extern "C" fn pthread_rwlock_destroy(_rw: *mut pthread_rwlock_t) -> c_int { 0 }
4403#[no_mangle]
4404pub unsafe extern "C" fn pthread_rwlock_rdlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_timedrdlock(rw, core::ptr::null()) }
4405#[no_mangle]
4406pub unsafe extern "C" fn pthread_rwlock_tryrdlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_tryrdlock(rw) }
4407#[no_mangle]
4408pub unsafe extern "C" fn pthread_rwlock_timedrdlock(rw: *mut pthread_rwlock_t, t: *const timespec) -> c_int { rwlock_timedrdlock(rw, t) }
4409#[no_mangle]
4410pub unsafe extern "C" fn pthread_rwlock_wrlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_timedwrlock(rw, core::ptr::null()) }
4411#[no_mangle]
4412pub unsafe extern "C" fn pthread_rwlock_trywrlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_trywrlock(rw) }
4413#[no_mangle]
4414pub unsafe extern "C" fn pthread_rwlock_timedwrlock(rw: *mut pthread_rwlock_t, t: *const timespec) -> c_int { rwlock_timedwrlock(rw, t) }
4415#[no_mangle]
4416pub unsafe extern "C" fn pthread_rwlock_unlock(rw: *mut pthread_rwlock_t) -> c_int {
4417 loop {
4418 let val = a_load(&raw const (*rw).__i[0]);
4419 let cnt = val & 0x7fffffff;
4420 let new_val = if cnt == 0x7fffffff || cnt == 1 { 0 } else { val - 1 };
4421 if a_cas(&raw mut (*rw).__i[0], val, new_val) == val {
4422 if new_val == 0 && (a_load(&raw const (*rw).__i[1]) > 0 || val < 0) {
4423 futex_wake(&raw mut (*rw).__i[0], cnt);
4424 }
4425 return 0;
4426 }
4427 }
4428}
4429
4430#[no_mangle]
4432pub unsafe extern "C" fn pthread_barrierattr_init(attr: *mut pthread_barrierattr_t) -> c_int { (*attr).__attr = 0; 0 }
4433#[no_mangle]
4434pub unsafe extern "C" fn pthread_barrierattr_destroy(_attr: *mut pthread_barrierattr_t) -> c_int { 0 }
4435#[no_mangle]
4436pub unsafe extern "C" fn pthread_barrierattr_setpshared(attr: *mut pthread_barrierattr_t, p: c_int) -> c_int {
4437 if (p as c_uint) > 1 { return EINVAL; }
4438 (*attr).__attr = p as c_uint; 0
4439}
4440#[no_mangle]
4441pub unsafe extern "C" fn pthread_barrierattr_getpshared(attr: *const pthread_barrierattr_t, p: *mut c_int) -> c_int {
4442 *p = (*attr).__attr as c_int; 0
4443}
4444
4445#[no_mangle]
4447pub unsafe extern "C" fn pthread_barrier_init(b: *mut pthread_barrier_t, _attr: *const pthread_barrierattr_t, count: c_uint) -> c_int {
4448 if count == 0 { return EINVAL; }
4449 core::ptr::write_bytes(b, 0, 1);
4450 (*b).__i[2] = count as c_int - 1;
4451 0
4452}
4453#[no_mangle]
4454pub unsafe extern "C" fn pthread_barrier_destroy(_b: *mut pthread_barrier_t) -> c_int { 0 }
4455#[no_mangle]
4456pub unsafe extern "C" fn pthread_barrier_wait(b: *mut pthread_barrier_t) -> c_int {
4457 let limit = (*b).__i[2];
4458 if limit == 0 { return PTHREAD_BARRIER_SERIAL_THREAD; }
4459 spinlock_lock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4460 let arrived = a_load(&raw const (*b).__i[3]) + 1;
4461 a_store(&raw mut (*b).__i[3], arrived);
4462 if arrived > limit {
4463 a_store(&raw mut (*b).__i[3], 0);
4464 let gen = a_load(&raw const (*b).__i[4]);
4465 a_store(&raw mut (*b).__i[4], gen + 1);
4466 spinlock_unlock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4467 futex_wake(&raw mut (*b).__i[4], -1);
4468 return PTHREAD_BARRIER_SERIAL_THREAD;
4469 }
4470 let gen = a_load(&raw const (*b).__i[4]);
4471 spinlock_unlock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4472 while a_load(&raw const (*b).__i[4]) == gen {
4473 futex_wait(&raw mut (*b).__i[4], gen);
4474 }
4475 0
4476}
4477
4478#[no_mangle]
4480pub unsafe extern "C" fn pthread_spin_init(s: *mut pthread_spinlock_t, _pshared: c_int) -> c_int { a_store(s, 0); 0 }
4481#[no_mangle]
4482pub unsafe extern "C" fn pthread_spin_destroy(_s: *mut pthread_spinlock_t) -> c_int { 0 }
4483#[no_mangle]
4484pub unsafe extern "C" fn pthread_spin_lock(s: *mut pthread_spinlock_t) -> c_int {
4485 while a_load(s) != 0 || a_cas(s, 0, EBUSY) != 0 { core::hint::spin_loop(); }
4486 0
4487}
4488#[no_mangle]
4489pub unsafe extern "C" fn pthread_spin_trylock(s: *mut pthread_spinlock_t) -> c_int { a_cas(s, 0, EBUSY) }
4490#[no_mangle]
4491pub unsafe extern "C" fn pthread_spin_unlock(s: *mut pthread_spinlock_t) -> c_int { a_store(s, 0); 0 }
4492
4493#[no_mangle]
4495pub unsafe extern "C" fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int {
4496 if value > SEM_VALUE_MAX as c_uint { return EINVAL; }
4497 (*sem).__val[0] = value as c_int;
4498 (*sem).__val[1] = 0;
4499 (*sem).__val[2] = if pshared != 0 { 0 } else { 128 };
4500 0
4501}
4502#[no_mangle]
4503pub unsafe extern "C" fn sem_destroy(_sem: *mut sem_t) -> c_int { 0 }
4504
4505unsafe fn sem_trywait_internal(sem: *mut sem_t) -> c_int {
4506 loop {
4507 let val = a_load(&raw const (*sem).__val[0]);
4508 if val & SEM_VALUE_MAX == 0 { return EAGAIN; }
4509 if a_cas(&raw mut (*sem).__val[0], val, val - 1) == val { return 0; }
4510 }
4511}
4512
4513#[no_mangle]
4514pub unsafe extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
4515 if sem_trywait_internal(sem) == 0 { 0 } else { ERRNO = EAGAIN; -1 }
4516}
4517#[no_mangle]
4518pub unsafe extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
4519 pthread_testcancel();
4520 if sem_trywait_internal(sem) == 0 { return 0; }
4521 let mut spins = 100;
4522 while spins > 0 { if sem_trywait_internal(sem) == 0 { return 0; } core::hint::spin_loop(); spins -= 1; }
4523 loop {
4524 pthread_testcancel();
4525 if sem_trywait_internal(sem) == 0 { return 0; }
4526 let val = a_load(&raw const (*sem).__val[0]);
4527 if val & SEM_VALUE_MAX != 0 { continue; }
4528 a_cas(&raw mut (*sem).__val[0], val, val | (1i32 << 31));
4529 a_fetch_add(&raw mut (*sem).__val[1], 1);
4530 futex_wait(&raw mut (*sem).__val[0], 1i32 << 31);
4531 a_fetch_sub(&raw mut (*sem).__val[1], 1);
4532 }
4533}
4534#[no_mangle]
4535pub unsafe extern "C" fn sem_timedwait(sem: *mut sem_t, abs_timeout: *const timespec) -> c_int {
4536 pthread_testcancel();
4537 if sem_trywait_internal(sem) == 0 { return 0; }
4538 let mut spins = 100;
4539 while spins > 0 { if sem_trywait_internal(sem) == 0 { return 0; } core::hint::spin_loop(); spins -= 1; }
4540 loop {
4541 pthread_testcancel();
4542 if sem_trywait_internal(sem) == 0 { return 0; }
4543 let val = a_load(&raw const (*sem).__val[0]);
4544 if val & SEM_VALUE_MAX != 0 { continue; }
4545 a_cas(&raw mut (*sem).__val[0], val, val | (1i32 << 31));
4546 a_fetch_add(&raw mut (*sem).__val[1], 1);
4547 let e = futex_timedwait(&raw mut (*sem).__val[0], 1i32 << 31, abs_timeout);
4548 a_fetch_sub(&raw mut (*sem).__val[1], 1);
4549 if e != 0 && e != EINTR { ERRNO = e; return -1; }
4550 }
4551}
4552#[no_mangle]
4553pub unsafe extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
4554 loop {
4555 let val = a_load(&raw const (*sem).__val[0]);
4556 if (val & SEM_VALUE_MAX) == SEM_VALUE_MAX { ERRNO = EOVERFLOW; return -1; }
4557 let mut new = val + 1;
4558 let waiters = a_load(&raw const (*sem).__val[1]);
4559 if waiters <= 1 { new &= !(1i32 << 31); }
4560 if a_cas(&raw mut (*sem).__val[0], val, new) == val {
4561 if val < 0 || waiters > 0 {
4562 futex_wake(&raw mut (*sem).__val[0], if waiters > 1 { 1 } else { -1 });
4563 }
4564 return 0;
4565 }
4566 }
4567}
4568#[no_mangle]
4569pub unsafe extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int {
4570 *sval = a_load(&raw const (*sem).__val[0]) & SEM_VALUE_MAX;
4571 0
4572}
4573
4574const NAME_MAX: usize = 255;
4579const SEM_NSEMS_MAX: usize = 256;
4580
4581static SEMTAB_LOCK: AtomicI32 = AtomicI32::new(0);
4583
4584struct SemEntry {
4585 ino: u64,
4586 sem: *mut sem_t,
4587 refcnt: u32,
4588}
4589
4590static mut SEMTAB: [SemEntry; SEM_NSEMS_MAX] = {
4592 const ZERO: SemEntry = SemEntry { ino: 0, sem: core::ptr::null_mut(), refcnt: 0 };
4593 [ZERO; SEM_NSEMS_MAX]
4594};
4595
4596unsafe fn semtab_lock() {
4597 while SEMTAB_LOCK.compare_exchange_weak(0, 1, Ordering::Acquire, Ordering::Relaxed).is_err() {
4598 core::hint::spin_loop();
4599 }
4600}
4601
4602unsafe fn semtab_unlock() {
4603 SEMTAB_LOCK.store(0, Ordering::Release);
4604}
4605
4606unsafe fn shm_mapname(name: *const c_char, buf: *mut u8) -> c_int {
4609 let mut p = name;
4610 while *p == b'/' as c_char { p = p.add(1); }
4612 let start = p;
4613 while *p != 0 && *p != b'/' as c_char { p = p.add(1); }
4615 let len = p.offset_from(start) as usize;
4616 if len == 0 || *p != 0 {
4618 ERRNO = EINVAL;
4619 return -1;
4620 }
4621 if len == 1 && *start == b'.' as c_char {
4622 ERRNO = EINVAL;
4623 return -1;
4624 }
4625 if len == 2 && *start == b'.' as c_char && *start.add(1) == b'.' as c_char {
4626 ERRNO = EINVAL;
4627 return -1;
4628 }
4629 if len > NAME_MAX {
4630 ERRNO = ENAMETOOLONG;
4631 return -1;
4632 }
4633 let prefix = b"/dev/shm/\0";
4635 let mut i = 0;
4636 while prefix[i] != 0 {
4637 *buf.add(i) = prefix[i];
4638 i += 1;
4639 }
4640 let mut j = 0;
4641 while j < len {
4642 *buf.add(i + j) = *start.add(j) as u8;
4643 j += 1;
4644 }
4645 *buf.add(i + j) = 0;
4646 (i + j) as c_int
4647}
4648
4649#[no_mangle]
4650pub unsafe extern "C" fn shm_open(name: *const c_char, flags: c_int, mode: mode_t) -> c_int {
4651 let mut buf = [0u8; 16 + NAME_MAX + 1];
4652 if shm_mapname(name, buf.as_mut_ptr()) < 0 { return -1; }
4653 let fd = sys_open(buf.as_ptr(), (flags | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, mode as i64);
4654 if fd < 0 { ERRNO = (-fd) as c_int; return -1; }
4655 fd as c_int
4656}
4657
4658#[no_mangle]
4659pub unsafe extern "C" fn shm_unlink(name: *const c_char) -> c_int {
4660 let mut buf = [0u8; 16 + NAME_MAX + 1];
4661 if shm_mapname(name, buf.as_mut_ptr()) < 0 { return -1; }
4662 let r = sys_unlink(buf.as_ptr());
4663 if r < 0 { ERRNO = (-r) as c_int; return -1; }
4664 0
4665}
4666
4667#[no_mangle]
4668pub unsafe extern "C" fn sem_open(name: *const c_char, flags: c_int, mut args: ...) -> *mut sem_t {
4669 let mut buf = [0u8; 16 + NAME_MAX + 1];
4670 if shm_mapname(name, buf.as_mut_ptr()).is_negative() {
4671 return core::ptr::null_mut(); }
4673
4674 let oflags = flags & (O_CREAT | O_EXCL);
4675
4676 semtab_lock();
4677
4678 let mut slot: c_int = -1;
4680 for i in 0..SEMTAB_LEN {
4681 if SEMTAB[i].sem.is_null() && slot < 0 { slot = i as c_int; }
4682 }
4683 if slot < 0 {
4684 ERRNO = EMFILE;
4685 semtab_unlock();
4686 return core::ptr::null_mut();
4687 }
4688 SEMTAB[slot as usize].sem = !0usize as *mut sem_t; semtab_unlock();
4691
4692 let mut mode: mode_t = 0;
4694 let mut value: c_uint = 0;
4695 if oflags & O_CREAT != 0 {
4696 mode = args.next_arg::<mode_t>() & 0o666;
4697 value = args.next_arg::<c_uint>();
4698 if value > SEM_VALUE_MAX as c_uint {
4699 ERRNO = EINVAL;
4700 semtab_lock();
4701 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4702 semtab_unlock();
4703 return core::ptr::null_mut();
4704 }
4705 }
4706
4707 if oflags != O_CREAT | O_EXCL {
4709 let fd = sys_open(buf.as_ptr(), (O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, 0);
4710 if fd >= 0 {
4711 let map = sys_mmap(
4712 core::ptr::null_mut(),
4713 core::mem::size_of::<sem_t>(),
4714 PROT_READ | PROT_WRITE,
4715 MAP_SHARED,
4716 fd as i32,
4717 0,
4718 );
4719 sys_close(fd);
4720 if map != MMAP_FAILED {
4721 let st_ino = get_ino(fd as c_int, buf.as_ptr());
4722 return sem_register(map as *mut sem_t, st_ino, slot);
4723 }
4724 }
4725 if oflags == 0 {
4726 semtab_lock();
4728 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4729 semtab_unlock();
4730 return core::ptr::null_mut();
4731 }
4732 }
4733
4734 let mut tmp = [0u8; 32];
4736 let tmpname = b"/dev/shm/tmp-XXXXXX\0";
4737 tmp[..tmpname.len()].copy_from_slice(tmpname);
4738 let mut ts: timespec = core::mem::zeroed();
4740 sys_clock_gettime(0, &mut ts);
4741 let mut n = ts.tv_nsec;
4743 let mut pos = tmpname.len() - 1;
4744 tmp[pos] = 0;
4745 pos -= 1;
4746 loop {
4747 tmp[pos] = b'0' + (n % 10) as u8;
4748 n /= 10;
4749 if n == 0 || pos == 0 { break; }
4750 pos -= 1;
4751 }
4752 let tmp_path = tmp.as_ptr();
4754
4755 let mut newsem: sem_t = core::mem::zeroed();
4756 newsem.__val[0] = value as c_int;
4757 newsem.__val[1] = 0;
4758 newsem.__val[2] = 128; loop {
4761 let fd = sys_open(tmp_path as *const u8, (O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC | O_NONBLOCK) as i64, mode as i64);
4762 if fd < 0 {
4763 if (-fd) as c_int == EEXIST { continue; }
4764 semtab_lock();
4765 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4766 semtab_unlock();
4767 return core::ptr::null_mut();
4768 }
4769 let written = sys_write(fd, &newsem as *const sem_t as *const u8, core::mem::size_of::<sem_t>());
4770 if written != core::mem::size_of::<sem_t>() as i64 {
4771 sys_close(fd);
4772 sys_unlink(tmp_path);
4773 semtab_lock();
4774 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4775 semtab_unlock();
4776 return core::ptr::null_mut();
4777 }
4778 let map = sys_mmap(
4779 core::ptr::null_mut(),
4780 core::mem::size_of::<sem_t>(),
4781 PROT_READ | PROT_WRITE,
4782 MAP_SHARED,
4783 fd as i32,
4784 0,
4785 );
4786 sys_close(fd);
4787 if map == MMAP_FAILED {
4788 sys_unlink(tmp_path);
4789 semtab_lock();
4790 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4791 semtab_unlock();
4792 return core::ptr::null_mut();
4793 }
4794 let r = sys_linkat(AT_FDCWD, tmp_path, AT_FDCWD, buf.as_ptr(), 0);
4796 let e = if r < 0 { (-r) as c_int } else { 0 };
4797 sys_unlink(tmp_path);
4798 if e == 0 {
4799 let st_ino = get_ino(-1, buf.as_ptr());
4800 return sem_register(map as *mut sem_t, st_ino, slot);
4801 }
4802 sys_munmap(map, core::mem::size_of::<sem_t>());
4803 if e != EEXIST || oflags == O_CREAT | O_EXCL {
4804 ERRNO = e;
4805 semtab_lock();
4806 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4807 semtab_unlock();
4808 return core::ptr::null_mut();
4809 }
4810 break;
4812 }
4813
4814 let fd = sys_open(buf.as_ptr(), (O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, 0);
4816 if fd < 0 {
4817 semtab_lock();
4818 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4819 semtab_unlock();
4820 return core::ptr::null_mut();
4821 }
4822 let map = sys_mmap(
4823 core::ptr::null_mut(),
4824 core::mem::size_of::<sem_t>(),
4825 PROT_READ | PROT_WRITE,
4826 MAP_SHARED,
4827 fd as i32,
4828 0,
4829 );
4830 sys_close(fd);
4831 if map == MMAP_FAILED {
4832 semtab_lock();
4833 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4834 semtab_unlock();
4835 return core::ptr::null_mut();
4836 }
4837 let st_ino = get_ino(-1, buf.as_ptr());
4838 sem_register(map as *mut sem_t, st_ino, slot)
4839}
4840
4841unsafe fn get_ino(_fd_hint: c_int, path: *const u8) -> u64 {
4842 let mut st: Stat = core::mem::zeroed();
4843 if sys_newfstatat(AT_FDCWD, path as *const c_char, &mut st as *mut Stat as *mut u8, 0) == 0 {
4844 st.st_ino
4845 } else {
4846 0
4847 }
4848}
4849
4850unsafe fn sem_register(map: *mut sem_t, ino: u64, slot_hint: c_int) -> *mut sem_t {
4851 semtab_lock();
4852 for i in 0..SEMTAB_LEN {
4854 if SEMTAB[i].ino == ino && !SEMTAB[i].sem.is_null() && SEMTAB[i].sem != !0usize as *mut sem_t {
4855 sys_munmap(map as *mut u8, core::mem::size_of::<sem_t>());
4857 SEMTAB[slot_hint as usize].sem = core::ptr::null_mut();
4858 SEMTAB[i].refcnt += 1;
4859 let ret = SEMTAB[i].sem;
4860 semtab_unlock();
4861 return ret;
4862 }
4863 }
4864 SEMTAB[slot_hint as usize].sem = map;
4866 SEMTAB[slot_hint as usize].ino = ino;
4867 SEMTAB[slot_hint as usize].refcnt = 1;
4868 semtab_unlock();
4869 map
4870}
4871
4872const SEMTAB_LEN: usize = SEM_NSEMS_MAX;
4873
4874#[no_mangle]
4875pub unsafe extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
4876 semtab_lock();
4877 for i in 0..SEMTAB_LEN {
4878 if SEMTAB[i].sem == sem {
4879 SEMTAB[i].refcnt -= 1;
4880 if SEMTAB[i].refcnt == 0 {
4881 SEMTAB[i].sem = core::ptr::null_mut();
4882 SEMTAB[i].ino = 0;
4883 semtab_unlock();
4884 sys_munmap(sem as *mut u8, core::mem::size_of::<sem_t>());
4885 return 0;
4886 }
4887 semtab_unlock();
4888 return 0;
4889 }
4890 }
4891 semtab_unlock();
4892 0
4893}
4894
4895#[no_mangle]
4896pub unsafe extern "C" fn sem_unlink(name: *const c_char) -> c_int {
4897 shm_unlink(name)
4898}
4899
4900#[no_mangle]
4902pub unsafe extern "C" fn pthread_once(control: *mut pthread_once_t, init_routine: Option<unsafe extern "C" fn()>) -> c_int {
4903 if a_load(control) == 2 { return 0; }
4904 loop {
4905 match a_cas(control, 0, 1) {
4906 0 => {
4907 if let Some(f) = init_routine { f(); }
4908 if a_swap(control, 2) == 3 { futex_wake(control, -1); }
4909 return 0;
4910 }
4911 1 => { a_cas(control, 1, 3); }
4912 3 => { futex_wait(control, 3); }
4913 _ => { return 0; }
4914 }
4915 }
4916}
4917
4918#[no_mangle]
4920pub unsafe extern "C" fn pthread_key_create(key: *mut pthread_key_t, dtor: Option<unsafe extern "C" fn(*mut c_void)>) -> c_int {
4921 let start = NEXT_KEY.load(Ordering::Relaxed);
4922 let mut j = start;
4923 loop {
4924 if KEY_DTORS[j].is_none() {
4925 KEY_DTORS[j] = dtor;
4926 NEXT_KEY.store((j + 1) % PTHREAD_KEYS_MAX, Ordering::Relaxed);
4927 *key = j as pthread_key_t;
4928 return 0;
4929 }
4930 j = (j + 1) % PTHREAD_KEYS_MAX;
4931 if j == start { return EAGAIN; }
4932 }
4933}
4934#[no_mangle]
4935pub unsafe extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int {
4936 KEY_DTORS[key as usize] = None;
4937 for i in 0..MAX_THREADS {
4938 if THREADS[i].tid > 0 { THREADS[i].tsd[key as usize] = core::ptr::null_mut(); }
4939 }
4940 0
4941}
4942#[no_mangle]
4943pub unsafe extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void {
4944 if let Some(slot) = find_thread() { slot.tsd[key as usize] } else { core::ptr::null_mut() }
4945}
4946#[no_mangle]
4947pub unsafe extern "C" fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int {
4948 if let Some(slot) = find_thread() {
4949 slot.tsd[key as usize] = value as *mut c_void;
4950 0
4951 } else { EINVAL }
4952}
4953
4954unsafe fn run_cleanup_handlers(slot: &mut Thread) {
4956 let mut cb = slot.cancelbuf;
4957 while !cb.is_null() {
4958 let cur = &*cb;
4959 let f = cur.__f;
4960 let x = cur.__x;
4961 cb = cur.__next;
4962 if let Some(func) = f {
4963 func(x);
4964 }
4965 }
4966 slot.cancelbuf = core::ptr::null_mut();
4967}
4968
4969unsafe fn do_cancel() -> ! {
4970 if let Some(slot) = find_thread() {
4971 run_cleanup_handlers(slot);
4972 slot.result = !0usize as *mut c_void; slot.detach_state = DT_EXITED;
4974 futex_wake(&raw mut slot.detach_state, 1);
4975 }
4976 sys_exit_thread(0);
4977}
4978
4979extern "C" fn cancel_handler(_sig: c_int) {
4980 unsafe {
4981 if let Some(slot) = find_thread() {
4982 if slot.cancel != 0
4986 && slot.cancel_state == PTHREAD_CANCEL_ENABLE
4987 && slot.cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS
4988 {
4989 do_cancel();
4990 }
4991 }
4992 }
4993}
4994
4995static CANCEL_INIT: AtomicI32 = AtomicI32::new(0);
4996
4997unsafe fn ensure_cancel_handler() {
4998 if CANCEL_INIT.swap(1, Ordering::AcqRel) == 0 {
4999 let act = sigaction {
5000 sa_handler: cancel_handler as *const () as usize,
5001 sa_flags: SA_RESTORER,
5002 sa_restorer: sig_restorer as *const () as usize,
5003 sa_mask: [!0u64],
5004 };
5005 sys_rt_sigaction(SIGCANCEL, &act as *const sigaction, core::ptr::null_mut(), 8);
5006 }
5007}
5008
5009#[no_mangle]
5010pub unsafe extern "C" fn pthread_cancel(thread: PthreadT) -> c_int {
5011 let slot = thread as *mut Thread;
5012 if slot.is_null() { return EINVAL; }
5013 ensure_cancel_handler();
5014 a_store(&raw mut (*slot).cancel, 1);
5015 let tid = (*slot).tid;
5016 if tid > 0 {
5017 sys_tgkill(sys_getpid() as c_int, tid, SIGCANCEL);
5018 }
5019 0
5020}
5021#[no_mangle]
5022pub unsafe extern "C" fn pthread_setcancelstate(state: c_int, oldstate: *mut c_int) -> c_int {
5023 if state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE { return EINVAL; }
5024 if let Some(slot) = find_thread() {
5025 if !oldstate.is_null() { *oldstate = slot.cancel_state; }
5026 slot.cancel_state = state;
5027 0
5028 } else { EINVAL }
5029}
5030#[no_mangle]
5031pub unsafe extern "C" fn pthread_setcanceltype(type_: c_int, oldtype: *mut c_int) -> c_int {
5032 if type_ != PTHREAD_CANCEL_DEFERRED && type_ != PTHREAD_CANCEL_ASYNCHRONOUS { return EINVAL; }
5033 if let Some(slot) = find_thread() {
5034 if !oldtype.is_null() { *oldtype = slot.cancel_type; }
5035 slot.cancel_type = type_;
5036 0
5037 } else { EINVAL }
5038}
5039#[no_mangle]
5040pub unsafe extern "C" fn pthread_testcancel() {
5041 if let Some(slot) = find_thread() {
5042 if slot.cancel != 0 && slot.cancel_state == PTHREAD_CANCEL_ENABLE {
5043 do_cancel();
5044 }
5045 }
5046}
5047
5048#[no_mangle]
5049pub unsafe extern "C" fn _pthread_cleanup_push(cb: *mut __ptcb, f: Option<unsafe extern "C" fn(*mut c_void)>, x: *mut c_void) {
5050 (*cb).__f = f;
5051 (*cb).__x = x;
5052 if let Some(slot) = find_thread() {
5053 (*cb).__next = slot.cancelbuf;
5054 slot.cancelbuf = cb;
5055 } else {
5056 (*cb).__next = core::ptr::null_mut();
5057 }
5058}
5059
5060#[no_mangle]
5061pub unsafe extern "C" fn _pthread_cleanup_pop(cb: *mut __ptcb, run: c_int) {
5062 if let Some(slot) = find_thread() {
5063 slot.cancelbuf = (*cb).__next;
5064 }
5065 if run != 0 {
5066 if let Some(f) = (*cb).__f {
5067 f((*cb).__x);
5068 }
5069 }
5070}
5071
5072#[no_mangle]
5073pub unsafe extern "C" fn pthread_kill(thread: PthreadT, sig: c_int) -> c_int {
5074 let slot = thread as *mut Thread;
5075 if slot.is_null() { return EINVAL; }
5076 let tid = (*slot).tid;
5077 if tid <= 0 { return EINVAL; }
5078 if sys_tgkill(sys_getpid() as c_int, tid, sig) < 0 { -1 } else { 0 }
5079}
5080
5081#[no_mangle]
5082pub unsafe extern "C" fn pthread_sigmask(how: c_int, set: *const SigSetT, oldset: *mut SigSetT) -> c_int {
5083 sigprocmask(how, set, oldset)
5084}
5085
5086
5087#[repr(C)]
5088pub struct lconv {
5089 pub decimal_point: *mut c_char,
5090 pub thousands_sep: *mut c_char,
5091 pub grouping: *mut c_char,
5092 pub int_curr_symbol: *mut c_char,
5093 pub currency_symbol: *mut c_char,
5094 pub mon_decimal_point: *mut c_char,
5095 pub mon_thousands_sep: *mut c_char,
5096 pub mon_grouping: *mut c_char,
5097 pub positive_sign: *mut c_char,
5098 pub negative_sign: *mut c_char,
5099 pub int_frac_digits: c_char,
5100 pub frac_digits: c_char,
5101 pub p_cs_precedes: c_char,
5102 pub p_sep_by_space: c_char,
5103 pub n_cs_precedes: c_char,
5104 pub n_sep_by_space: c_char,
5105 pub p_sign_posn: c_char,
5106 pub n_sign_posn: c_char,
5107 pub int_p_cs_precedes: c_char,
5108 pub int_p_sep_by_space: c_char,
5109 pub int_n_cs_precedes: c_char,
5110 pub int_n_sep_by_space: c_char,
5111 pub int_p_sign_posn: c_char,
5112 pub int_n_sign_posn: c_char,
5113}
5114
5115static UTF8_NAME: [u8; 6] = [b'U', b'T', b'F', b'-', b'8', 0];
5116static C_NAME: [u8; 2] = [b'C', 0];
5117static mut LOCALE_NAME: *const c_char = C_NAME.as_ptr() as *const c_char;
5118static mut LOCALE_CTYPE_UTF8: bool = true;
5119static mut EMPTY_STR: [c_char; 1] = [0];
5120static mut DECIMAL_POINT: [c_char; 2] = [b'.' as c_char, 0];
5121static mut LCONV: lconv = lconv {
5122 decimal_point: core::ptr::null_mut(),
5123 thousands_sep: core::ptr::null_mut(),
5124 grouping: core::ptr::null_mut(),
5125 int_curr_symbol: core::ptr::null_mut(),
5126 currency_symbol: core::ptr::null_mut(),
5127 mon_decimal_point: core::ptr::null_mut(),
5128 mon_thousands_sep: core::ptr::null_mut(),
5129 mon_grouping: core::ptr::null_mut(),
5130 positive_sign: core::ptr::null_mut(),
5131 negative_sign: core::ptr::null_mut(),
5132 int_frac_digits: (-1i32) as c_char,
5133 frac_digits: (-1i32) as c_char,
5134 p_cs_precedes: (-1i32) as c_char,
5135 p_sep_by_space: (-1i32) as c_char,
5136 n_cs_precedes: (-1i32) as c_char,
5137 n_sep_by_space: (-1i32) as c_char,
5138 p_sign_posn: (-1i32) as c_char,
5139 n_sign_posn: (-1i32) as c_char,
5140 int_p_cs_precedes: (-1i32) as c_char,
5141 int_p_sep_by_space: (-1i32) as c_char,
5142 int_n_cs_precedes: (-1i32) as c_char,
5143 int_n_sep_by_space: (-1i32) as c_char,
5144 int_p_sign_posn: (-1i32) as c_char,
5145 int_n_sign_posn: (-1i32) as c_char,
5146};
5147
5148unsafe fn cstr_contains_ci(s: *const u8, needle: &[u8]) -> bool {
5149 let len = strlen(s as *const c_char) as usize;
5150 let s_slice = core::slice::from_raw_parts(s, len);
5151 if needle.len() > len { return false; }
5152 for i in 0..=len - needle.len() {
5153 if s_slice[i..i + needle.len()].eq_ignore_ascii_case(needle) {
5154 return true;
5155 }
5156 }
5157 false
5158}
5159
5160#[no_mangle]
5161pub unsafe extern "C" fn setlocale(_category: c_int, locale: *const c_char) -> *mut c_char {
5162 if locale.is_null() || *locale == 0 {
5163 return LOCALE_NAME as *mut c_char;
5164 }
5165 let name = locale as *const u8;
5166 if strcmp(name, b"C\0".as_ptr()) == 0 || strcmp(name, b"POSIX\0".as_ptr()) == 0 {
5167 LOCALE_CTYPE_UTF8 = false;
5168 return LOCALE_NAME as *mut c_char;
5169 }
5170 if cstr_contains_ci(name, b"UTF-8") || cstr_contains_ci(name, b"UTF8") {
5171 LOCALE_CTYPE_UTF8 = true;
5172 return LOCALE_NAME as *mut c_char;
5173 }
5174 core::ptr::null_mut()
5175}
5176
5177#[no_mangle]
5178pub unsafe extern "C" fn localeconv() -> *mut lconv {
5179 let empty = core::ptr::addr_of_mut!(EMPTY_STR) as *mut c_char;
5180 let lconv = core::ptr::addr_of_mut!(LCONV);
5181 (*lconv).decimal_point = core::ptr::addr_of_mut!(DECIMAL_POINT) as *mut c_char;
5182 (*lconv).thousands_sep = empty;
5183 (*lconv).grouping = empty;
5184 (*lconv).int_curr_symbol = empty;
5185 (*lconv).currency_symbol = empty;
5186 (*lconv).mon_decimal_point = empty;
5187 (*lconv).mon_thousands_sep = empty;
5188 (*lconv).mon_grouping = empty;
5189 (*lconv).positive_sign = empty;
5190 (*lconv).negative_sign = empty;
5191 lconv
5192}
5193
5194pub type locale_t = *mut c_void;
5195static mut CURRENT_LOCALE: locale_t = LC_GLOBAL_LOCALE;
5196
5197static mut C_LOCALE_STORAGE: c_int = 0;
5198const C_LOCALE: locale_t = core::ptr::addr_of_mut!(C_LOCALE_STORAGE) as locale_t;
5199const LC_GLOBAL_LOCALE: locale_t = usize::MAX as locale_t;
5200
5201#[no_mangle]
5202pub unsafe extern "C" fn newlocale(_mask: c_int, name: *const c_char, base: locale_t) -> locale_t {
5203 if !name.is_null() && *name != 0 {
5204 let n = name as *const u8;
5205 if strcmp(n, b"C\0".as_ptr()) != 0
5206 && strcmp(n, b"POSIX\0".as_ptr()) != 0
5207 {
5208 return core::ptr::null_mut();
5209 }
5210 }
5211 if base.is_null() || base == C_LOCALE || base == LC_GLOBAL_LOCALE {
5212 C_LOCALE
5213 } else {
5214 core::ptr::null_mut()
5215 }
5216}
5217
5218#[no_mangle]
5219pub unsafe extern "C" fn freelocale(_loc: locale_t) {}
5220
5221#[no_mangle]
5222pub unsafe extern "C" fn uselocale(loc: locale_t) -> locale_t {
5223 let old = CURRENT_LOCALE;
5224 if !loc.is_null() {
5225 CURRENT_LOCALE = loc;
5226 }
5227 old
5228}
5229
5230#[no_mangle]
5231pub unsafe extern "C" fn duplocale(loc: locale_t) -> locale_t {
5232 if loc.is_null() {
5233 return core::ptr::null_mut();
5234 }
5235 C_LOCALE
5236}
5237
5238const NL_ITEM_CODESET: c_int = 14;
5239const NL_ITEM_RADIXCHAR: c_int = 0x10000;
5240const NL_ITEM_THOUSEP: c_int = 0x10001;
5241const NL_ITEM_YESEXPR: c_int = 0x50000;
5242const NL_ITEM_NOEXPR: c_int = 0x50001;
5243
5244const C_TIME_STRINGS: &[u8] = b"Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat\0\
5245Sunday\0Monday\0Tuesday\0Wednesday\0Thursday\0Friday\0Saturday\0\
5246Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec\0\
5247January\0February\0March\0April\0May\0June\0July\0August\0\
5248September\0October\0November\0December\0\
5249AM\0PM\0\
5250%a %b %e %T %Y\0%m/%d/%y\0%H:%M:%S\0%I:%M:%S %p\0\
5251\0\0%m/%d/%y\00123456789\0%a %b %e %T %Y\0%H:%M:%S\0";
5252
5253const C_NUMERIC_STRINGS: &[u8] = b".\0\0";
5254const C_MESSAGES_STRINGS: &[u8] = b"^[yY]\0^[nN]\0";
5255
5256unsafe fn langinfo_str(table: *const u8, mut idx: c_int) -> *mut c_char {
5257 let mut p = table;
5258 while idx > 0 {
5259 while *p != 0 { p = p.add(1); }
5260 p = p.add(1);
5261 idx -= 1;
5262 }
5263 p as *mut c_char
5264}
5265
5266#[no_mangle]
5267pub unsafe extern "C" fn nl_langinfo(item: c_int) -> *mut c_char {
5268 if item == NL_ITEM_CODESET {
5269 return if LOCALE_CTYPE_UTF8 {
5270 b"UTF-8\0".as_ptr() as *mut c_char
5271 } else {
5272 b"US-ASCII\0".as_ptr() as *mut c_char
5273 };
5274 }
5275 let cat = item >> 16;
5276 let idx = item & 0xFFFF;
5277 match cat {
5278 1 => {
5279 if idx > 1 { return b"\0".as_ptr() as *mut c_char; }
5280 langinfo_str(C_NUMERIC_STRINGS.as_ptr(), idx)
5281 }
5282 2 => {
5283 if idx > 49 { return b"\0".as_ptr() as *mut c_char; }
5284 langinfo_str(C_TIME_STRINGS.as_ptr(), idx)
5285 }
5286 5 => {
5287 if idx > 1 { return b"\0".as_ptr() as *mut c_char; }
5288 langinfo_str(C_MESSAGES_STRINGS.as_ptr(), idx)
5289 }
5290 _ => b"\0".as_ptr() as *mut c_char,
5291 }
5292}
5293
5294pub type nl_catd = *mut c_void;
5295
5296#[no_mangle]
5297pub unsafe extern "C" fn catopen(_name: *const c_char, _oflag: c_int) -> nl_catd {
5298 !0usize as nl_catd
5299}
5300
5301#[no_mangle]
5302pub unsafe extern "C" fn catclose(_catd: nl_catd) -> c_int { 0 }
5303
5304#[no_mangle]
5305pub unsafe extern "C" fn catgets(catd: nl_catd, _set_id: c_int, _msg_id: c_int, s: *const c_char) -> *mut c_char {
5306 if catd == !0usize as nl_catd { return s as *mut c_char; }
5307 s as *mut c_char
5308}
5309
5310pub type IconvT = *mut c_void;
5311
5312const ENC_UTF8: i32 = 1;
5313const ENC_UTF16LE: i32 = 2;
5314const ENC_UTF16BE: i32 = 3;
5315const ENC_UTF32LE: i32 = 4;
5316const ENC_UTF32BE: i32 = 5;
5317const ENC_WCHAR_T: i32 = 6;
5318const ENC_ASCII: i32 = 7;
5319const ENC_LATIN1: i32 = 8;
5320const ENC_WIN1252: i32 = 9;
5321const ENC_WIN1251: i32 = 10;
5322const ENC_KOI8R: i32 = 11;
5323const ENC_GBK: i32 = 12;
5324const ENC_GB2312: i32 = 13;
5325const ENC_BIG5: i32 = 14;
5326const ENC_EUCJP: i32 = 15;
5327const ENC_SHIFTJIS: i32 = 16;
5328const ENC_ISO8859_2: i32 = 17;
5329const ENC_ISO8859_3: i32 = 18;
5330const ENC_ISO8859_4: i32 = 19;
5331const ENC_ISO8859_5: i32 = 20;
5332const ENC_ISO8859_6: i32 = 21;
5333const ENC_ISO8859_7: i32 = 22;
5334const ENC_ISO8859_8: i32 = 23;
5335const ENC_ISO8859_9: i32 = 24;
5336const ENC_ISO8859_10: i32 = 25;
5337const ENC_ISO8859_11: i32 = 26;
5338const ENC_ISO8859_13: i32 = 27;
5339const ENC_ISO8859_14: i32 = 28;
5340const ENC_ISO8859_15: i32 = 29;
5341const ENC_ISO8859_16: i32 = 30;
5342
5343include!("iconv_iso8859.rs");
5344
5345fn make_cd(from: i32, to: i32) -> IconvT {
5346 ((from as usize) << 16 | (to as usize) << 1 | 1) as IconvT
5347}
5348fn extract_from(cd: IconvT) -> i32 {
5349 ((cd as usize) >> 16) as i32
5350}
5351fn extract_to(cd: IconvT) -> i32 {
5352 (((cd as usize) >> 1) & 0x7fff) as i32
5353}
5354
5355unsafe fn match_name(input: *const u8, target: &[u8]) -> bool {
5356 let mut i = input;
5357 let mut j = 0;
5358 while *i != 0 && j < target.len() {
5359 let mut c = *i;
5360 if !c.is_ascii_alphanumeric() { i = i.add(1); continue; }
5361 c = c.to_ascii_lowercase();
5362 if c != target[j] { return false; }
5363 i = i.add(1);
5364 j += 1;
5365 }
5366 while *i != 0 && !(*i).is_ascii_alphanumeric() { i = i.add(1); }
5367 *i == 0 && j == target.len()
5368}
5369
5370unsafe fn find_encoding(name: *const u8) -> i32 {
5371 if name.is_null() { return -1; }
5372 if match_name(name, b"utf8") || match_name(name, b"utf-8") || match_name(name, b"char") { return ENC_UTF8; }
5373 if match_name(name, b"utf16le") || match_name(name, b"utf-16le") { return ENC_UTF16LE; }
5374 if match_name(name, b"utf16be") || match_name(name, b"utf-16be") { return ENC_UTF16BE; }
5375 if match_name(name, b"utf32le") || match_name(name, b"utf-32le") || match_name(name, b"ucs4le") { return ENC_UTF32LE; }
5376 if match_name(name, b"utf32be") || match_name(name, b"utf-32be") || match_name(name, b"ucs4be") { return ENC_UTF32BE; }
5377 if match_name(name, b"wchart") || match_name(name, b"wchar-t") { return ENC_WCHAR_T; }
5378 if match_name(name, b"ascii") || match_name(name, b"usascii") || match_name(name, b"iso646") { return ENC_ASCII; }
5379 if match_name(name, b"iso88591") || match_name(name, b"iso-8859-1") || match_name(name, b"latin1") { return ENC_LATIN1; }
5380 if match_name(name, b"iso88592") || match_name(name, b"iso-8859-2") { return ENC_ISO8859_2; }
5381 if match_name(name, b"iso88593") || match_name(name, b"iso-8859-3") { return ENC_ISO8859_3; }
5382 if match_name(name, b"iso88594") || match_name(name, b"iso-8859-4") { return ENC_ISO8859_4; }
5383 if match_name(name, b"iso88595") || match_name(name, b"iso-8859-5") { return ENC_ISO8859_5; }
5384 if match_name(name, b"iso88596") || match_name(name, b"iso-8859-6") { return ENC_ISO8859_6; }
5385 if match_name(name, b"iso88597") || match_name(name, b"iso-8859-7") { return ENC_ISO8859_7; }
5386 if match_name(name, b"iso88598") || match_name(name, b"iso-8859-8") { return ENC_ISO8859_8; }
5387 if match_name(name, b"iso88599") || match_name(name, b"iso-8859-9") { return ENC_ISO8859_9; }
5388 if match_name(name, b"iso885910") || match_name(name, b"iso-8859-10") { return ENC_ISO8859_10; }
5389 if match_name(name, b"iso885911") || match_name(name, b"iso-8859-11") || match_name(name, b"tis620") { return ENC_ISO8859_11; }
5390 if match_name(name, b"iso885913") || match_name(name, b"iso-8859-13") { return ENC_ISO8859_13; }
5391 if match_name(name, b"iso885914") || match_name(name, b"iso-8859-14") { return ENC_ISO8859_14; }
5392 if match_name(name, b"iso885915") || match_name(name, b"iso-8859-15") { return ENC_ISO8859_15; }
5393 if match_name(name, b"iso885916") || match_name(name, b"iso-8859-16") { return ENC_ISO8859_16; }
5394 if match_name(name, b"cp1252") || match_name(name, b"windows1252") || match_name(name, b"windows-1252") { return ENC_WIN1252; }
5395 if match_name(name, b"cp1251") || match_name(name, b"windows1251") || match_name(name, b"windows-1251") { return ENC_WIN1251; }
5396 if match_name(name, b"koi8r") || match_name(name, b"koi8-r") { return ENC_KOI8R; }
5397 if match_name(name, b"gbk") || match_name(name, b"cp936") { return ENC_GBK; }
5398 if match_name(name, b"gb2312") { return ENC_GB2312; }
5399 if match_name(name, b"big5") || match_name(name, b"bigfive") || match_name(name, b"cp950") { return ENC_BIG5; }
5400 if match_name(name, b"eucjp") || match_name(name, b"euc-jp") { return ENC_EUCJP; }
5401 if match_name(name, b"shiftjis") || match_name(name, b"sjis") || match_name(name, b"cp932") { return ENC_SHIFTJIS; }
5402 -1
5403}
5404
5405fn uni_to_jis(c: u32) -> u16 {
5406 let mut b = 0usize;
5407 let mut nel = REV_JIS.len();
5408 loop {
5409 let i = nel / 2;
5410 let j = REV_JIS[b + i] as usize;
5411 let row = j / 256;
5412 let col = j % 256;
5413 let d = JIS0208[row * 94 + col] as u32;
5414 if d == c { return (j as u16) + 0x2121; }
5415 if nel == 1 { return 0; }
5416 if c < d { nel /= 2; }
5417 else { b += i; nel -= nel / 2; }
5418 }
5419}
5420
5421unsafe fn iconv_decode(enc: i32, src: *const u8, src_left: usize) -> (u32, usize, c_int) {
5422 if src_left == 0 { return (0, 0, EINVAL); }
5423 match enc {
5424 ENC_UTF8 => {
5425 let c = *src;
5426 if c < 128 { return (c as u32, 1, 0); }
5427 if c < 0xC2 { return (0, 0, EILSEQ); }
5428 if c < 0xE0 {
5429 if src_left < 2 || (*src.add(1) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5430 return (((c as u32 & 0x1F) << 6) | (*src.add(1) as u32 & 0x3F), 2, 0);
5431 }
5432 if c < 0xF0 {
5433 if src_left < 3 || (*src.add(1) & 0xC0) != 0x80 || (*src.add(2) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5434 let cp = ((c as u32 & 0x0F) << 12) | ((*src.add(1) as u32 & 0x3F) << 6) | (*src.add(2) as u32 & 0x3F);
5435 if cp < 0x800 { return (0, 0, EILSEQ); }
5436 return (cp, 3, 0);
5437 }
5438 if c < 0xF8 {
5439 if src_left < 4 || (*src.add(1) & 0xC0) != 0x80 || (*src.add(2) & 0xC0) != 0x80 || (*src.add(3) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5440 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);
5441 if cp < 0x10000 || cp >= 0x110000 { return (0, 0, EILSEQ); }
5442 return (cp, 4, 0);
5443 }
5444 (0, 0, EILSEQ)
5445 }
5446 ENC_UTF16LE => {
5447 if src_left < 2 { return (0, 0, EINVAL); }
5448 let c = (*src as u32) | ((*src.add(1) as u32) << 8);
5449 if c >= 0xD800 && c <= 0xDBFF {
5450 if src_left < 4 { return (0, 0, EINVAL); }
5451 let d = (*src.add(2) as u32) | ((*src.add(3) as u32) << 8);
5452 if d < 0xDC00 || d > 0xDFFF { return (0, 0, EILSEQ); }
5453 return (((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000, 4, 0);
5454 }
5455 if c >= 0xDC00 && c <= 0xDFFF { return (0, 0, EILSEQ); }
5456 (c, 2, 0)
5457 }
5458 ENC_UTF16BE => {
5459 if src_left < 2 { return (0, 0, EINVAL); }
5460 let c = ((*src as u32) << 8) | (*src.add(1) as u32);
5461 if c >= 0xD800 && c <= 0xDBFF {
5462 if src_left < 4 { return (0, 0, EINVAL); }
5463 let d = ((*src.add(2) as u32) << 8) | (*src.add(3) as u32);
5464 if d < 0xDC00 || d > 0xDFFF { return (0, 0, EILSEQ); }
5465 return (((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000, 4, 0);
5466 }
5467 if c >= 0xDC00 && c <= 0xDFFF { return (0, 0, EILSEQ); }
5468 (c, 2, 0)
5469 }
5470 ENC_UTF32LE => {
5471 if src_left < 4 { return (0, 0, EINVAL); }
5472 let c = (*src as u32) | ((*src.add(1) as u32) << 8) | ((*src.add(2) as u32) << 16) | ((*src.add(3) as u32) << 24);
5473 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5474 if c >= 0x110000 { return (0, 0, EILSEQ); }
5475 (c, 4, 0)
5476 }
5477 ENC_UTF32BE => {
5478 if src_left < 4 { return (0, 0, EINVAL); }
5479 let c = ((*src as u32) << 24) | ((*src.add(1) as u32) << 16) | ((*src.add(2) as u32) << 8) | (*src.add(3) as u32);
5480 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5481 if c >= 0x110000 { return (0, 0, EILSEQ); }
5482 (c, 4, 0)
5483 }
5484 ENC_WCHAR_T => {
5485 if src_left < 4 { return (0, 0, EINVAL); }
5486 let c = *(src as *const u32);
5487 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5488 if c >= 0x110000 { return (0, 0, EILSEQ); }
5489 (c, 4, 0)
5490 }
5491 ENC_ASCII => {
5492 let c = *src as u32;
5493 if c >= 128 { return (0, 0, EILSEQ); }
5494 (c, 1, 0)
5495 }
5496 ENC_LATIN1 => (*src as u32, 1, 0),
5497 ENC_ISO8859_2 => (iso8859_to_u(&ISO8859_2_TO_U, *src), 1, 0),
5498 ENC_ISO8859_3 => (iso8859_to_u(&ISO8859_3_TO_U, *src), 1, 0),
5499 ENC_ISO8859_4 => (iso8859_to_u(&ISO8859_4_TO_U, *src), 1, 0),
5500 ENC_ISO8859_5 => (iso8859_to_u(&ISO8859_5_TO_U, *src), 1, 0),
5501 ENC_ISO8859_6 => (iso8859_to_u(&ISO8859_6_TO_U, *src), 1, 0),
5502 ENC_ISO8859_7 => (iso8859_to_u(&ISO8859_7_TO_U, *src), 1, 0),
5503 ENC_ISO8859_8 => (iso8859_to_u(&ISO8859_8_TO_U, *src), 1, 0),
5504 ENC_ISO8859_9 => (iso8859_to_u(&ISO8859_9_TO_U, *src), 1, 0),
5505 ENC_ISO8859_10 => (iso8859_to_u(&ISO8859_10_TO_U, *src), 1, 0),
5506 ENC_ISO8859_11 => (iso8859_to_u(&ISO8859_11_TO_U, *src), 1, 0),
5507 ENC_ISO8859_13 => (iso8859_to_u(&ISO8859_13_TO_U, *src), 1, 0),
5508 ENC_ISO8859_14 => (iso8859_to_u(&ISO8859_14_TO_U, *src), 1, 0),
5509 ENC_ISO8859_15 => (iso8859_to_u(&ISO8859_15_TO_U, *src), 1, 0),
5510 ENC_ISO8859_16 => (iso8859_to_u(&ISO8859_16_TO_U, *src), 1, 0),
5511 ENC_WIN1252 => {
5512 let b = *src;
5513 if b < 128 { return (b as u32, 1, 0); }
5514 (WIN1252_TO_U[b as usize - 128], 1, 0)
5515 }
5516 ENC_WIN1251 => {
5517 let b = *src;
5518 if b < 128 { return (b as u32, 1, 0); }
5519 (WIN1251_TO_U[b as usize - 128], 1, 0)
5520 }
5521 ENC_KOI8R => {
5522 let b = *src;
5523 if b < 128 { return (b as u32, 1, 0); }
5524 (KOI8R_TO_U[b as usize - 128], 1, 0)
5525 }
5526 ENC_GBK | ENC_GB2312 => {
5527 let c = *src;
5528 if c < 128 { return (c as u32, 1, 0); }
5529 if c == 128 { return (0x20AC, 1, 0); }
5530 if src_left < 2 { return (0, 0, EINVAL); }
5531 let d = *src.add(1);
5532 if d < 0x40 || d == 0x7F || d > 0xFE { return (0, 0, EILSEQ); }
5533 let row = (c as usize).wrapping_sub(0x81);
5534 if row >= 126 { return (0, 0, EILSEQ); }
5535 let mut col = (d as usize) - 0x40;
5536 if col > 63 { col -= 1; }
5537 let cp = GB18030_TABLE[row * 190 + col] as u32;
5538 if cp == 0 { return (0, 0, EILSEQ); }
5539 (cp, 2, 0)
5540 }
5541 ENC_BIG5 => {
5542 let c = *src;
5543 if c < 128 { return (c as u32, 1, 0); }
5544 if src_left < 2 { return (0, 0, EINVAL); }
5545 let d = *src.add(1);
5546 if d < 0x40 || d == 0x7F || d > 0xFE { return (0, 0, EILSEQ); }
5547 let mut col = (d as usize) - 0x40;
5548 if col > 0x3E { col -= 0x22; }
5549 if c >= 0xA1 && c < 0xFA {
5550 let row = (c as usize) - 0xA1;
5551 if row >= 89 { return (0, 0, EILSEQ); }
5552 let cp = BIG5_TABLE[row * 157 + col] as u32;
5553 if cp == 0 { return (0, 0, EILSEQ); }
5554 return (cp, 2, 0);
5555 }
5556 (0, 0, EILSEQ)
5557 }
5558 ENC_EUCJP => {
5559 let c = *src;
5560 if c < 128 { return (c as u32, 1, 0); }
5561 if c == 0x8E {
5562 if src_left < 2 { return (0, 0, EINVAL); }
5563 let d = *src.add(1);
5564 if d < 0xA1 || d > 0xDF { return (0, 0, EILSEQ); }
5565 return ((d as u32) + 0xFF61 - 0xA1, 2, 0);
5566 }
5567 if c < 0xA1 { return (0, 0, EILSEQ); }
5568 if src_left < 2 { return (0, 0, EINVAL); }
5569 let d = *src.add(1);
5570 if d < 0xA1 || d > 0xFE { return (0, 0, EILSEQ); }
5571 let row = (c as usize) - 0xA1;
5572 let col = (d as usize) - 0xA1;
5573 if row >= 84 || col >= 94 { return (0, 0, EILSEQ); }
5574 let cp = JIS0208[row * 94 + col] as u32;
5575 if cp == 0 { return (0, 0, EILSEQ); }
5576 (cp, 2, 0)
5577 }
5578 ENC_SHIFTJIS => {
5579 let c = *src;
5580 if c < 128 { return (c as u32, 1, 0); }
5581 if c >= 0xA1 && c <= 0xDF { return ((c as u32) + 0xFF61 - 0xA1, 1, 0); }
5582 if src_left < 2 { return (0, 0, EINVAL); }
5583 let d = *src.add(1);
5584 if d < 0x40 || d == 0x7F || d > 0xFC { return (0, 0, EILSEQ); }
5585 let row = if c >= 129 && c <= 159 { (c as usize) - 129 }
5586 else if c >= 224 && c <= 239 { (c as usize) - 193 }
5587 else { return (0, 0, EILSEQ); };
5588 let (col, row_adj) = if d >= 64 && d <= 158 && d != 127 {
5589 let mut dd = d as usize;
5590 if dd > 127 { dd -= 1; }
5591 (dd - 64, row * 2)
5592 } else if d >= 159 && d <= 252 {
5593 ((d as usize) - 159, row * 2 + 1)
5594 } else {
5595 return (0, 0, EILSEQ);
5596 };
5597 if row_adj >= 84 { return (0, 0, EILSEQ); }
5598 let cp = JIS0208[row_adj * 94 + col] as u32;
5599 if cp == 0 { return (0, 0, EILSEQ); }
5600 (cp, 2, 0)
5601 }
5602 _ => (0, 0, EILSEQ),
5603 }
5604}
5605
5606unsafe fn iconv_encode(enc: i32, c: u32, dst: *mut u8, dst_left: usize) -> (usize, c_int) {
5607 match enc {
5608 ENC_UTF8 => {
5609 if c < 0x80 {
5610 if dst_left < 1 { return (0, E2BIG); }
5611 *dst = c as u8; return (1, 0);
5612 }
5613 if c < 0x800 {
5614 if dst_left < 2 { return (0, E2BIG); }
5615 *dst = (0xC0 | (c >> 6)) as u8;
5616 *dst.add(1) = (0x80 | (c & 0x3F)) as u8;
5617 return (2, 0);
5618 }
5619 if c < 0x10000 {
5620 if dst_left < 3 { return (0, E2BIG); }
5621 *dst = (0xE0 | (c >> 12)) as u8;
5622 *dst.add(1) = (0x80 | ((c >> 6) & 0x3F)) as u8;
5623 *dst.add(2) = (0x80 | (c & 0x3F)) as u8;
5624 return (3, 0);
5625 }
5626 if dst_left < 4 { return (0, E2BIG); }
5627 *dst = (0xF0 | (c >> 18)) as u8;
5628 *dst.add(1) = (0x80 | ((c >> 12) & 0x3F)) as u8;
5629 *dst.add(2) = (0x80 | ((c >> 6) & 0x3F)) as u8;
5630 *dst.add(3) = (0x80 | (c & 0x3F)) as u8;
5631 (4, 0)
5632 }
5633 ENC_UTF16LE => {
5634 if c < 0x10000 {
5635 if dst_left < 2 { return (0, E2BIG); }
5636 *dst = (c & 0xFF) as u8;
5637 *dst.add(1) = (c >> 8) as u8;
5638 return (2, 0);
5639 }
5640 if dst_left < 4 { return (0, E2BIG); }
5641 let c = c - 0x10000;
5642 let hi = ((c >> 10) + 0xD800) as u16;
5643 let lo = ((c & 0x3FF) + 0xDC00) as u16;
5644 *dst = (hi & 0xFF) as u8; *dst.add(1) = (hi >> 8) as u8;
5645 *dst.add(2) = (lo & 0xFF) as u8; *dst.add(3) = (lo >> 8) as u8;
5646 (4, 0)
5647 }
5648 ENC_UTF16BE => {
5649 if c < 0x10000 {
5650 if dst_left < 2 { return (0, E2BIG); }
5651 *dst = (c >> 8) as u8;
5652 *dst.add(1) = (c & 0xFF) as u8;
5653 return (2, 0);
5654 }
5655 if dst_left < 4 { return (0, E2BIG); }
5656 let c = c - 0x10000;
5657 let hi = ((c >> 10) + 0xD800) as u16;
5658 let lo = ((c & 0x3FF) + 0xDC00) as u16;
5659 *dst = (hi >> 8) as u8; *dst.add(1) = (hi & 0xFF) as u8;
5660 *dst.add(2) = (lo >> 8) as u8; *dst.add(3) = (lo & 0xFF) as u8;
5661 (4, 0)
5662 }
5663 ENC_UTF32LE => {
5664 if dst_left < 4 { return (0, E2BIG); }
5665 *dst = (c & 0xFF) as u8; *dst.add(1) = ((c >> 8) & 0xFF) as u8;
5666 *dst.add(2) = ((c >> 16) & 0xFF) as u8; *dst.add(3) = (c >> 24) as u8;
5667 (4, 0)
5668 }
5669 ENC_UTF32BE => {
5670 if dst_left < 4 { return (0, E2BIG); }
5671 *dst = (c >> 24) as u8; *dst.add(1) = ((c >> 16) & 0xFF) as u8;
5672 *dst.add(2) = ((c >> 8) & 0xFF) as u8; *dst.add(3) = (c & 0xFF) as u8;
5673 (4, 0)
5674 }
5675 ENC_WCHAR_T => {
5676 if dst_left < 4 { return (0, E2BIG); }
5677 *(dst as *mut u32) = c;
5678 (4, 0)
5679 }
5680 ENC_ASCII => {
5681 if c < 128 {
5682 if dst_left < 1 { return (0, E2BIG); }
5683 *dst = c as u8; return (1, 0);
5684 }
5685 (0, EILSEQ)
5686 }
5687 ENC_LATIN1 => {
5688 if c < 256 {
5689 if dst_left < 1 { return (0, E2BIG); }
5690 *dst = c as u8; return (1, 0);
5691 }
5692 (0, EILSEQ)
5693 }
5694 ENC_ISO8859_2 => {
5695 if let Some(b) = u_to_iso8859(&ISO8859_2_TO_U, c) {
5696 if dst_left < 1 { return (0, E2BIG); }
5697 *dst = b; return (1, 0);
5698 }
5699 (0, EILSEQ)
5700 }
5701 ENC_ISO8859_3 => {
5702 if let Some(b) = u_to_iso8859(&ISO8859_3_TO_U, c) {
5703 if dst_left < 1 { return (0, E2BIG); }
5704 *dst = b; return (1, 0);
5705 }
5706 (0, EILSEQ)
5707 }
5708 ENC_ISO8859_4 => {
5709 if let Some(b) = u_to_iso8859(&ISO8859_4_TO_U, c) {
5710 if dst_left < 1 { return (0, E2BIG); }
5711 *dst = b; return (1, 0);
5712 }
5713 (0, EILSEQ)
5714 }
5715 ENC_ISO8859_5 => {
5716 if let Some(b) = u_to_iso8859(&ISO8859_5_TO_U, c) {
5717 if dst_left < 1 { return (0, E2BIG); }
5718 *dst = b; return (1, 0);
5719 }
5720 (0, EILSEQ)
5721 }
5722 ENC_ISO8859_6 => {
5723 if let Some(b) = u_to_iso8859(&ISO8859_6_TO_U, c) {
5724 if dst_left < 1 { return (0, E2BIG); }
5725 *dst = b; return (1, 0);
5726 }
5727 (0, EILSEQ)
5728 }
5729 ENC_ISO8859_7 => {
5730 if let Some(b) = u_to_iso8859(&ISO8859_7_TO_U, c) {
5731 if dst_left < 1 { return (0, E2BIG); }
5732 *dst = b; return (1, 0);
5733 }
5734 (0, EILSEQ)
5735 }
5736 ENC_ISO8859_8 => {
5737 if let Some(b) = u_to_iso8859(&ISO8859_8_TO_U, c) {
5738 if dst_left < 1 { return (0, E2BIG); }
5739 *dst = b; return (1, 0);
5740 }
5741 (0, EILSEQ)
5742 }
5743 ENC_ISO8859_9 => {
5744 if let Some(b) = u_to_iso8859(&ISO8859_9_TO_U, c) {
5745 if dst_left < 1 { return (0, E2BIG); }
5746 *dst = b; return (1, 0);
5747 }
5748 (0, EILSEQ)
5749 }
5750 ENC_ISO8859_10 => {
5751 if let Some(b) = u_to_iso8859(&ISO8859_10_TO_U, c) {
5752 if dst_left < 1 { return (0, E2BIG); }
5753 *dst = b; return (1, 0);
5754 }
5755 (0, EILSEQ)
5756 }
5757 ENC_ISO8859_11 => {
5758 if let Some(b) = u_to_iso8859(&ISO8859_11_TO_U, c) {
5759 if dst_left < 1 { return (0, E2BIG); }
5760 *dst = b; return (1, 0);
5761 }
5762 (0, EILSEQ)
5763 }
5764 ENC_ISO8859_13 => {
5765 if let Some(b) = u_to_iso8859(&ISO8859_13_TO_U, c) {
5766 if dst_left < 1 { return (0, E2BIG); }
5767 *dst = b; return (1, 0);
5768 }
5769 (0, EILSEQ)
5770 }
5771 ENC_ISO8859_14 => {
5772 if let Some(b) = u_to_iso8859(&ISO8859_14_TO_U, c) {
5773 if dst_left < 1 { return (0, E2BIG); }
5774 *dst = b; return (1, 0);
5775 }
5776 (0, EILSEQ)
5777 }
5778 ENC_ISO8859_15 => {
5779 if let Some(b) = u_to_iso8859(&ISO8859_15_TO_U, c) {
5780 if dst_left < 1 { return (0, E2BIG); }
5781 *dst = b; return (1, 0);
5782 }
5783 (0, EILSEQ)
5784 }
5785 ENC_ISO8859_16 => {
5786 if let Some(b) = u_to_iso8859(&ISO8859_16_TO_U, c) {
5787 if dst_left < 1 { return (0, E2BIG); }
5788 *dst = b; return (1, 0);
5789 }
5790 (0, EILSEQ)
5791 }
5792 ENC_WIN1252 => {
5793 if c < 128 {
5794 if dst_left < 1 { return (0, E2BIG); }
5795 *dst = c as u8; return (1, 0);
5796 }
5797 if c >= 0xA0 && c <= 0xFF && WIN1252_TO_U[c as usize - 128] == c {
5798 if dst_left < 1 { return (0, E2BIG); }
5799 *dst = c as u8; return (1, 0);
5800 }
5801 for i in 0..128usize {
5802 if WIN1252_TO_U[i] == c {
5803 if dst_left < 1 { return (0, E2BIG); }
5804 *dst = (i + 128) as u8; return (1, 0);
5805 }
5806 }
5807 (0, EILSEQ)
5808 }
5809 ENC_WIN1251 => {
5810 if c < 128 {
5811 if dst_left < 1 { return (0, E2BIG); }
5812 *dst = c as u8; return (1, 0);
5813 }
5814 for i in 0..128usize {
5815 if WIN1251_TO_U[i] == c {
5816 if dst_left < 1 { return (0, E2BIG); }
5817 *dst = (i + 128) as u8; return (1, 0);
5818 }
5819 }
5820 (0, EILSEQ)
5821 }
5822 ENC_KOI8R => {
5823 if c < 128 {
5824 if dst_left < 1 { return (0, E2BIG); }
5825 *dst = c as u8; return (1, 0);
5826 }
5827 for i in 0..128usize {
5828 if KOI8R_TO_U[i] == c {
5829 if dst_left < 1 { return (0, E2BIG); }
5830 *dst = (i + 128) as u8; return (1, 0);
5831 }
5832 }
5833 (0, EILSEQ)
5834 }
5835 ENC_GBK | ENC_GB2312 => {
5836 if c < 128 {
5837 if dst_left < 1 { return (0, E2BIG); }
5838 *dst = c as u8; return (1, 0);
5839 }
5840 if c == 0x20AC {
5841 if dst_left < 1 { return (0, E2BIG); }
5842 *dst = 128; return (1, 0);
5843 }
5844 for row in 0..126usize {
5845 for col in 0..190usize {
5846 if GB18030_TABLE[row * 190 + col] as u32 == c {
5847 if dst_left < 2 { return (0, E2BIG); }
5848 *dst = (row + 0x81) as u8;
5849 *dst.add(1) = if col <= 62 { (col + 0x40) as u8 } else { (col + 0x41) as u8 };
5850 return (2, 0);
5851 }
5852 }
5853 }
5854 (0, EILSEQ)
5855 }
5856 ENC_BIG5 => {
5857 if c < 128 {
5858 if dst_left < 1 { return (0, E2BIG); }
5859 *dst = c as u8; return (1, 0);
5860 }
5861 for row in 0..89usize {
5862 for col in 0..157usize {
5863 if BIG5_TABLE[row * 157 + col] as u32 == c {
5864 if dst_left < 2 { return (0, E2BIG); }
5865 *dst = (row + 0xA1) as u8;
5866 *dst.add(1) = if col <= 0x3E { (col + 0x40) as u8 } else { (col + 0x62) as u8 };
5867 return (2, 0);
5868 }
5869 }
5870 }
5871 (0, EILSEQ)
5872 }
5873 ENC_EUCJP => {
5874 if c < 128 {
5875 if dst_left < 1 { return (0, E2BIG); }
5876 *dst = c as u8; return (1, 0);
5877 }
5878 if c >= 0xFF61 && c <= 0xFF9F {
5879 if dst_left < 2 { return (0, E2BIG); }
5880 *dst = 0x8E;
5881 *dst.add(1) = (c - 0xFF61 + 0xA1) as u8;
5882 return (2, 0);
5883 }
5884 let jis = uni_to_jis(c);
5885 if jis == 0 { return (0, EILSEQ); }
5886 if dst_left < 2 { return (0, E2BIG); }
5887 *dst = ((jis >> 8) as u8).wrapping_add(0x80);
5888 *dst.add(1) = ((jis & 0xFF) as u8).wrapping_add(0x80);
5889 (2, 0)
5890 }
5891 ENC_SHIFTJIS => {
5892 if c < 128 {
5893 if dst_left < 1 { return (0, E2BIG); }
5894 *dst = c as u8; return (1, 0);
5895 }
5896 if c >= 0xFF61 && c <= 0xFF9F {
5897 if dst_left < 1 { return (0, E2BIG); }
5898 *dst = (c - 0xFF61 + 0xA1) as u8;
5899 return (1, 0);
5900 }
5901 let jis = uni_to_jis(c);
5902 if jis == 0 { return (0, EILSEQ); }
5903 if dst_left < 2 { return (0, E2BIG); }
5904 let r = (jis >> 8) as usize;
5905 let d = (jis & 0xFF) as usize;
5906 *dst = ((r + 1) / 2 + if r < 95 { 112 } else { 176 }) as u8;
5907 *dst.add(1) = if r % 2 == 1 { (d + 31 + d / 96) as u8 } else { (d + 126) as u8 };
5908 (2, 0)
5909 }
5910 _ => (0, EILSEQ),
5911 }
5912}
5913
5914#[no_mangle]
5915pub unsafe extern "C" fn iconv_open(tocode: *const c_char, fromcode: *const c_char) -> IconvT {
5916 let to = find_encoding(tocode as *const u8);
5917 let from = find_encoding(fromcode as *const u8);
5918 if to < 0 || from < 0 {
5919 ERRNO = EINVAL;
5920 return !0usize as IconvT;
5921 }
5922 make_cd(from, to)
5923}
5924
5925#[no_mangle]
5926pub unsafe extern "C" fn iconv(
5927 cd: IconvT,
5928 inbuf: *mut *mut c_char,
5929 inbytesleft: *mut SizeT,
5930 outbuf: *mut *mut c_char,
5931 outbytesleft: *mut SizeT,
5932) -> SizeT {
5933 if cd == !0usize as IconvT {
5934 ERRNO = EINVAL;
5935 return !0usize;
5936 }
5937 if inbuf.is_null() || outbuf.is_null() { return 0; }
5938 let from = extract_from(cd);
5939 let to = extract_to(cd);
5940 let mut src = *inbuf as *const u8;
5941 let mut dst = *outbuf as *mut u8;
5942 let mut src_left = *inbytesleft;
5943 let mut dst_left = *outbytesleft;
5944 let mut subst = 0usize;
5945 while src_left > 0 {
5946 let (cp, consumed, err) = iconv_decode(from, src, src_left);
5947 if err != 0 {
5948 if err == EINVAL { break; }
5949 ERRNO = err;
5950 return !0usize;
5951 }
5952 let (written, err) = iconv_encode(to, cp, dst, dst_left);
5953 if err != 0 {
5954 if err == E2BIG {
5955 ERRNO = E2BIG;
5956 return !0usize;
5957 }
5958 if dst_left < 1 {
5959 ERRNO = E2BIG;
5960 return !0usize;
5961 }
5962 *dst = b'*';
5963 dst = dst.add(1);
5964 dst_left -= 1;
5965 subst += 1;
5966 } else {
5967 dst = dst.add(written);
5968 dst_left -= written;
5969 }
5970 src = src.add(consumed);
5971 src_left -= consumed;
5972 }
5973 *inbuf = src as *mut c_char;
5974 *outbuf = dst as *mut c_char;
5975 *inbytesleft = src_left;
5976 *outbytesleft = dst_left;
5977 subst
5978}
5979
5980#[no_mangle]
5981pub unsafe extern "C" fn iconv_close(_cd: IconvT) -> c_int { 0 }
5982
5983#[no_mangle]
5988pub unsafe extern "C" fn write(fd: c_int, buf: *const c_void, count: SizeT) -> SSizeT {
5989 sys_write(fd as i64, buf as *const u8, count) as SSizeT
5990}
5991
5992#[no_mangle]
5993pub unsafe extern "C" fn read(fd: c_int, buf: *mut c_void, count: SizeT) -> SSizeT {
5994 sys_read(fd as i64, buf as *mut u8, count) as SSizeT
5995}
5996
5997#[no_mangle]
5998pub unsafe extern "C" fn open(path: *const c_char, flags: c_int, mode: c_int) -> c_int {
5999 sys_open(path as *const u8, flags as i64, mode as i64) as c_int
6000}
6001
6002#[no_mangle]
6003pub unsafe extern "C" fn close(fd: c_int) -> c_int {
6004 sys_close(fd as i64);
6005 0
6006}
6007
6008#[no_mangle]
6009pub unsafe extern "C" fn lseek(fd: c_int, offset: i64, whence: c_int) -> i64 {
6010 sys_lseek(fd as i64, offset, whence as i64)
6011}
6012
6013const O_RDONLY: i32 = 0;
6018const O_WRONLY: i32 = 1;
6019const O_RDWR: i32 = 2;
6020const O_CREAT: i32 = 64;
6021const O_TRUNC: i32 = 512;
6022const O_APPEND: i32 = 1024;
6023const O_EXCL: i32 = 128;
6024const O_NONBLOCK: i32 = 2048;
6025const O_NOFOLLOW: i32 = if cfg!(target_arch = "aarch64") { 0o100000 } else { 0o400000 };
6026const O_DIRECTORY: i32 = if cfg!(target_arch = "aarch64") { 0o40000 } else { 0o200000 };
6027const O_CLOEXEC: i32 = 0x80000;
6028
6029const F_GETFD: i32 = 1;
6030const F_SETFD: i32 = 2;
6031const F_GETFL: i32 = 3;
6032const F_SETFL: i32 = 4;
6033const F_GETLK: i32 = 5;
6034const F_SETLK: i32 = 6;
6035const F_SETLKW: i32 = 7;
6036const F_DUPFD: i32 = 0;
6037const F_DUPFD_CLOEXEC: i32 = 1030;
6038const FD_CLOEXEC: i32 = 1;
6039
6040const TIOCGWINSZ: u32 = 0x5413;
6041
6042#[repr(C)]
6043struct winsize {
6044 ws_row: u16,
6045 ws_col: u16,
6046 ws_xpixel: u16,
6047 ws_ypixel: u16,
6048}
6049
6050#[inline]
6051unsafe fn sys_pipe2(fds: *mut c_int, flags: i32) -> i64 {
6052 <Arch as Syscalls>::syscall2(SYS_PIPE2, fds as i64, flags as i64)
6053}
6054
6055#[inline]
6056unsafe fn sys_dup3(oldfd: i32, newfd: i32, flags: i32) -> i64 {
6057 <Arch as Syscalls>::syscall3(SYS_DUP3, oldfd as i64, newfd as i64, flags as i64)
6058}
6059
6060#[inline]
6061unsafe fn sys_fcntl(fd: i32, cmd: i32, arg: i64) -> i64 {
6062 <Arch as Syscalls>::syscall3(SYS_FCNTL, fd as i64, cmd as i64, arg as i64)
6063}
6064
6065#[inline]
6066unsafe fn sys_ioctl(fd: c_int, request: u32, arg: *mut u8) -> i64 {
6067 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, request as i64, arg as i64)
6068}
6069
6070#[inline]
6071unsafe fn sys_unlinkat(dirfd: i32, path: *const u8, flags: i32) -> i64 {
6072 <Arch as Syscalls>::syscall3(SYS_UNLINKAT, dirfd as i64, path as i64, flags as i64)
6073}
6074
6075#[inline]
6076unsafe fn sys_renameat2(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: u32) -> i64 {
6077 <Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
6078}
6079
6080const UNGET: usize = 8;
6085const F_PERM: u32 = 1;
6086const F_NORD: u32 = 4;
6087const F_NOWR: u32 = 8;
6088const F_EOF: u32 = 16;
6089const F_ERR: u32 = 32;
6090const F_SVB: u32 = 64;
6091const F_APP: u32 = 128;
6092
6093const BUFSIZ: usize = 1024;
6094
6095const _IOFBF: c_int = 0;
6096const _IOLBF: c_int = 1;
6097const _IONBF: c_int = 2;
6098
6099const SEEK_SET: c_int = 0;
6100const SEEK_CUR: c_int = 1;
6101const SEEK_END: c_int = 2;
6102
6103#[repr(C)]
6105pub struct FILE {
6106 flags: c_uint,
6107 rpos: *mut u8,
6108 rend: *mut u8,
6109 close: Option<unsafe extern "C" fn(*mut FILE) -> c_int>,
6110 wend: *mut u8,
6111 wpos: *mut u8,
6112 mustbezero_1: *mut u8,
6113 wbase: *mut u8,
6114 read_fn: Option<unsafe extern "C" fn(*mut FILE, *mut u8, usize) -> usize>,
6115 write_fn: Option<unsafe extern "C" fn(*mut FILE, *const u8, usize) -> usize>,
6116 seek_fn: Option<unsafe extern "C" fn(*mut FILE, i64, c_int) -> i64>,
6117 buf: *mut u8,
6118 buf_size: usize,
6119 prev: *mut FILE,
6120 next: *mut FILE,
6121 fd: c_int,
6122 pipe_pid: c_int,
6123 lockcount: c_long,
6124 mode: c_int,
6125 lock: c_int,
6126 lbf: c_int,
6127 cookie: *mut c_void,
6128 off: i64,
6129 getln_buf: *mut c_char,
6130 mustbezero_2: *mut c_void,
6131 shend: *mut u8,
6132 shlim: i64,
6133 shcnt: i64,
6134 ungotten: [c_int; UNGET],
6135 ungotten_count: c_int,
6136 _eof: c_int,
6137 _err: c_int,
6138}
6139
6140static mut STDIN_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6141static mut STDOUT_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6142static mut STDERR_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6143
6144static mut STDIN_FILE: FILE = FILE {
6145 flags: 0, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6146 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6147 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6148 read_fn: None, write_fn: None, seek_fn: None,
6149 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6150 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6151 fd: 0, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6152 cookie: core::ptr::null_mut(), off: 0,
6153 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6154 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6155 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6156};
6157static mut STDOUT_FILE: FILE = FILE {
6158 flags: F_NOWR as u32 + F_SVB as u32, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6159 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6160 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6161 read_fn: None, write_fn: None, seek_fn: None,
6162 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6163 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6164 fd: 1, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6165 cookie: core::ptr::null_mut(), off: 0,
6166 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6167 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6168 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6169};
6170static mut STDERR_FILE: FILE = FILE {
6171 flags: F_NOWR as u32, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6172 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6173 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6174 read_fn: None, write_fn: None, seek_fn: None,
6175 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6176 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6177 fd: 2, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6178 cookie: core::ptr::null_mut(), off: 0,
6179 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6180 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6181 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6182};
6183
6184#[no_mangle]
6185pub static mut stdin: *mut FILE = &raw mut STDIN_FILE as *mut FILE;
6186#[no_mangle]
6187pub static mut stdout: *mut FILE = &raw mut STDOUT_FILE as *mut FILE;
6188#[no_mangle]
6189pub static mut stderr: *mut FILE = &raw mut STDERR_FILE as *mut FILE;
6190
6191unsafe fn __stdio_init() {
6196 STDIN_FILE.buf = core::ptr::addr_of_mut!(STDIN_BUF) as *mut u8;
6197 STDIN_FILE.buf_size = BUFSIZ;
6198 STDIN_FILE.read_fn = Some(__stdio_read);
6199 STDIN_FILE.write_fn = Some(__stdio_write);
6200 STDIN_FILE.seek_fn = Some(__stdio_seek);
6201 STDOUT_FILE.buf = core::ptr::addr_of_mut!(STDOUT_BUF) as *mut u8;
6202 STDOUT_FILE.buf_size = BUFSIZ;
6203 STDOUT_FILE.lbf = b'\n' as c_int;
6204 STDOUT_FILE.read_fn = Some(__stdio_read);
6205 STDOUT_FILE.write_fn = Some(__stdio_write);
6206 STDOUT_FILE.seek_fn = Some(__stdio_seek);
6207 STDERR_FILE.buf = core::ptr::addr_of_mut!(STDERR_BUF) as *mut u8;
6208 STDERR_FILE.buf_size = BUFSIZ;
6209 STDERR_FILE.read_fn = Some(__stdio_read);
6210 STDERR_FILE.write_fn = Some(__stdio_write);
6211 STDERR_FILE.seek_fn = Some(__stdio_seek);
6212}
6213
6214unsafe fn buf_ptr(f: *mut FILE) -> *mut u8 {
6215 (f as *mut u8).add(core::mem::size_of::<FILE>())
6216}
6217
6218unsafe extern "C" fn __stdio_read(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
6219 let n = sys_read((*f).fd as i64, buf, len);
6220 if n <= 0 {
6221 if n == 0 { (*f).flags |= F_EOF; } else { (*f).flags |= F_ERR; (*f)._err = 1; }
6222 return 0;
6223 }
6224 n as usize
6225}
6226
6227unsafe extern "C" fn __stdio_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
6228 let l = (*f).wpos as usize - (*f).wbase as usize;
6229 let mut iov = [
6230 ((*f).wbase as *const u8, l),
6231 (buf, len),
6232 ];
6233 if iov[0].1 == 0 { iov = [iov[1], (core::ptr::null(), 0)]; }
6234 if (*f).flags & F_APP != 0 {
6235 let _ = sys_lseek((*f).fd as i64, 0, SEEK_END as i64);
6236 }
6237 let mut rem = iov[0].1 + iov[1].1;
6238 let mut idx = 0usize;
6239 while rem > 0 {
6240 let ptr = iov[idx].0;
6241 let cnt = iov[idx].1;
6242 if cnt == 0 { idx += 1; continue; }
6243 let n = sys_write((*f).fd as i64, ptr, cnt);
6244 if n <= 0 {
6245 (*f).wpos = core::ptr::null_mut();
6246 (*f).wbase = core::ptr::null_mut();
6247 (*f).wend = core::ptr::null_mut();
6248 (*f).flags |= F_ERR;
6249 return if iov[idx].0 == buf { 0 } else { len };
6250 }
6251 rem -= n as usize;
6252 iov[idx].0 = iov[idx].0.add(n as usize);
6253 iov[idx].1 -= n as usize;
6254 if iov[idx].1 == 0 { idx += 1; }
6255 }
6256 (*f).wend = (*f).buf.add((*f).buf_size);
6257 (*f).wbase = (*f).buf;
6258 (*f).wpos = (*f).buf;
6259 len
6260}
6261
6262unsafe extern "C" fn __stdio_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
6263 sys_lseek((*f).fd as i64, off, whence as i64)
6264}
6265
6266unsafe fn init_file(
6267 f: *mut FILE,
6268 fd: c_int,
6269 mode: *const c_char,
6270 close_fn: Option<unsafe extern "C" fn(*mut FILE) -> c_int>,
6271 buf_area: *mut u8,
6272 buf_sz: usize,
6273) {
6274 core::ptr::write_bytes(f as *mut u8, 0, core::mem::size_of::<FILE>());
6275 (*f).fd = fd;
6276 (*f).close = close_fn;
6277 (*f).lock = 0;
6278 (*f).lbf = -1;
6279 (*f).buf = buf_area;
6280 (*f).buf_size = buf_sz;
6281 (*f).read_fn = Some(__stdio_read);
6282 (*f).write_fn = Some(__stdio_write);
6283 (*f).seek_fn = Some(__stdio_seek);
6284 let m = *mode;
6285 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
6286 if m == b'r' as c_char && !has_plus {
6287 (*f).flags = F_NORD;
6288 } else if !has_plus {
6289 (*f).flags = F_NOWR;
6290 }
6291}
6292
6293unsafe extern "C" fn __stdio_close(f: *mut FILE) -> c_int {
6294 sys_close((*f).fd as i64);
6295 0
6296}
6297
6298unsafe fn fmodeflags(mode: *const c_char) -> c_int {
6299 let mut flags: c_int;
6300 let m = *mode;
6301 if !strchr(mode as *const u8, b'+' as c_int).is_null() {
6302 flags = O_RDWR;
6303 } else if m == b'r' as c_char {
6304 flags = O_RDONLY;
6305 } else {
6306 flags = O_WRONLY;
6307 }
6308 if !strchr(mode as *const u8, b'x' as c_int).is_null() { flags |= O_EXCL; }
6309 if !strchr(mode as *const u8, b'e' as c_int).is_null() { flags |= O_CLOEXEC; }
6310 if m != b'r' as c_char { flags |= O_CREAT; }
6311 if m == b'w' as c_char { flags |= O_TRUNC; }
6312 if m == b'a' as c_char { flags |= O_APPEND; }
6313 flags
6314}
6315
6316const O_ACCMODE: c_int = O_RDONLY | O_WRONLY | O_RDWR;
6317
6318unsafe fn flush_buf(f: *mut FILE) -> c_int {
6319 if (*f).wpos == (*f).wbase {
6320 if !(*f).wpos.is_null() {
6321 (*f).wend = (*f).buf.add((*f).buf_size);
6322 (*f).wpos = (*f).wbase;
6323 }
6324 return 0;
6325 }
6326 if let Some(wfunc) = (*f).write_fn {
6327 let ret = wfunc(f, core::ptr::null(), 0);
6328 if ret == 0 && (*f).wpos.is_null() { return -1; }
6329 return 0;
6330 }
6331 (*f).flags |= F_ERR;
6332 -1
6333}
6334
6335#[no_mangle]
6340pub unsafe extern "C" fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE {
6341 if filename.is_null() || mode.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
6342 let m = *mode;
6343 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
6344 ERRNO = EINVAL; return core::ptr::null_mut();
6345 }
6346 let flags = fmodeflags(mode);
6347 let fd = sys_open(filename as *const u8, flags as i64, 0o666);
6348 if fd < 0 { ERRNO = (-fd) as c_int; return core::ptr::null_mut(); }
6349 fdopen(fd as c_int, mode)
6350}
6351
6352#[no_mangle]
6353pub unsafe extern "C" fn fdopen(fd: c_int, mode: *const c_char) -> *mut FILE {
6354 if fd < 0 || mode.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
6355 let m = *mode;
6356 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
6357 ERRNO = EINVAL; return core::ptr::null_mut();
6358 }
6359 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
6360 if f.is_null() { ERRNO = ENOMEM; return core::ptr::null_mut(); }
6361 let buf = buf_ptr(f);
6362 init_file(f, fd, mode, Some(__stdio_close), buf, BUFSIZ);
6363 if !strchr(mode as *const u8, b'a' as c_int).is_null() { (*f).flags |= F_APP; }
6364 if !strchr(mode as *const u8, b'e' as c_int).is_null() { sys_fcntl(fd, F_SETFD, FD_CLOEXEC as i64); }
6365 if (*f).flags & F_NOWR == 0 {
6366 let mut ws: winsize = core::mem::zeroed();
6367 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 {
6368 (*f).lbf = b'\n' as c_int;
6369 }
6370 }
6371 f
6372}
6373
6374#[no_mangle]
6375pub unsafe extern "C" fn freopen(
6376 filename: *const c_char, mode: *const c_char, f: *mut FILE,
6377) -> *mut FILE {
6378 fflush(f);
6379 if (*f).pipe_pid > 0 { let _ = __stdio_close(f); }
6380 if filename.is_null() {
6381 let flags = fmodeflags(mode);
6382 if flags == 0 { return core::ptr::null_mut(); }
6383 let mut fl = flags & !(O_CREAT | O_EXCL | O_CLOEXEC);
6384 if (*f).flags & F_APP != 0 { fl = (fl & !O_ACCMODE) | O_WRONLY | O_APPEND; }
6385 if sys_fcntl((*f).fd, F_SETFL, fl as i64) < 0 { return core::ptr::null_mut(); }
6386 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
6387 if has_plus {
6388 (*f).flags &= !(F_NORD | F_NOWR);
6389 } else if *mode == b'r' as c_char {
6390 (*f).flags = ((*f).flags & !F_NOWR) | F_NORD;
6391 } else {
6392 (*f).flags = ((*f).flags & !F_NORD) | F_NOWR;
6393 }
6394 return f;
6395 }
6396 let new_f = fopen(filename, mode);
6397 if new_f.is_null() { let _ = __stdio_close(f); return core::ptr::null_mut(); }
6398 if (*new_f).fd == (*f).fd {
6399 (*new_f).fd = -1;
6400 } else {
6401 sys_dup3((*new_f).fd, (*f).fd, 0);
6402 let _ = __stdio_close(new_f);
6403 }
6404 (*f).flags = (*new_f).flags;
6405 (*f).rpos = core::ptr::null_mut();
6406 (*f).rend = core::ptr::null_mut();
6407 (*f).wpos = core::ptr::null_mut();
6408 (*f).wbase = core::ptr::null_mut();
6409 (*f).wend = core::ptr::null_mut();
6410 (*f).lbf = (*new_f).lbf;
6411 (*f).pipe_pid = 0;
6412 free(new_f as *mut c_void);
6413 f
6414}
6415
6416#[no_mangle]
6417pub unsafe extern "C" fn fclose(f: *mut FILE) -> c_int {
6418 if f.is_null() { return -1; }
6419 let r = fflush(f);
6420 if let Some(close_fn) = (*f).close { let _ = close_fn(f); }
6421 if r != 0 { -1 } else { 0 }
6422}
6423
6424#[no_mangle]
6429pub unsafe extern "C" fn setvbuf(f: *mut FILE, buf: *mut c_char, mode: c_int, size: usize) -> c_int {
6430 if mode != _IOFBF && mode != _IOLBF && mode != _IONBF { return -1; }
6431 fflush(f);
6432 (*f).rpos = core::ptr::null_mut();
6433 (*f).rend = core::ptr::null_mut();
6434 (*f).wpos = core::ptr::null_mut();
6435 (*f).wbase = core::ptr::null_mut();
6436 (*f).wend = core::ptr::null_mut();
6437 if mode == _IONBF {
6438 (*f).buf_size = 0;
6439 } else if !buf.is_null() && size > 0 {
6440 (*f).buf = buf as *mut u8;
6441 (*f).buf_size = size;
6442 }
6443 (*f).lbf = if mode == _IOLBF { b'\n' as c_int } else { -1 };
6444 0
6445}
6446
6447#[no_mangle]
6448pub unsafe extern "C" fn setbuf(f: *mut FILE, buf: *mut c_char) {
6449 if buf.is_null() { setvbuf(f, core::ptr::null_mut(), _IONBF, 0); }
6450 else { setvbuf(f, buf, _IOFBF, BUFSIZ); }
6451}
6452
6453#[no_mangle]
6454pub unsafe extern "C" fn setbuffer(f: *mut FILE, buf: *mut c_char, size: usize) {
6455 if buf.is_null() { setvbuf(f, core::ptr::null_mut(), _IONBF, 0); }
6456 else { setvbuf(f, buf, _IOFBF, size); }
6457}
6458
6459#[no_mangle]
6460pub unsafe extern "C" fn fflush(f: *mut FILE) -> c_int {
6461 if f.is_null() {
6462 let mut r = 0;
6463 if !stdout.is_null() && !(*stdout).wpos.is_null() && (*stdout).wpos != (*stdout).wbase {
6464 if flush_buf(stdout) != 0 { r = -1; }
6465 }
6466 if !stderr.is_null() && !(*stderr).wpos.is_null() && (*stderr).wpos != (*stderr).wbase {
6467 if flush_buf(stderr) != 0 { r = -1; }
6468 }
6469 return r;
6470 }
6471 if !(*f).wpos.is_null() && (*f).wpos != (*f).wbase {
6472 return flush_buf(f);
6473 }
6474 0
6475}
6476
6477#[no_mangle]
6482pub unsafe extern "C" fn fwide(_f: *mut FILE, mode: c_int) -> c_int { mode }
6483
6484#[no_mangle]
6485pub unsafe extern "C" fn feof(f: *mut FILE) -> c_int { if (*f)._eof != 0 { 1 } else { 0 } }
6486
6487#[no_mangle]
6488pub unsafe extern "C" fn ferror(f: *mut FILE) -> c_int { if (*f)._err != 0 { 1 } else { 0 } }
6489
6490#[no_mangle]
6491pub unsafe extern "C" fn clearerr(f: *mut FILE) { (*f)._eof = 0; (*f)._err = 0; }
6492
6493#[no_mangle]
6494pub unsafe extern "C" fn fileno(f: *mut FILE) -> c_int { (*f).fd }
6495
6496#[no_mangle]
6501pub unsafe extern "C" fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int {
6502 fseeko(stream, offset as i64, whence)
6503}
6504
6505#[no_mangle]
6506pub unsafe extern "C" fn ftell(stream: *mut FILE) -> c_long {
6507 ftello(stream) as c_long
6508}
6509
6510#[no_mangle]
6511pub unsafe extern "C" fn rewind(stream: *mut FILE) {
6512 fseek(stream, 0, SEEK_SET);
6513 (*stream)._eof = 0;
6514 (*stream)._err = 0;
6515}
6516
6517#[no_mangle]
6518pub unsafe extern "C" fn fseeko(stream: *mut FILE, offset: i64, whence: c_int) -> c_int {
6519 if whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END {
6520 ERRNO = EINVAL;
6521 return -1;
6522 }
6523 let f = &mut *stream;
6524 let mut adj_offset = offset;
6525 if whence == SEEK_CUR {
6526 if !f.rpos.is_null() {
6527 adj_offset -= f.rend as i64 - f.rpos as i64;
6528 }
6529 adj_offset -= f.ungotten_count as i64;
6530 }
6531 if !f.wpos.is_null() && f.wpos != f.wbase {
6532 if flush_buf(stream) != 0 { return -1; }
6533 }
6534 f.wpos = core::ptr::null_mut();
6535 f.wbase = core::ptr::null_mut();
6536 f.wend = core::ptr::null_mut();
6537 if let Some(sfunc) = f.seek_fn {
6538 let r = sfunc(stream, adj_offset, whence);
6539 if r < 0 { return -1; }
6540 } else {
6541 ERRNO = EINVAL;
6542 return -1;
6543 }
6544 f.rpos = core::ptr::null_mut();
6545 f.rend = core::ptr::null_mut();
6546 f._eof = 0;
6547 f.ungotten_count = 0;
6548 0
6549}
6550
6551#[no_mangle]
6552pub unsafe extern "C" fn ftello(stream: *mut FILE) -> i64 {
6553 let f = &mut *stream;
6554 if f.flags & F_APP != 0 && !f.wpos.is_null() && f.wpos != f.wbase {
6555 if fflush(stream) != 0 { return -1; }
6556 }
6557 let sfunc = match f.seek_fn { Some(s) => s, None => return -1 };
6558 let pos = sfunc(stream, 0,
6559 if (f.flags & F_APP) != 0 && !f.wpos.is_null() && f.wpos != f.wbase { SEEK_END } else { SEEK_CUR });
6560 if pos < 0 { return -1; }
6561 let mut pos = pos;
6562 if !f.rpos.is_null() {
6563 pos += f.rpos as i64 - f.rend as i64;
6564 } else if !f.wbase.is_null() {
6565 pos += f.wpos as i64 - f.wbase as i64;
6566 }
6567 pos - f.ungotten_count as i64
6568}
6569
6570#[no_mangle]
6571pub unsafe extern "C" fn fgetpos(stream: *mut FILE, pos: *mut i64) -> c_int {
6572 let off = ftello(stream);
6573 if off < 0 { return -1; }
6574 *pos = off;
6575 0
6576}
6577
6578#[no_mangle]
6579pub unsafe extern "C" fn fsetpos(stream: *mut FILE, pos: *const i64) -> c_int {
6580 fseeko(stream, *pos, SEEK_SET)
6581}
6582
6583#[no_mangle]
6588pub unsafe extern "C" fn fgetc(stream: *mut FILE) -> c_int {
6589 let f = &mut *stream;
6590 if f.ungotten_count > 0 {
6591 f.ungotten_count -= 1;
6592 return f.ungotten[f.ungotten_count as usize];
6593 }
6594 if !f.rpos.is_null() && f.rpos < f.rend {
6595 let c = *f.rpos;
6596 f.rpos = f.rpos.add(1);
6597 return c as c_int;
6598 }
6599 if f._eof != 0 { return -1; }
6600 if let Some(rfunc) = f.read_fn {
6601 let mut buf = [0u8; 1];
6602 let n = rfunc(stream, buf.as_mut_ptr(), 1);
6603 if n == 0 {
6604 if f.flags & F_ERR != 0 { f._err = 1; } else { f._eof = 1; }
6605 return -1;
6606 }
6607 buf[0] as c_int
6608 } else {
6609 f._eof = 1;
6610 -1
6611 }
6612}
6613
6614#[no_mangle]
6615pub unsafe extern "C" fn getc(stream: *mut FILE) -> c_int { fgetc(stream) }
6616
6617#[no_mangle]
6618pub unsafe extern "C" fn getchar() -> c_int { fgetc(stdin) }
6619
6620#[no_mangle]
6621pub unsafe extern "C" fn ungetc(c: c_int, stream: *mut FILE) -> c_int {
6622 if c == -1 { return -1; }
6623 let f = &mut *stream;
6624 if f.ungotten_count >= UNGET as c_int { return -1; }
6625 f.ungotten[f.ungotten_count as usize] = c;
6626 f.ungotten_count += 1;
6627 f._eof = 0;
6628 c
6629}
6630
6631#[no_mangle]
6636pub unsafe extern "C" fn fgets(s: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char {
6637 if n <= 0 { return null_mut(); }
6638 let max = (n - 1) as usize;
6639 let mut i = 0usize;
6640 while i < max {
6641 let c = fgetc(stream);
6642 if c == -1 { if i == 0 { return null_mut(); } break; }
6643 *s.add(i) = c as c_char;
6644 i += 1;
6645 if c == b'\n' as c_int { break; }
6646 }
6647 *s.add(i) = 0;
6648 s
6649}
6650
6651#[no_mangle]
6653pub unsafe extern "C" fn gets(s: *mut c_char) -> *mut c_char {
6654 let mut i = 0usize;
6655 loop {
6656 let c = fgetc(stdin);
6657 if c == -1 { if i == 0 { return null_mut(); } break; }
6658 if c == b'\n' as c_int { break; }
6659 *s.add(i) = c as c_char;
6660 i += 1;
6661 }
6662 *s.add(i) = 0;
6663 s
6664}
6665
6666#[no_mangle]
6667pub unsafe extern "C" fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut FILE {
6668 fopen(filename, mode)
6669}
6670
6671const PERROR_BUF_SIZE: usize = 64;
6673static mut PERROR_BUF: [u8; PERROR_BUF_SIZE] = [0; PERROR_BUF_SIZE];
6674
6675#[no_mangle]
6676pub unsafe extern "C" fn perror(msg: *const c_char) {
6677 let fd = (*stderr).fd;
6678 if !msg.is_null() && *msg != 0 {
6679 let len = strlen(msg as *const c_char);
6680 write_str(fd, msg as *const u8, len);
6681 write_str(fd, b": ".as_ptr(), 2);
6682 }
6683 let e = ERRNO;
6684 let text = strerror(e) as *const u8;
6685 write_str(fd, text, strlen(text as *const c_char));
6686 write_str(fd, b"\n".as_ptr(), 1);
6687}
6688
6689#[no_mangle]
6690pub unsafe extern "C" fn fread(
6691 ptr: *mut c_void, size: SizeT, nmemb: SizeT, stream: *mut FILE,
6692) -> SizeT {
6693 if size == 0 || nmemb == 0 { return 0; }
6694 let total = size * nmemb;
6695 let mut rd = 0usize;
6696 while rd < total {
6697 let c = fgetc(stream);
6698 if c == -1 { break; }
6699 *(ptr as *mut u8).add(rd) = c as u8;
6700 rd += 1;
6701 }
6702 rd / size
6703}
6704
6705unsafe fn write_str(fd: c_int, s: *const u8, len: usize) {
6710 let mut written = 0usize;
6711 while written < len {
6712 let n = sys_write(fd as i64, s.add(written), len - written);
6713 if n <= 0 { break; }
6714 written += n as usize;
6715 }
6716}
6717
6718#[no_mangle]
6719unsafe fn __overflow(f: *mut FILE, c: c_int) -> c_int {
6720 if (*f).wpos.is_null() {
6721 (*f).wbase = (*f).buf;
6722 (*f).wpos = (*f).buf;
6723 (*f).wend = (*f).buf.add((*f).buf_size);
6724 }
6725 if flush_buf(f) == -1 { return -1; }
6726 if (*f).wpos >= (*f).wend {
6727 if let Some(wfunc) = (*f).write_fn {
6728 let byte = c as u8;
6729 let ret = wfunc(f, &byte as *const u8, 1);
6730 if ret == 0 { return -1; }
6731 }
6732 return c;
6733 }
6734 *(*f).wpos = c as u8;
6735 (*f).wpos = (*f).wpos.add(1);
6736 if c == (*f).lbf || (*f).wpos >= (*f).wend { let _ = flush_buf(f); }
6737 c
6738}
6739
6740#[no_mangle]
6741pub unsafe extern "C" fn puts(s: *const c_char) -> c_int {
6742 let len = strlen(s as *const c_char);
6743 let _ = fwrite(s as *const c_void, 1, len, stdout);
6744 let _ = fwrite(b"\n".as_ptr() as *const c_void, 1, 1, stdout);
6745 let f = &mut *stdout;
6746 if f.lbf >= 0 { let _ = flush_buf(stdout); }
6747 (len + 1) as c_int
6748}
6749
6750#[no_mangle]
6751pub unsafe extern "C" fn fputs(s: *const c_char, stream: *mut FILE) -> c_int {
6752 let len = strlen(s as *const c_char);
6753 fwrite(s as *const c_void, 1, len, stream) as c_int
6754}
6755
6756#[no_mangle]
6757pub unsafe extern "C" fn fputc(c: c_int, stream: *mut FILE) -> c_int {
6758 let f = &mut *stream;
6759 if f.wpos.is_null() || f.wpos >= f.wend {
6760 if __overflow(f, c) == -1 { return -1; }
6761 return c;
6762 }
6763 *f.wpos = c as u8;
6764 f.wpos = f.wpos.add(1);
6765 if c == f.lbf || f.wpos >= f.wend { let _ = flush_buf(f); }
6766 c
6767}
6768
6769#[no_mangle]
6770pub unsafe extern "C" fn putc(c: c_int, stream: *mut FILE) -> c_int { fputc(c, stream) }
6771
6772#[no_mangle]
6773pub unsafe extern "C" fn putchar(c: c_int) -> c_int { fputc(c, stdout) }
6774
6775#[no_mangle]
6776pub unsafe extern "C" fn fwrite(
6777 ptr: *const c_void, size: SizeT, nmemb: SizeT, stream: *mut FILE,
6778) -> SizeT {
6779 if size == 0 || nmemb == 0 { return 0; }
6780 let total = size * nmemb;
6781 let f = &mut *stream;
6782 if f.buf_size == 0 {
6783 if let Some(wfunc) = f.write_fn {
6784 let ret = wfunc(stream, ptr as *const u8, total);
6785 return ret / size;
6786 }
6787 return 0;
6788 }
6789 if f.wpos.is_null() {
6790 f.wbase = f.buf;
6791 f.wpos = f.buf;
6792 f.wend = f.buf.add(f.buf_size);
6793 }
6794 let mut remaining = total;
6795 let mut src = ptr as *const u8;
6796 while remaining > 0 {
6797 let space = f.wend as usize - f.wpos as usize;
6798 if space == 0 {
6799 if flush_buf(f as *mut FILE) == -1 { break; }
6800 continue;
6801 }
6802 let n = if remaining < space { remaining } else { space };
6803 core::ptr::copy_nonoverlapping(src, f.wpos, n);
6804 f.wpos = f.wpos.add(n);
6805 src = src.add(n);
6806 remaining -= n;
6807 if f.wpos >= f.wend { let _ = flush_buf(f as *mut FILE); }
6808 }
6809 if f.lbf >= 0 { let _ = flush_buf(f as *mut FILE); }
6810 (total - remaining) / size
6811}
6812
6813unsafe fn wide_to_mb(dst: *mut u8, cap: usize, src: *const wchar_t) -> usize {
6818 let mut o = 0usize;
6819 let mut i = 0usize;
6820 let mut st: c_uint = 0;
6821 while *src.add(i) != 0 {
6822 let mut tmp = [0u8; 8];
6823 let n = wcrtomb(tmp.as_mut_ptr() as *mut c_char, *src.add(i), &mut st);
6824 if n == !0usize || n == 0 { break; }
6825 if o + n > cap { break; }
6826 core::ptr::copy_nonoverlapping(tmp.as_ptr(), dst.add(o), n);
6827 o += n;
6828 i += 1;
6829 }
6830 o
6831}
6832
6833macro_rules! impl_format {
6834 ($fmt:expr, $args:expr, $write_char:expr, $write_str:expr) => {{
6835 let fmt = $fmt;
6836 let args = &mut $args;
6837 let mut count: usize = 0;
6838 let mut i = 0usize;
6839 loop {
6840 let c = *fmt.add(i) as u8;
6841 if c == 0 { break; }
6842 if c != b'%' {
6843 ($write_char)(c);
6844 count += 1; i += 1; continue;
6845 }
6846 i += 1;
6847 let mut flags: u8 = 0;
6849 loop {
6850 let fc = *fmt.add(i) as u8;
6851 match fc {
6852 b'-' => { flags |= FLAG_MINUS; i += 1; }
6853 b'+' => { flags |= FLAG_PLUS; i += 1; }
6854 b' ' => { flags |= FLAG_SPACE; i += 1; }
6855 b'0' => { flags |= FLAG_ZERO; i += 1; }
6856 b'#' => { flags |= FLAG_HASH; i += 1; }
6857 _ => break,
6858 }
6859 }
6860 let mut width: usize = 0;
6862 if *fmt.add(i) as u8 == b'*' {
6863 width = args.next_arg::<c_int>() as usize; i += 1;
6864 } else {
6865 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
6866 width = width * 10 + ((*fmt.add(i) as u8) - b'0') as usize; i += 1;
6867 }
6868 }
6869 let mut precision: i32 = -1;
6871 if *fmt.add(i) as u8 == b'.' {
6872 i += 1;
6873 if *fmt.add(i) as u8 == b'*' {
6874 precision = args.next_arg::<c_int>(); i += 1;
6875 } else {
6876 precision = 0;
6877 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
6878 precision = precision * 10 + ((*fmt.add(i) as u8) - b'0') as i32; i += 1;
6879 }
6880 }
6881 }
6882 let len_mod = *fmt.add(i) as u8;
6884 let spec: u8;
6885 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' {
6886 i += 1;
6887 let len_mod2 = *fmt.add(i) as u8;
6888 if (len_mod == b'h' && len_mod2 == b'h') || (len_mod == b'l' && len_mod2 == b'l') {
6889 i += 1;
6890 spec = *fmt.add(i) as u8;
6891 match (len_mod, len_mod2, spec) {
6893 (b'h', b'h', b'n') => {
6894 let p = args.next_arg::<*mut c_void>();
6895 if !p.is_null() { *(p as *mut u8) = count as u8; }
6896 }
6897 (b'l', b'l', b'n') => {
6898 let p = args.next_arg::<*mut c_void>();
6899 if !p.is_null() { *(p as *mut c_longlong) = count as c_longlong; }
6900 }
6901 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
6902 let val = args.next_arg::<c_longlong>();
6903 let neg = val < 0;
6904 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
6905 let b = format_u64(abs);
6906 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
6907 let mut fbuf = [0u8; 32];
6908 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
6909 ($write_str)(fbuf.as_ptr(), len); count += len;
6910 }
6911 (b'l', b'l', b'u') => {
6912 let val = args.next_arg::<c_ulonglong>();
6913 let b = format_u64(val as u64);
6914 let mut fbuf = [0u8; 32];
6915 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
6916 ($write_str)(fbuf.as_ptr(), len); count += len;
6917 }
6918 (b'l', b'l', b'o') => {
6919 let val = args.next_arg::<c_ulonglong>();
6920 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
6921 let mut fbuf = [0u8; 32];
6922 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
6923 ($write_str)(fbuf.as_ptr(), len); count += len;
6924 }
6925 (b'l', b'l', b'x') => {
6926 let val = args.next_arg::<c_ulonglong>();
6927 let b = format_hex(val as u64, false);
6928 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
6929 let mut fbuf = [0u8; 32];
6930 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6931 ($write_str)(fbuf.as_ptr(), len); count += len;
6932 }
6933 (b'l', b'l', b'X') => {
6934 let val = args.next_arg::<c_ulonglong>();
6935 let b = format_hex(val as u64, true);
6936 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
6937 let mut fbuf = [0u8; 32];
6938 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6939 ($write_str)(fbuf.as_ptr(), len); count += len;
6940 }
6941 _ => { ($write_char)(b'%'); ($write_char)(len_mod); ($write_char)(len_mod2); ($write_char)(spec); count += 4; }
6942 }
6943 } else {
6944 spec = len_mod2;
6945 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
6948 match (lm, spec) {
6949 (b'h', b'n') => {
6950 let p = args.next_arg::<*mut c_void>();
6951 if !p.is_null() { *(p as *mut u16) = count as u16; }
6952 }
6953 (b'l', b'n') => {
6954 let p = args.next_arg::<*mut c_void>();
6955 if !p.is_null() { *(p as *mut c_long) = count as c_long; }
6956 }
6957 (b'z', b'n') | (b't', b'n') => {
6958 let p = args.next_arg::<*mut c_void>();
6959 if !p.is_null() { *(p as *mut usize) = count; }
6960 }
6961 (b'j', b'n') => {
6962 let p = args.next_arg::<*mut c_void>();
6963 if !p.is_null() { *(p as *mut c_ulonglong) = count as c_ulonglong; }
6964 }
6965 (b'l', b'd') | (b'l', b'i') => {
6966 let val = args.next_arg::<c_long>();
6967 let neg = val < 0;
6968 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
6969 let b = format_u64(abs);
6970 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
6971 let mut fbuf = [0u8; 32];
6972 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
6973 ($write_str)(fbuf.as_ptr(), len); count += len;
6974 }
6975 (b'l', b'u') => {
6976 let val = args.next_arg::<c_ulong>();
6977 let b = format_u64(val as u64);
6978 let mut fbuf = [0u8; 32];
6979 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
6980 ($write_str)(fbuf.as_ptr(), len); count += len;
6981 }
6982 (b'l', b's') => {
6983 let p = args.next_arg::<*const wchar_t>();
6984 if p.is_null() {
6985 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
6986 let pad = width.saturating_sub(slen);
6987 if flags & FLAG_MINUS != 0 { ($write_str)(b"(null)".as_ptr(), slen); for _ in 0..pad { ($write_char)(b' '); } }
6988 else { for _ in 0..pad { ($write_char)(b' '); } ($write_str)(b"(null)".as_ptr(), slen); }
6989 count += slen + pad;
6990 } else {
6991 let mut mb = [0u8; 4096];
6992 let mut n = wide_to_mb(mb.as_mut_ptr(), mb.len(), p);
6993 if precision >= 0 && (precision as usize) < n { n = precision as usize; }
6994 let pad = width.saturating_sub(n);
6995 if flags & FLAG_MINUS != 0 { ($write_str)(mb.as_ptr(), n); for _ in 0..pad { ($write_char)(b' '); } }
6996 else { for _ in 0..pad { ($write_char)(b' '); } ($write_str)(mb.as_ptr(), n); }
6997 count += n + pad;
6998 }
6999 }
7000 (b'l', b'c') => {
7001 let ch = args.next_arg::<c_int>();
7002 let mut mb = [0u8; 8];
7003 let mut st: c_uint = 0;
7004 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, ch, &mut st);
7005 if n != !0usize { ($write_str)(mb.as_ptr(), n); count += n; }
7006 }
7007 (b'l', b'x') => {
7008 let val = args.next_arg::<c_ulong>();
7009 let b = format_hex(val as u64, false);
7010 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7011 let mut fbuf = [0u8; 32];
7012 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7013 ($write_str)(fbuf.as_ptr(), len); count += len;
7014 }
7015 (b'l', b'X') => {
7016 let val = args.next_arg::<c_ulong>();
7017 let b = format_hex(val as u64, true);
7018 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7019 let mut fbuf = [0u8; 32];
7020 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7021 ($write_str)(fbuf.as_ptr(), len); count += len;
7022 }
7023 (b'l', b'o') => {
7024 let val = args.next_arg::<c_ulong>();
7025 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
7026 let mut fbuf = [0u8; 32];
7027 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7028 ($write_str)(fbuf.as_ptr(), len); count += len;
7029 }
7030 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
7031 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
7032 let val = args.next_arg::<f64>();
7033 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7034 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7035 let mut fbuf = [0u8; 4224];
7036 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7037 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
7038 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
7039 ($write_str)(fbuf.as_ptr(), total); count += total;
7040 }
7041 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
7042 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
7043 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
7044 let val = {
7045 let lo: u64 = args.next_arg::<u64>();
7046 let hi: u64 = args.next_arg::<u64>();
7047 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
7048 f128::from_bits(combined) as f64
7049 };
7050 #[cfg(target_arch = "x86_64")]
7051 let val = args.next_arg::<f64>();
7052 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7053 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7054 let mut fbuf = [0u8; 4224];
7055 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7056 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
7057 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
7058 ($write_str)(fbuf.as_ptr(), total); count += total;
7059 }
7060 _ => { ($write_char)(b'%'); ($write_char)(len_mod); ($write_char)(spec); count += 3; }
7061 }
7062 }
7063 } else {
7064 spec = *fmt.add(i) as u8;
7065 match spec {
7066 b's' => {
7067 let s = args.next_arg::<*const c_char>();
7068 if s.is_null() {
7069 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
7070 let padded_len = if width > slen { width } else { slen };
7071 let pad = padded_len - slen;
7072 if flags & FLAG_MINUS != 0 {
7073 ($write_str)(b"(null)".as_ptr(), slen);
7074 for _ in 0..pad { ($write_char)(b' '); }
7075 } else {
7076 for _ in 0..pad { ($write_char)(b' '); }
7077 ($write_str)(b"(null)".as_ptr(), slen);
7078 }
7079 count += padded_len;
7080 } else {
7081 let full_len = strlen(s as *const c_char);
7082 let slen = if precision >= 0 { (precision as usize).min(full_len) } else { full_len };
7083 let padded_len = if width > slen { width } else { slen };
7084 let pad = padded_len - slen;
7085 if flags & FLAG_MINUS != 0 {
7086 ($write_str)(s as *const u8, slen);
7087 for _ in 0..pad { ($write_char)(b' '); }
7088 } else {
7089 for _ in 0..pad { ($write_char)(b' '); }
7090 ($write_str)(s as *const u8, slen);
7091 }
7092 count += padded_len;
7093 }
7094 }
7095 b'd' | b'i' => {
7096 let d = args.next_arg::<c_int>();
7097 let neg = d < 0;
7098 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
7099 let b = format_u64(abs);
7100 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7101 let mut fbuf = [0u8; 32];
7102 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7103 ($write_str)(fbuf.as_ptr(), len); count += len;
7104 }
7105 b'u' => {
7106 let u = args.next_arg::<c_uint>();
7107 let b = format_u64(u as u64);
7108 let mut fbuf = [0u8; 32];
7109 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7110 ($write_str)(fbuf.as_ptr(), len); count += len;
7111 }
7112 b'x' => {
7113 let x = args.next_arg::<c_uint>();
7114 let b = format_hex(x as u64, false);
7115 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7116 let mut fbuf = [0u8; 32];
7117 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7118 ($write_str)(fbuf.as_ptr(), len); count += len;
7119 }
7120 b'X' => {
7121 let x = args.next_arg::<c_uint>();
7122 let b = format_hex(x as u64, true);
7123 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7124 let mut fbuf = [0u8; 32];
7125 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7126 ($write_str)(fbuf.as_ptr(), len); count += len;
7127 }
7128 b'o' => {
7129 let o = args.next_arg::<c_uint>();
7130 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
7131 let mut fbuf = [0u8; 32];
7132 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7133 ($write_str)(fbuf.as_ptr(), len); count += len;
7134 }
7135 b'c' => {
7136 let ch = args.next_arg::<c_int>();
7137 if width > 1 {
7138 let pad = width - 1;
7139 if flags & FLAG_MINUS != 0 {
7140 ($write_char)(ch as u8); count += 1;
7141 for _ in 0..pad { ($write_char)(b' '); count += 1; }
7142 } else {
7143 for _ in 0..pad { ($write_char)(b' '); count += 1; }
7144 ($write_char)(ch as u8); count += 1;
7145 }
7146 } else {
7147 ($write_char)(ch as u8); count += 1;
7148 }
7149 }
7150 b'p' => {
7151 let p = args.next_arg::<*const c_void>();
7152 let mut fbuf = [0u8; 20];
7153 fbuf[0] = b'0'; fbuf[1] = b'x';
7154 let b = format_hex(p as u64, false);
7155 core::ptr::copy_nonoverlapping(b.0.as_ptr(), fbuf.as_mut_ptr().add(2), b.1);
7156 ($write_str)(fbuf.as_ptr(), b.1 + 2); count += b.1 + 2;
7157 }
7158 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
7159 let val = args.next_arg::<f64>();
7160 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7161 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7162 let mut fbuf = [0u8; 4224];
7163 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7164 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
7165 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
7166 ($write_str)(fbuf.as_ptr(), total); count += total;
7167 }
7168 b'%' => { ($write_char)(b'%'); count += 1; }
7169 b'n' => {
7170 let p = args.next_arg::<*mut c_void>();
7171 if !p.is_null() { *(p as *mut c_int) = count as c_int; }
7172 }
7173 _ => { ($write_char)(b'%'); ($write_char)(spec); count += 2; }
7174 }
7175 }
7176 i += 1;
7177 }
7178 count as c_int
7179 }};
7180}
7181
7182unsafe fn format_u64(mut val: u64) -> ([u8; 20], usize) {
7183 let mut buf = [0u8; 20];
7184 if val == 0 { buf[0] = b'0'; return (buf, 1); }
7185 let mut tmp = [0u8; 20];
7186 let mut pos = 20;
7187 while val > 0 { pos -= 1; tmp[pos] = b'0' + (val % 10) as u8; val /= 10; }
7188 let len = 20 - pos;
7189 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7190 (buf, len)
7191}
7192
7193unsafe fn format_i64(val: i64) -> ([u8; 21], usize) {
7194 let mut buf = [0u8; 21];
7195 if val < 0 {
7196 buf[0] = b'-';
7197 let (inner, len) = format_u64((-(val as i128)) as u64);
7198 core::ptr::copy_nonoverlapping(inner.as_ptr(), buf.as_mut_ptr().add(1), len);
7199 (buf, len + 1)
7200 } else {
7201 let (inner, len) = format_u64(val as u64);
7202 core::ptr::copy_nonoverlapping(inner.as_ptr(), buf.as_mut_ptr(), len);
7203 (buf, len)
7204 }
7205}
7206
7207unsafe fn format_hex(mut val: u64, uppercase: bool) -> ([u8; 16], usize) {
7208 let digits = if uppercase { b"0123456789ABCDEF" } else { b"0123456789abcdef" };
7209 let mut buf = [0u8; 16];
7210 if val == 0 { buf[0] = b'0'; return (buf, 1); }
7211 let mut tmp = [0u8; 16];
7212 let mut pos = 16;
7213 while val > 0 { pos -= 1; tmp[pos] = digits[(val & 0xf) as usize]; val >>= 4; }
7214 let len = 16 - pos;
7215 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7216 (buf, len)
7217}
7218
7219unsafe fn format_octal(mut val: u64, alt: bool) -> ([u8; 24], usize) {
7220 let mut buf = [0u8; 24];
7221 if val == 0 {
7222 buf[0] = b'0';
7223 return (buf, 1);
7224 }
7225 let mut tmp = [0u8; 24];
7226 let mut pos = 24;
7227 while val > 0 {
7228 pos -= 1;
7229 tmp[pos] = b'0' + (val & 7) as u8;
7230 val >>= 3;
7231 }
7232 let len = 24 - pos;
7233 if alt {
7234 tmp[pos - 1] = b'0';
7235 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos - 1), buf.as_mut_ptr(), len + 1);
7236 (buf, len + 1)
7237 } else {
7238 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7239 (buf, len)
7240 }
7241}
7242
7243unsafe fn format_int(
7244 dst: *mut u8,
7245 digits: *const u8,
7246 digits_len: usize,
7247 sign: Option<u8>,
7248 prefix: Option<u8>,
7249 precision: i32,
7250 width: usize,
7251 flags: u8,
7252 octal_alt: bool,
7253) -> usize {
7254 let num_digits = if precision == 0 && digits_len == 1 && *digits == b'0' && !octal_alt {
7255 0
7256 } else {
7257 digits_len
7258 };
7259 let prec = precision as usize;
7260 let zero_pad = if precision >= 0 && prec > num_digits { prec - num_digits } else { 0 };
7261
7262 let sign_len = sign.map_or(0, |_| 1);
7263 let prefix_len = prefix.map_or(0, |_| 2);
7264 let content_len = sign_len + prefix_len + zero_pad + num_digits;
7265
7266 let mut buf = [0u8; 32];
7267 let mut pos = 0usize;
7268 if let Some(c) = sign { buf[pos] = c; pos += 1; }
7269 if let Some(c) = prefix { buf[pos] = b'0'; pos += 1; buf[pos] = c; pos += 1; }
7270 for _ in 0..zero_pad { buf[pos] = b'0'; pos += 1; }
7271 if num_digits > 0 {
7272 core::ptr::copy_nonoverlapping(digits, buf.as_mut_ptr().add(pos), num_digits);
7273 }
7274
7275 if content_len >= width {
7276 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, content_len);
7277 return content_len;
7278 }
7279 let pad = width - content_len;
7280 if flags & FLAG_MINUS != 0 {
7281 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, content_len);
7282 for i in 0..pad { *dst.add(content_len + i) = b' '; }
7283 } else if flags & FLAG_ZERO != 0 && precision < 0 {
7284 let fixed = sign_len + prefix_len;
7285 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, fixed);
7286 for i in fixed..width - num_digits { *dst.add(i) = b'0'; }
7287 if num_digits > 0 {
7288 core::ptr::copy_nonoverlapping(digits, dst.add(width - num_digits), num_digits);
7289 }
7290 } else {
7291 for i in 0..pad { *dst.add(i) = b' '; }
7292 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst.add(pad), content_len);
7293 }
7294 width
7295}
7296
7297unsafe fn format_f64(val: f64) -> ([u8; 64], usize) {
7298 let mut buf = [0u8; 64];
7299 let mut pos = 0usize;
7300 let mut v = val;
7301 if v.is_nan() {
7302 let nan = b"nan";
7303 core::ptr::copy_nonoverlapping(nan.as_ptr(), buf.as_mut_ptr(), 3);
7304 return (buf, 3);
7305 }
7306 if v < 0.0 { buf[pos] = b'-'; pos += 1; v = -v; }
7307 if v.is_infinite() {
7308 let inf = b"inf";
7309 core::ptr::copy_nonoverlapping(inf.as_ptr(), buf.as_mut_ptr().add(pos), 3);
7310 return (buf, pos + 3);
7311 }
7312 let int_part = v as u64;
7313 let frac = v - int_part as f64;
7314 let (ibuf, ilen) = format_u64(int_part);
7315 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), buf.as_mut_ptr().add(pos), ilen);
7316 pos += ilen;
7317 buf[pos] = b'.';
7318 pos += 1;
7319 let mut f = frac;
7320 for _ in 0..6 { f *= 10.0; let digit = f as u8; buf[pos] = b'0' + digit; pos += 1; f -= digit as f64; }
7321 (buf, pos)
7322}
7323
7324const FMT_F: u8 = 0;
7326const FMT_E: u8 = 1;
7327const FMT_G: u8 = 2;
7328const FMT_A: u8 = 3;
7329
7330const FLAG_HASH: u8 = 1;
7331const FLAG_PLUS: u8 = 2;
7332const FLAG_SPACE: u8 = 4;
7333const FLAG_ZERO: u8 = 8;
7334const FLAG_MINUS: u8 = 16;
7335
7336unsafe fn bigint_to_decimal(buf: *mut u8, mant: u64, shift: u32) -> usize {
7341 let nlimbs = (2 + (shift + 31) / 32) as usize;
7343 let mut limbs = [0u32; 36];
7344 limbs[0] = mant as u32;
7345 limbs[1] = (mant >> 32) as u32;
7346
7347 let ws = (shift / 32) as usize;
7348 let bs = shift % 32;
7349
7350 if ws > 0 {
7352 let mut i = 1usize;
7353 loop {
7354 limbs[i + ws] = limbs[i];
7355 if i == 0 { break; }
7356 i -= 1;
7357 }
7358 for j in 0..ws { limbs[j] = 0; }
7359 }
7360 if bs > 0 {
7362 let mut carry = 0u32;
7363 let end = nlimbs.min(ws + 3);
7364 for i in ws..end {
7365 let new_val = (limbs[i] << bs) | carry;
7366 carry = limbs[i] >> (32 - bs);
7367 limbs[i] = new_val;
7368 }
7369 }
7370
7371 let mut used = nlimbs;
7373 while used > 0 && limbs[used - 1] == 0 { used -= 1; }
7374 if used == 0 { *buf = b'0'; return 1; }
7375
7376 let mut digits = [0u8; 400];
7378 let mut nd = 0usize;
7379 loop {
7380 let mut all_zero = true;
7381 for i in 0..used { if limbs[i] != 0 { all_zero = false; break; } }
7382 if all_zero { break; }
7383 let mut rem = 0u64;
7384 for i in (0..used).rev() {
7385 let val = (rem << 32) | limbs[i] as u64;
7386 limbs[i] = (val / 10) as u32;
7387 rem = val % 10;
7388 }
7389 digits[nd] = rem as u8;
7390 nd += 1;
7391 }
7392 for i in 0..nd { *buf.add(i) = b'0' + digits[nd - 1 - i]; }
7394 nd
7395}
7396
7397unsafe fn frac_digits_u128(buf: *mut u8, frac_bits: u64, shift: u32, count: usize) -> bool {
7400 let mask: u128 = (1u128 << shift) - 1;
7401 let mut rem = frac_bits as u128;
7402 for i in 0..count {
7403 rem *= 10;
7404 let digit = (rem >> shift) as u8;
7405 rem &= mask;
7406 *buf.add(i) = digit;
7407 }
7408 rem != 0
7409}
7410
7411unsafe fn frac_digits_bigint(buf: *mut u8, frac_bits: u64, shift: u32, count: usize) -> bool {
7414 let nlimbs = ((shift + 31) / 32) as usize;
7415 let mut rem = [0u32; 36]; rem[0] = frac_bits as u32;
7417 if nlimbs > 1 { rem[1] = (frac_bits >> 32) as u32; }
7418 let hi_word = (shift / 32) as usize;
7420 let hi_bit = shift % 32;
7421 if hi_bit > 0 && hi_word < nlimbs {
7422 rem[hi_word] &= (1u32 << hi_bit) - 1;
7423 }
7424 let clear_from = if hi_bit > 0 { hi_word + 1 } else { hi_word };
7426 for j in clear_from..nlimbs { rem[j] = 0; }
7427
7428 for i in 0..count {
7429 let mut carry = 0u64;
7431 for j in 0..nlimbs {
7432 let val = rem[j] as u64 * 10 + carry;
7433 rem[j] = val as u32;
7434 carry = val >> 32;
7435 }
7436 let digit: u32;
7438 if hi_bit == 0 {
7439 digit = if hi_word < nlimbs { rem[hi_word] } else { carry as u32 };
7440 } else {
7441 let mut d = if hi_word < nlimbs { rem[hi_word] >> hi_bit } else { 0 };
7442 if hi_word + 1 < nlimbs {
7443 d |= rem[hi_word + 1] << (32 - hi_bit);
7444 } else if carry > 0 {
7445 d |= (carry as u32) << (32 - hi_bit);
7446 }
7447 digit = d;
7448 }
7449 *buf.add(i) = digit.min(9) as u8;
7450 if hi_bit == 0 {
7452 if hi_word < nlimbs { rem[hi_word] = 0; }
7453 } else {
7454 if hi_word < nlimbs {
7455 rem[hi_word] &= (1u32 << hi_bit) - 1;
7456 }
7457 for j in (hi_word + 1)..nlimbs { rem[j] = 0; }
7458 }
7459 }
7460 for i in 0..nlimbs { if rem[i] != 0 { return true; } }
7462 false
7463}
7464
7465unsafe fn increment_decimal(buf: *mut u8, len: &mut usize) {
7467 let mut j = *len;
7468 loop {
7469 if j == 0 {
7470 let l = *len;
7472 for i in (0..l).rev() { *buf.add(i + 1) = *buf.add(i); }
7473 *buf = b'1';
7474 *len = l + 1;
7475 return;
7476 }
7477 j -= 1;
7478 let d = *buf.add(j);
7479 if d < b'9' { *buf.add(j) = d + 1; return; }
7480 *buf.add(j) = b'0';
7481 }
7482}
7483
7484unsafe fn format_f64_full(
7486 dst: *mut u8, val: f64, fmt_type: u8, precision: i32, flags: u8, uppercase: bool,
7487) -> usize {
7488 let mut pos = 0usize;
7489
7490 if val.is_nan() {
7492 let nan_s: &[u8] = if uppercase { b"NAN" } else { b"nan" };
7493 core::ptr::copy_nonoverlapping(nan_s.as_ptr(), dst, 3);
7494 return 3;
7495 }
7496 let neg = val.is_sign_negative();
7497 let v = if neg { -val } else { val };
7498
7499 if v.is_infinite() {
7501 if neg { *dst.add(pos) = b'-'; pos += 1; }
7502 else if flags & FLAG_PLUS != 0 { *dst.add(pos) = b'+'; pos += 1; }
7503 else if flags & FLAG_SPACE != 0 { *dst.add(pos) = b' '; pos += 1; }
7504 let inf_s: &[u8] = if uppercase { b"INF" } else { b"inf" };
7505 core::ptr::copy_nonoverlapping(inf_s.as_ptr(), dst.add(pos), 3);
7506 return pos + 3;
7507 }
7508
7509 if neg { *dst.add(pos) = b'-'; pos += 1; }
7511 else if flags & FLAG_PLUS != 0 { *dst.add(pos) = b'+'; pos += 1; }
7512 else if flags & FLAG_SPACE != 0 { *dst.add(pos) = b' '; pos += 1; }
7513
7514 if fmt_type == FMT_A {
7516 return pos + fmt_hex_float(dst.add(pos), val, precision, flags, uppercase);
7517 }
7518
7519 let p: usize;
7521 let mut exp: i32;
7522 let use_f: bool;
7523
7524 match fmt_type {
7525 FMT_G => {
7526 let gp = if precision < 0 { 6usize } else if precision == 0 { 1usize } else { precision as usize };
7527 exp = if v > 0.0 { compute_exp10(v) } else { 0 };
7528 use_f = exp >= -4 && exp < gp as i32;
7529 if use_f {
7530 p = if exp < 0 { gp + ((-exp) as usize - 1) }
7531 else if (exp as usize) < gp { gp - exp as usize - 1 }
7532 else { 0 };
7533 } else {
7534 p = gp - 1;
7535 }
7536 }
7537 FMT_E => {
7538 p = if precision < 0 { 6usize } else { precision as usize };
7539 exp = if v > 0.0 { compute_exp10(v) } else { 0 };
7540 use_f = false;
7541 }
7542 _ => {
7543 p = if precision < 0 { 6usize } else { precision as usize };
7544 exp = 0;
7545 use_f = true;
7546 }
7547 }
7548
7549 if v == 0.0 {
7550 *dst.add(pos) = b'0'; pos += 1;
7551 if !(fmt_type == FMT_G && flags & FLAG_HASH == 0) {
7552 if p > 0 || flags & FLAG_HASH != 0 {
7553 *dst.add(pos) = b'.'; pos += 1;
7554 for _ in 0..p { *dst.add(pos) = b'0'; pos += 1; }
7555 }
7556 }
7557 if !use_f {
7558 let ec = if uppercase { b'E' } else { b'e' };
7559 *dst.add(pos) = ec; pos += 1;
7560 *dst.add(pos) = b'+'; pos += 1;
7561 *dst.add(pos) = b'0'; pos += 1;
7562 *dst.add(pos) = b'0'; pos += 1;
7563 }
7564 return pos;
7565 }
7566
7567 if use_f {
7569 let bits = v.to_bits();
7570 let raw_mant = bits & 0x000FFFFFFFFFFFFF;
7571 let raw_exp_bits = ((bits >> 52) & 0x7FF) as i32;
7572 let (mant_b, bin_exp) = if raw_exp_bits == 0 {
7573 (raw_mant, -1022i32)
7574 } else {
7575 (raw_mant | (1u64 << 52), raw_exp_bits - 1023)
7576 };
7577
7578 let mut ibuf = [0u8; 400];
7580 let mut ilen: usize;
7581 if bin_exp < 0 {
7582 ibuf[0] = b'0'; ilen = 1;
7583 } else if bin_exp <= 63 {
7584 let int_val = if bin_exp <= 52 { mant_b >> (52 - bin_exp) }
7585 else { mant_b << (bin_exp - 52) };
7586 let (buf2, len2) = format_u64(int_val);
7587 ibuf[..len2].copy_from_slice(&buf2[..len2]);
7588 ilen = len2;
7589 } else {
7590 ilen = bigint_to_decimal(ibuf.as_mut_ptr(), mant_b, (bin_exp - 52) as u32);
7591 }
7592
7593 let mut fbuf = [0u8; 1100];
7595 let mut has_rest = false;
7596 if p > 0 && bin_exp < 52 {
7597 let shift = (52 - bin_exp) as u32;
7598 let frac_bits = if bin_exp >= 0 { mant_b & ((1u64 << shift) - 1) } else { mant_b };
7599 if shift <= 124 {
7600 has_rest = frac_digits_u128(fbuf.as_mut_ptr(), frac_bits, shift, p + 1);
7601 } else {
7602 has_rest = frac_digits_bigint(fbuf.as_mut_ptr(), frac_bits, shift, p + 1);
7603 }
7604 }
7605
7606 if p > 0 && bin_exp < 52 {
7608 let next_d = fbuf[p];
7609 let last_d = fbuf[p - 1];
7610 if next_d > 5 || (next_d == 5 && (has_rest || last_d & 1 != 0)) {
7611 let mut carry = true;
7612 for j in (0..p).rev() {
7613 if !carry { break; }
7614 fbuf[j] += 1;
7615 if fbuf[j] < 10 { carry = false; break; }
7616 fbuf[j] = 0;
7617 }
7618 if carry { increment_decimal(ibuf.as_mut_ptr(), &mut ilen); }
7619 }
7620 } else if p == 0 {
7621 if bin_exp >= 0 && bin_exp < 52 {
7623 let shift = (52 - bin_exp) as u32;
7624 let frac_bits = mant_b & ((1u64 << shift) - 1);
7625 let half = 1u64 << (shift - 1);
7626 let last_d = ibuf[ilen - 1] - b'0';
7627 if frac_bits > half || (frac_bits == half && last_d & 1 != 0) {
7628 increment_decimal(ibuf.as_mut_ptr(), &mut ilen);
7629 }
7630 }
7631 }
7632
7633 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), dst.add(pos), ilen);
7635 pos += ilen;
7636 if p > 0 || flags & FLAG_HASH != 0 {
7637 *dst.add(pos) = b'.'; pos += 1;
7638 for i in 0..p { *dst.add(pos) = b'0' + fbuf[i]; pos += 1; }
7639 }
7640 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7641 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7642 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7643 }
7644 return pos;
7645 }
7646
7647 let mut fbuf = [0u8; 20];
7650 let mut int_part: u64;
7651 {
7652 let bits_v = v.to_bits();
7653 let raw_mant_v = bits_v & 0x000FFFFFFFFFFFFF;
7654 let raw_exp_v = ((bits_v >> 52) & 0x7FF) as i32;
7655 let (mant_b_v, bin_exp_v) = if raw_exp_v == 0 {
7656 (raw_mant_v, -1022i32)
7657 } else {
7658 (raw_mant_v | (1u64 << 52), raw_exp_v - 1023)
7659 };
7660
7661 let s: i32 = (p as i32) + 1 - exp;
7662 let bs: i32 = bin_exp_v - 52 + s;
7663
7664 let mut limbs = [0u32; 40];
7665 limbs[0] = mant_b_v as u32;
7666 limbs[1] = (mant_b_v >> 32) as u32;
7667 let mut nlimbs: usize = if limbs[1] != 0 { 2 } else { 1 };
7668
7669 if s > 0 {
7670 for _ in 0..(s as usize) {
7671 let mut carry = 0u64;
7672 for j in 0..nlimbs {
7673 let val = limbs[j] as u64 * 5 + carry;
7674 limbs[j] = val as u32;
7675 carry = val >> 32;
7676 }
7677 if carry > 0 { limbs[nlimbs] = carry as u32; nlimbs += 1; }
7678 }
7679 }
7680
7681 if bs > 0 {
7682 let ws = (bs as u32 / 32) as usize;
7683 let bit = bs as u32 % 32;
7684 if ws > 0 {
7685 let mut i = nlimbs;
7686 while i > 0 { i -= 1; if i + ws < 40 { limbs[i + ws] = limbs[i]; } limbs[i] = 0; }
7687 nlimbs += ws;
7688 }
7689 if bit > 0 {
7690 let mut carry = 0u32;
7691 for i in ws..nlimbs {
7692 let new_val = (limbs[i] << bit) | carry;
7693 carry = limbs[i] >> (32 - bit);
7694 limbs[i] = new_val;
7695 }
7696 if carry > 0 && nlimbs < 40 { limbs[nlimbs] = carry; nlimbs += 1; }
7697 }
7698 }
7699
7700 let mut has_rest = false;
7701 if s < 0 {
7702 for _ in 0..(-s as usize) {
7703 let mut rem = 0u64;
7704 for i in (0..nlimbs).rev() {
7705 let val = (rem << 32) | limbs[i] as u64;
7706 limbs[i] = (val / 5) as u32;
7707 rem = val % 5;
7708 }
7709 if rem != 0 { has_rest = true; }
7710 }
7711 }
7712
7713 if bs < 0 {
7714 let rshift = (-bs) as u32;
7715 let ws = (rshift / 32) as usize;
7716 let bit = rshift % 32;
7717 if ws > 0 {
7718 for j in 0..ws.min(nlimbs) { if limbs[j] != 0 { has_rest = true; } }
7719 for i in ws..nlimbs { limbs[i - ws] = limbs[i]; }
7720 nlimbs = nlimbs.saturating_sub(ws);
7721 }
7722 if bit > 0 && nlimbs > 0 {
7723 let mask = (1u32 << bit) - 1;
7724 if limbs[0] & mask != 0 { has_rest = true; }
7725 for i in 0..nlimbs - 1 {
7726 limbs[i] = (limbs[i] >> bit) | (limbs[i + 1] << (32 - bit));
7727 }
7728 limbs[nlimbs - 1] >>= bit;
7729 }
7730 }
7731
7732 while nlimbs > 0 && limbs[nlimbs - 1] == 0 { nlimbs -= 1; }
7733
7734 let ndigits = p + 2;
7735 let mut all_digits = [0u8; 25];
7736 let mut nd = 0usize;
7737 if nlimbs > 0 {
7738 loop {
7739 let mut all_zero = true;
7740 for i in 0..nlimbs { if limbs[i] != 0 { all_zero = false; break; } }
7741 if all_zero { break; }
7742 let mut rem64 = 0u64;
7743 for i in (0..nlimbs).rev() {
7744 let val = (rem64 << 32) | limbs[i] as u64;
7745 limbs[i] = (val / 10) as u32;
7746 rem64 = val % 10;
7747 }
7748 if nd < 25 { all_digits[nd] = rem64 as u8; }
7749 nd += 1;
7750 }
7751 }
7752
7753 if nd >= ndigits {
7754 for i in 0..ndigits { fbuf[ndigits - 1 - i] = all_digits[i]; }
7755 } else {
7756 for i in 0..nd { fbuf[ndigits - 1 - i] = all_digits[i]; }
7757 for i in nd..ndigits { fbuf[ndigits - 1 - i] = 0; }
7758 }
7759
7760 int_part = fbuf[0] as u64;
7761
7762 if p > 0 {
7764 let next_d = fbuf[p + 1];
7765 let last_d = fbuf[p];
7766 if next_d > 5 || (next_d == 5 && (has_rest || last_d & 1 != 0)) {
7767 let mut carry = true;
7768 for j in (1..=p).rev() {
7769 if !carry { break; }
7770 let d = fbuf[j] + 1;
7771 if d < 10 { fbuf[j] = d; carry = false; break; }
7772 fbuf[j] = 0;
7773 }
7774 if carry { int_part += 1; }
7775 }
7776 } else {
7777 let next_d = fbuf[1];
7778 if next_d > 5 || (next_d == 5 && (has_rest || int_part & 1 != 0)) {
7779 int_part += 1;
7780 }
7781 }
7782
7783 for i in 0..p { fbuf[i] = fbuf[i + 1]; }
7786 }
7787
7788 if !use_f && int_part >= 10 {
7789 exp += 1;
7790 int_part = 1;
7791 }
7792
7793 if use_f {
7795 let (ibuf, ilen) = format_u64(int_part);
7797 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), dst.add(pos), ilen);
7798 pos += ilen;
7799 if p > 0 || flags & FLAG_HASH != 0 {
7800 *dst.add(pos) = b'.'; pos += 1;
7801 for idx in 0..p { *dst.add(pos) = b'0' + fbuf[idx]; pos += 1; }
7802 }
7803 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7804 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7805 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7806 }
7807 } else {
7808 *dst.add(pos) = b'0' + int_part as u8; pos += 1;
7810 if p > 0 || flags & FLAG_HASH != 0 {
7811 *dst.add(pos) = b'.'; pos += 1;
7812 for idx in 0..p { *dst.add(pos) = b'0' + fbuf[idx]; pos += 1; }
7813 }
7814 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7815 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7816 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7817 }
7818 let ec = if uppercase { b'E' } else { b'e' };
7819 *dst.add(pos) = ec; pos += 1;
7820 *dst.add(pos) = if exp < 0 { b'-' } else { b'+' }; pos += 1;
7821 let eabs = if exp < 0 { (-exp) as u32 } else { exp as u32 };
7822 if eabs < 10 { *dst.add(pos) = b'0'; pos += 1; }
7823 let (ebuf, elen) = format_u64(eabs as u64);
7824 core::ptr::copy_nonoverlapping(ebuf.as_ptr(), dst.add(pos), elen);
7825 pos += elen;
7826 }
7827
7828 pos
7829}
7830
7831unsafe fn compute_exp10(v: f64) -> i32 {
7833 let e = libm::floor(libm::log10(v)) as i32;
7834 let probe = v / libm::pow(10.0, e as f64);
7835 if probe >= 10.0 { e + 1 }
7836 else if probe < 1.0 { e - 1 }
7837 else { e }
7838}
7839
7840unsafe fn fmt_hex_float(dst: *mut u8, val: f64, precision: i32, _flags: u8, uppercase: bool) -> usize {
7842 if val.to_bits() & 0x7FFFFFFFFFFFFFFF == 0 {
7844 let lc = !uppercase;
7845 let pfx: &[u8] = if lc { b"0x" } else { b"0X" };
7846 let p = if precision < 0 { 0usize } else { precision as usize };
7847 let mut pos = 0usize;
7848 core::ptr::copy_nonoverlapping(pfx.as_ptr(), dst.add(pos), 2); pos += 2;
7849 *dst.add(pos) = b'0'; pos += 1;
7850 if p > 0 {
7851 *dst.add(pos) = b'.'; pos += 1;
7852 for _ in 0..p { *dst.add(pos) = b'0'; pos += 1; }
7853 }
7854 let pc = if lc { b'p' } else { b'P' };
7855 *dst.add(pos) = pc; pos += 1;
7856 *dst.add(pos) = b'+'; pos += 1;
7857 *dst.add(pos) = b'0'; pos += 1;
7858 return pos;
7859 }
7860 let bits = val.to_bits();
7861 let exp_bits = ((bits >> 52) & 0x7FF) as i32;
7862 let mant_bits = bits & 0x000FFFFFFFFFFFFF;
7863 let (mut e, mut m) = if exp_bits == 0 { (1 - 1023, mant_bits) } else { (exp_bits - 1023, mant_bits | (1u64 << 52)) };
7864 if exp_bits == 0 && m != 0 {
7867 let shift = m.leading_zeros() as i32 - 11;
7868 m <<= shift;
7869 e -= shift;
7870 }
7871 let explicit = precision >= 0;
7872 let p = if explicit { precision as usize } else { 13usize };
7873 let mut pos = 0usize;
7874 let lc = !uppercase;
7875 let pfx: &[u8] = if lc { b"0x" } else { b"0X" };
7876 core::ptr::copy_nonoverlapping(pfx.as_ptr(), dst.add(pos), 2); pos += 2;
7877
7878 let lead_pos = pos;
7880 let mut lead = ((m >> 52) & 0xF) as u8;
7881 *dst.add(pos) = hex_digit_char(lead, lc); pos += 1;
7882 let mut frac_start = pos;
7883 if p > 0 {
7884 *dst.add(pos) = b'.'; pos += 1;
7885 frac_start = pos;
7886 }
7887
7888 let mut rm = m;
7890 for _ in 0..p {
7891 let nib = ((rm >> 48) & 0xF) as u8;
7892 *dst.add(pos) = hex_digit_char(nib, lc); pos += 1;
7893 rm <<= 4;
7894 }
7895
7896 let round_nib = ((rm >> 48) & 0xF) as u8;
7898 let rest = rm & 0x0000FFFFFFFFFFFF;
7899 let last_nib = if p > 0 {
7900 hex_char_val(*dst.add(pos - 1))
7901 } else {
7902 lead
7903 };
7904 let should_round = round_nib > 8 || (round_nib == 8 && (rest != 0 || (last_nib & 1) != 0));
7905 if should_round {
7906 let mut j = pos;
7907 loop {
7908 if j == frac_start {
7909 lead += 1;
7911 *dst.add(lead_pos) = hex_digit_char(lead, lc);
7912 break;
7913 }
7914 j -= 1;
7915 let v = hex_char_val(*dst.add(j));
7916 if v < 15 {
7917 *dst.add(j) = hex_digit_char(v + 1, lc);
7918 break;
7919 }
7920 *dst.add(j) = b'0';
7921 }
7922 }
7923
7924 if !explicit {
7927 while pos > frac_start && *dst.add(pos - 1) == b'0' {
7928 pos -= 1;
7929 }
7930 if pos == frac_start {
7931 pos = frac_start - 1;
7932 }
7933 }
7934
7935 let pc = if lc { b'p' } else { b'P' };
7937 *dst.add(pos) = pc; pos += 1;
7938 *dst.add(pos) = if e < 0 { b'-' } else { b'+' }; pos += 1;
7939 let eabs = if e < 0 { (-e) as u32 } else { e as u32 };
7940 let (ebuf, elen) = format_u64(eabs as u64);
7941 core::ptr::copy_nonoverlapping(ebuf.as_ptr(), dst.add(pos), elen);
7942 pos += elen;
7943 pos
7944}
7945
7946#[inline]
7947fn hex_digit_char(v: u8, lowercase: bool) -> u8 {
7948 if v < 10 { b'0' + v }
7949 else if lowercase { b'a' + v - 10 }
7950 else { b'A' + v - 10 }
7951}
7952
7953#[inline]
7954fn hex_char_val(c: u8) -> u8 {
7955 if c >= b'0' && c <= b'9' { c - b'0' }
7956 else if c >= b'a' && c <= b'f' { c - b'a' + 10 }
7957 else if c >= b'A' && c <= b'F' { c - b'A' + 10 }
7958 else { 0 }
7959}
7960
7961unsafe fn apply_width_flags(
7964 dst: *mut u8, buf: *const u8, len: usize, width: usize, flags: u8,
7965) -> usize {
7966 if len >= width {
7967 core::ptr::copy_nonoverlapping(buf, dst, len);
7968 return len;
7969 }
7970 let pad = width - len;
7971 let pad_char = if flags & FLAG_ZERO != 0 && flags & FLAG_MINUS == 0 { b'0' } else { b' ' };
7972 if flags & FLAG_MINUS != 0 {
7973 core::ptr::copy_nonoverlapping(buf, dst, len);
7975 for i in 0..pad { *dst.add(len + i) = pad_char; }
7976 } else {
7977 if flags & FLAG_ZERO != 0 && len > 0 {
7980 let first = *buf;
7981 if first == b'-' || first == b'+' || first == b' ' {
7982 *dst = first;
7983 for i in 0..pad { *dst.add(1 + i) = pad_char; }
7984 core::ptr::copy_nonoverlapping(buf.add(1), dst.add(1 + pad), len - 1);
7985 return width;
7986 }
7987 }
7988 for i in 0..pad { *dst.add(i) = pad_char; }
7989 core::ptr::copy_nonoverlapping(buf, dst.add(pad), len);
7990 }
7991 width
7992}
7993
7994#[no_mangle]
7995pub unsafe extern "C" fn vprintf(fmt: *const c_char, mut args: VaList) -> c_int {
7996 impl_format!(fmt, args,
7997 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stdout); },
7998 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stdout); }
7999 )
8000}
8001
8002#[no_mangle]
8003pub unsafe extern "C" fn vfprintf(stream: *mut FILE, fmt: *const c_char, mut args: VaList) -> c_int {
8004 impl_format!(fmt, args,
8005 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stream); },
8006 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stream); }
8007 )
8008}
8009
8010#[no_mangle]
8011pub unsafe extern "C" fn printf(fmt: *const c_char, mut args: ...) -> c_int {
8012 impl_format!(fmt, args,
8013 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stdout); },
8014 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stdout); }
8015 )
8016}
8017
8018#[no_mangle]
8019pub unsafe extern "C" fn fprintf(stream: *mut FILE, fmt: *const c_char, mut args: ...) -> c_int {
8020 impl_format!(fmt, args,
8021 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stream); },
8022 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stream); }
8023 )
8024}
8025
8026#[no_mangle]
8027pub unsafe extern "C" fn dprintf(fd: c_int, fmt: *const c_char, mut args: ...) -> c_int {
8028 impl_format!(fmt, args,
8029 |c: u8| { write_str(fd, &c as *const u8, 1); },
8030 |s: *const u8, len: usize| { write_str(fd, s, len); }
8031 )
8032}
8033
8034#[no_mangle]
8035pub unsafe extern "C" fn vdprintf(fd: c_int, fmt: *const c_char, mut args: VaList) -> c_int {
8036 impl_format!(fmt, args,
8037 |c: u8| { write_str(fd, &c as *const u8, 1); },
8038 |s: *const u8, len: usize| { write_str(fd, s, len); }
8039 )
8040}
8041
8042unsafe fn format_to_buf(buf: *mut u8, cap: usize, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
8047 let mut pos = 0usize;
8048 let mut i = 0usize;
8049 let mut count = 0usize;
8050 macro_rules! wc {
8051 ($c:expr) => { if pos < cap { *buf.add(pos) = $c; } pos += 1; count += 1; }
8052 }
8053 macro_rules! ws {
8054 ($s:expr, $len:expr) => {{
8055 let __len = $len;
8056 for k in 0..__len { if pos + k < cap { *buf.add(pos + k) = *$s.add(k); } }
8057 pos += __len; count += __len;
8058 }}
8059 }
8060 macro_rules! ws_buf {
8062 ($src:expr, $len:expr) => {{
8063 let __len = $len;
8064 for k in 0..__len { if pos + k < cap { *buf.add(pos + k) = *$src.add(k); } }
8065 pos += __len; count += __len;
8066 }}
8067 }
8068 loop {
8069 let c = *fmt.add(i) as u8;
8070 if c == 0 { break; }
8071 if c != b'%' { wc!(c); i += 1; continue; }
8072 i += 1;
8073 let mut flags: u8 = 0;
8075 loop {
8076 let fc = *fmt.add(i) as u8;
8077 match fc {
8078 b'-' => { flags |= FLAG_MINUS; i += 1; }
8079 b'+' => { flags |= FLAG_PLUS; i += 1; }
8080 b' ' => { flags |= FLAG_SPACE; i += 1; }
8081 b'0' => { flags |= FLAG_ZERO; i += 1; }
8082 b'#' => { flags |= FLAG_HASH; i += 1; }
8083 _ => break,
8084 }
8085 }
8086 let mut width: usize = 0;
8088 if *fmt.add(i) as u8 == b'*' {
8089 width = args.next_arg::<c_int>() as usize; i += 1;
8090 } else {
8091 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
8092 width = width * 10 + ((*fmt.add(i) as u8) - b'0') as usize; i += 1;
8093 }
8094 }
8095 let mut precision: i32 = -1;
8097 if *fmt.add(i) as u8 == b'.' {
8098 i += 1;
8099 if *fmt.add(i) as u8 == b'*' {
8100 precision = args.next_arg::<c_int>(); i += 1;
8101 } else {
8102 precision = 0;
8103 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
8104 precision = precision * 10 + ((*fmt.add(i) as u8) - b'0') as i32; i += 1;
8105 }
8106 }
8107 }
8108 let len_mod = *fmt.add(i) as u8;
8110 let spec: u8;
8111 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' {
8112 i += 1;
8113 let len_mod2 = *fmt.add(i) as u8;
8114 if (len_mod == b'h' && len_mod2 == b'h') || (len_mod == b'l' && len_mod2 == b'l') {
8115 i += 1;
8116 spec = *fmt.add(i) as u8;
8117 match (len_mod, len_mod2, spec) {
8118 (b'h', b'h', b'n') => {
8119 let p = args.next_arg::<*mut c_void>();
8120 if !p.is_null() { *(p as *mut u8) = count as u8; }
8121 }
8122 (b'l', b'l', b'n') => {
8123 let p = args.next_arg::<*mut c_void>();
8124 if !p.is_null() { *(p as *mut c_longlong) = count as c_longlong; }
8125 }
8126 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
8127 let val = args.next_arg::<c_longlong>();
8128 let neg = val < 0;
8129 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
8130 let b = format_u64(abs);
8131 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8132 let mut fbuf = [0u8; 32];
8133 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8134 ws_buf!(fbuf.as_ptr(), len);
8135 }
8136 (b'l', b'l', b'u') => {
8137 let val = args.next_arg::<c_ulonglong>();
8138 let b = format_u64(val as u64);
8139 let mut fbuf = [0u8; 32];
8140 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8141 ws_buf!(fbuf.as_ptr(), len);
8142 }
8143 (b'l', b'l', b'o') => {
8144 let val = args.next_arg::<c_ulonglong>();
8145 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
8146 let mut fbuf = [0u8; 32];
8147 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8148 ws_buf!(fbuf.as_ptr(), len);
8149 }
8150 _ => { wc!(b'%'); wc!(len_mod); wc!(len_mod2); wc!(spec); }
8151 }
8152 } else {
8153 spec = len_mod2;
8154 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
8155 match (lm, spec) {
8156 (b'h', b'n') => {
8157 let p = args.next_arg::<*mut c_void>();
8158 if !p.is_null() { *(p as *mut u16) = count as u16; }
8159 }
8160 (b'l', b'n') => {
8161 let p = args.next_arg::<*mut c_void>();
8162 if !p.is_null() { *(p as *mut c_long) = count as c_long; }
8163 }
8164 (b'z', b'n') | (b't', b'n') => {
8165 let p = args.next_arg::<*mut c_void>();
8166 if !p.is_null() { *(p as *mut usize) = count; }
8167 }
8168 (b'j', b'n') => {
8169 let p = args.next_arg::<*mut c_void>();
8170 if !p.is_null() { *(p as *mut c_ulonglong) = count as c_ulonglong; }
8171 }
8172 (b'l', b'd') | (b'l', b'i') => {
8173 let val = args.next_arg::<c_long>();
8174 let neg = val < 0;
8175 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
8176 let b = format_u64(abs);
8177 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8178 let mut fbuf = [0u8; 32];
8179 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8180 ws_buf!(fbuf.as_ptr(), len);
8181 }
8182 (b'l', b'u') => {
8183 let val = args.next_arg::<c_ulong>();
8184 let b = format_u64(val as u64);
8185 let mut fbuf = [0u8; 32];
8186 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8187 ws_buf!(fbuf.as_ptr(), len);
8188 }
8189 (b'l', b's') => {
8190 let p = args.next_arg::<*const wchar_t>();
8191 if p.is_null() {
8192 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
8193 let pad = width.saturating_sub(slen);
8194 if flags & FLAG_MINUS != 0 { ws!(b"(null)".as_ptr(), slen); for _ in 0..pad { wc!(b' '); } }
8195 else { for _ in 0..pad { wc!(b' '); } ws!(b"(null)".as_ptr(), slen); }
8196 } else {
8197 let mut mb = [0u8; 4096];
8198 let mut n = wide_to_mb(mb.as_mut_ptr(), mb.len(), p);
8199 if precision >= 0 && (precision as usize) < n { n = precision as usize; }
8200 let pad = width.saturating_sub(n);
8201 if flags & FLAG_MINUS != 0 { ws!(mb.as_ptr(), n); for _ in 0..pad { wc!(b' '); } }
8202 else { for _ in 0..pad { wc!(b' '); } ws!(mb.as_ptr(), n); }
8203 }
8204 }
8205 (b'l', b'c') => {
8206 let ch = args.next_arg::<c_int>();
8207 let mut mb = [0u8; 8];
8208 let mut st: c_uint = 0;
8209 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, ch, &mut st);
8210 if n != !0usize { ws!(mb.as_ptr(), n); }
8211 }
8212 (b'l', b'x') => {
8213 let val = args.next_arg::<c_ulong>();
8214 let b = format_hex(val as u64, false);
8215 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
8216 let mut fbuf = [0u8; 32];
8217 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8218 ws_buf!(fbuf.as_ptr(), len);
8219 }
8220 (b'l', b'X') => {
8221 let val = args.next_arg::<c_ulong>();
8222 let b = format_hex(val as u64, true);
8223 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
8224 let mut fbuf = [0u8; 32];
8225 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8226 ws_buf!(fbuf.as_ptr(), len);
8227 }
8228 (b'l', b'o') => {
8229 let val = args.next_arg::<c_ulong>();
8230 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
8231 let mut fbuf = [0u8; 32];
8232 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8233 ws_buf!(fbuf.as_ptr(), len);
8234 }
8235 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
8236 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
8237 let val = args.next_arg::<f64>();
8238 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8239 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8240 let mut fbuf = [0u8; 4224];
8241 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8242 let mut wbuf = [0u8; 4224];
8243 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8244 ws_buf!(wbuf.as_ptr(), wlen);
8245 }
8246 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
8247 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
8248 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
8249 let val = {
8250 let lo: u64 = args.next_arg::<u64>();
8251 let hi: u64 = args.next_arg::<u64>();
8252 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
8253 f128::from_bits(combined) as f64
8254 };
8255 #[cfg(target_arch = "x86_64")]
8256 let val = args.next_arg::<f64>();
8257 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8258 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8259 let mut fbuf = [0u8; 4224];
8260 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8261 let mut wbuf = [0u8; 4224];
8262 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8263 ws_buf!(wbuf.as_ptr(), wlen);
8264 }
8265 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
8266 }
8267 }
8268 } else {
8269 spec = *fmt.add(i) as u8;
8270 match spec {
8271 b's' => {
8272 let s = args.next_arg::<*const c_char>();
8273 if s.is_null() {
8274 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
8275 let padded_len = if width > slen { width } else { slen };
8276 let pad = padded_len - slen;
8277 if flags & FLAG_MINUS != 0 {
8278 ws!(b"(null)".as_ptr(), slen);
8279 for _ in 0..pad { wc!(b' '); }
8280 } else {
8281 for _ in 0..pad { wc!(b' '); }
8282 ws!(b"(null)".as_ptr(), slen);
8283 }
8284 } else {
8285 let full_len = strlen(s as *const c_char);
8286 let slen = if precision >= 0 { (precision as usize).min(full_len) } else { full_len };
8287 let padded_len = if width > slen { width } else { slen };
8288 let pad = padded_len - slen;
8289 if flags & FLAG_MINUS != 0 {
8290 ws!(s as *const u8, slen);
8291 for _ in 0..pad { wc!(b' '); }
8292 } else {
8293 for _ in 0..pad { wc!(b' '); }
8294 ws!(s as *const u8, slen);
8295 }
8296 }
8297 }
8298 b'd' | b'i' => {
8299 let d = args.next_arg::<c_int>();
8300 let neg = d < 0;
8301 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
8302 let b = format_u64(abs);
8303 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8304 let mut fbuf = [0u8; 32];
8305 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8306 ws_buf!(fbuf.as_ptr(), len);
8307 }
8308 b'u' => {
8309 let u = args.next_arg::<c_uint>();
8310 let b = format_u64(u as u64);
8311 let mut fbuf = [0u8; 32];
8312 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8313 ws_buf!(fbuf.as_ptr(), len);
8314 }
8315 b'x' => {
8316 let x = args.next_arg::<c_uint>();
8317 let b = format_hex(x as u64, false);
8318 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
8319 let mut fbuf = [0u8; 32];
8320 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8321 ws_buf!(fbuf.as_ptr(), len);
8322 }
8323 b'X' => {
8324 let x = args.next_arg::<c_uint>();
8325 let b = format_hex(x as u64, true);
8326 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
8327 let mut fbuf = [0u8; 32];
8328 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8329 ws_buf!(fbuf.as_ptr(), len);
8330 }
8331 b'o' => {
8332 let o = args.next_arg::<c_uint>();
8333 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
8334 let mut fbuf = [0u8; 32];
8335 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8336 ws_buf!(fbuf.as_ptr(), len);
8337 }
8338 b'c' => {
8339 let ch = args.next_arg::<c_int>();
8340 if width > 1 {
8341 let pad = width - 1;
8342 if flags & FLAG_MINUS != 0 {
8343 wc!(ch as u8);
8344 for _ in 0..pad { wc!(b' '); }
8345 } else {
8346 for _ in 0..pad { wc!(b' '); }
8347 wc!(ch as u8);
8348 }
8349 } else {
8350 wc!(ch as u8);
8351 }
8352 }
8353 b'p' => {
8354 wc!(b'0'); wc!(b'x');
8355 let p = args.next_arg::<*const c_void>();
8356 let b = format_hex(p as u64, false);
8357 ws!(b.0.as_ptr(), b.1);
8358 }
8359 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
8360 let val = args.next_arg::<f64>();
8361 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8362 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8363 let mut fbuf = [0u8; 4224];
8364 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8365 let mut wbuf = [0u8; 4224];
8366 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8367 ws_buf!(wbuf.as_ptr(), wlen);
8368 }
8369 b'%' => { wc!(b'%'); }
8370 b'n' => {
8371 let p = args.next_arg::<*mut c_void>();
8372 if !p.is_null() { *(p as *mut c_int) = count as c_int; }
8373 }
8374 _ => { wc!(b'%'); wc!(spec); }
8375 }
8376 }
8377 i += 1;
8378 }
8379 if cap > 0 { let null_pos = if pos < cap { pos } else { cap - 1 }; *buf.add(null_pos) = 0; }
8380 count as c_int
8381}
8382
8383#[no_mangle]
8384pub unsafe extern "C" fn vsprintf(buf: *mut c_char, fmt: *const c_char, mut args: VaList) -> c_int {
8385 format_to_buf(buf as *mut u8, usize::MAX, fmt, &mut args)
8386}
8387
8388#[no_mangle]
8389pub unsafe extern "C" fn vsnprintf(buf: *mut c_char, size: usize, fmt: *const c_char, mut args: VaList) -> c_int {
8390 format_to_buf(buf as *mut u8, size, fmt, &mut args)
8391}
8392
8393#[no_mangle]
8394pub unsafe extern "C" fn sprintf(buf: *mut c_char, fmt: *const c_char, mut args: ...) -> c_int {
8395 format_to_buf(buf as *mut u8, usize::MAX, fmt, &mut args)
8396}
8397
8398#[no_mangle]
8399pub unsafe extern "C" fn snprintf(buf: *mut c_char, size: usize, fmt: *const c_char, mut args: ...) -> c_int {
8400 format_to_buf(buf as *mut u8, size, fmt, &mut args)
8401}
8402
8403#[no_mangle]
8404pub unsafe extern "C" fn vasprintf(strp: *mut *mut c_char, fmt: *const c_char, ap: VaList) -> c_int {
8405 let len = vsnprintf(core::ptr::null_mut(), 0, fmt, ap.clone());
8406 if len < 0 {
8407 *strp = core::ptr::null_mut();
8408 return -1;
8409 }
8410 let p = malloc((len as usize) + 1) as *mut c_char;
8411 if p.is_null() {
8412 *strp = core::ptr::null_mut();
8413 return -1;
8414 }
8415 let ret = vsnprintf(p, (len as usize) + 1, fmt, ap.clone());
8416 if ret < 0 {
8417 free(p as *mut c_void);
8418 *strp = core::ptr::null_mut();
8419 return -1;
8420 }
8421 *strp = p;
8422 ret
8423}
8424
8425#[no_mangle]
8426pub unsafe extern "C" fn asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int {
8427 vasprintf(strp, fmt, args)
8428}
8429
8430unsafe fn skip_ws(p: *const u8) -> *const u8 {
8435 let mut q = p;
8436 while *q == b' ' || *q == b'\t' || *q == b'\n' || *q == b'\r' { q = q.add(1); }
8437 q
8438}
8439
8440#[inline]
8441fn is_ws_byte(c: u8) -> bool {
8442 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0b || c == 0x0c
8443}
8444
8445unsafe fn scan_int_val(
8448 buf: *const u8, pos: &mut usize, buf_len: usize, base: u32, width: usize,
8449) -> (u64, bool, bool) {
8450 let start = *pos;
8451 let max = if width > 0 { (start + width).min(buf_len) } else { buf_len };
8452 let neg = if *pos < max && *buf.add(*pos) == b'-' { *pos += 1; true }
8453 else if *pos < max && *buf.add(*pos) == b'+' { *pos += 1; false }
8454 else { false };
8455 if *pos >= max { *pos = start; return (0, false, false); }
8456 let mut base = base;
8457 let mut val: u64 = 0;
8458 if (base == 0 || base == 16) && *pos < max && *buf.add(*pos) == b'0' {
8460 *pos += 1;
8461 if *pos < max && (*buf.add(*pos) == b'x' || *buf.add(*pos) == b'X') {
8462 *pos += 1;
8463 if *pos < max {
8464 if let Some(d) = hex_val(*buf.add(*pos)) {
8465 val = d as u64; *pos += 1;
8466 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; } }
8467 return (val, neg, true);
8468 }
8469 }
8470 return (0, neg, false);
8471 } else if base == 0 {
8472 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; } }
8473 return (val, neg, true);
8474 } else {
8475 return (0, neg, true); }
8477 }
8478 if base == 0 { base = 10; }
8479 let mut found = false;
8480 while *pos < max {
8481 let c = *buf.add(*pos);
8482 let d: Option<u64> = match base {
8483 8 => if c >= b'0' && c <= b'7' { Some((c - b'0') as u64) } else { None },
8484 10 => if c >= b'0' && c <= b'9' { Some((c - b'0') as u64) } else { None },
8485 16 => hex_val(c).map(|v| v as u64),
8486 _ => None,
8487 };
8488 match d { Some(digit) => { val = val.wrapping_mul(base as u64).wrapping_add(digit); *pos += 1; found = true; } None => break }
8489 }
8490 if !found { *pos = start; return (0, false, false); }
8491 (val, neg, true)
8492}
8493
8494unsafe fn scan_float_val(
8496 buf: *const u8, pos: &mut usize, buf_len: usize, width: usize,
8497) -> (f64, bool) {
8498 let start = *pos;
8499 let max = if width > 0 { (start + width).min(buf_len) } else { buf_len };
8500 let neg = if *pos < max && *buf.add(*pos) == b'-' { *pos += 1; true }
8501 else if *pos < max && *buf.add(*pos) == b'+' { *pos += 1; false }
8502 else { false };
8503 if *pos + 2 < max {
8505 let (c0,c1,c2) = (*buf.add(*pos), *buf.add(*pos+1), *buf.add(*pos+2));
8506 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); }
8507 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); }
8508 }
8509 if *pos+1 < max && *buf.add(*pos)==b'0' && (*buf.add(*pos+1)==b'x'||*buf.add(*pos+1)==b'X') {
8511 *pos += 2;
8512 let mut val: f64 = 0.0; let mut found = false; let mut frac_scale = 1.0f64; let mut in_frac = false;
8513 while *pos < max {
8514 if let Some(d) = hex_val(*buf.add(*pos)) {
8515 if in_frac { frac_scale /= 16.0; val += d as f64 * frac_scale; } else { val = val * 16.0 + d as f64; }
8516 *pos += 1; found = true;
8517 } else if *buf.add(*pos)==b'.' && !in_frac { in_frac = true; *pos += 1; } else { break; }
8518 }
8519 if !found { *pos = start; return (0.0, false); }
8520 if *pos < max && (*buf.add(*pos)==b'p'||*buf.add(*pos)==b'P') {
8522 *pos += 1;
8523 let mut eneg = false;
8524 if *pos<max && *buf.add(*pos)==b'-' { eneg=true; *pos+=1; }
8525 else if *pos<max && *buf.add(*pos)==b'+' { *pos+=1; }
8526 let mut ev: i32 = 0; let mut ef = false;
8527 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; }
8528 if !ef { return (0.0, false); }
8529 if eneg { ev = -ev; }
8530 val *= libm::pow(2.0, ev as f64);
8531 }
8532 return (if neg{-val}else{val}, true);
8533 }
8534 let token_start = start;
8535 let mut i = start;
8536 let mut saw_digit = false;
8537 let mut saw_dot = false;
8538 let mut saw_exp = false;
8539 let mut first = true;
8540 while i < max {
8541 let c = *buf.add(i);
8542 if (c == b'+' || c == b'-') && first {
8543 i += 1; first = false; continue;
8544 }
8545 if c >= b'0' && c <= b'9' {
8546 saw_digit = true; i += 1; first = false; continue;
8547 }
8548 if c == b'.' && !saw_dot && !saw_exp {
8549 saw_dot = true; i += 1; first = false; continue;
8550 }
8551 if (c == b'e' || c == b'E') && !saw_exp && saw_digit {
8552 saw_exp = true; i += 1; first = true; continue;
8553 }
8554 break;
8555 }
8556 if !saw_digit { return (0.0, false); }
8557 let s = core::str::from_utf8_unchecked(core::slice::from_raw_parts(buf.add(token_start), i - token_start));
8558 match <f64 as core::str::FromStr>::from_str(s) {
8559 Ok(v) => { *pos = i; return (v, true); }
8560 Err(_) => { return (0.0, false); }
8561 }
8562}
8563
8564unsafe fn do_vsscanf(
8567 buf: *const u8, buf_len: usize, fmt: *const c_char, args: &mut VaList<'_>, consumed: *mut usize,
8568) -> c_int {
8569 let mut p = 0usize;
8570 let mut fi = 0usize;
8571 let mut assigned = 0i32;
8572 let mut input_eof = false;
8573 loop {
8574 let fc = *fmt.add(fi) as u8;
8575 if fc == 0 { break; }
8576 if is_ws_byte(fc) {
8577 while is_ws_byte(*fmt.add(fi) as u8) { fi += 1; }
8578 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8579 continue;
8580 }
8581 if fc != b'%' {
8582 if p >= buf_len { input_eof = true; break; }
8583 if *buf.add(p) != fc { break; }
8584 p += 1; fi += 1; continue;
8585 }
8586 fi += 1;
8587 if *fmt.add(fi) as u8 == b'%' {
8589 if p >= buf_len { input_eof = true; break; }
8590 if *buf.add(p) != b'%' { break; }
8591 p += 1; fi += 1; continue;
8592 }
8593 let suppress = if *fmt.add(fi) as u8 == b'*' { fi += 1; true } else { false };
8594 let mut width: usize = 0;
8595 while (*fmt.add(fi) as u8) >= b'0' && (*fmt.add(fi) as u8) <= b'9' {
8596 width = width * 10 + ((*fmt.add(fi) as u8) - b'0') as usize; fi += 1;
8597 }
8598 if *fmt.add(fi) as u8 == b'm' { fi += 1; }
8599 let mut len_mod = 0u8;
8600 match *fmt.add(fi) as u8 {
8601 b'h' => { fi += 1; if *fmt.add(fi) as u8 == b'h' { fi += 1; len_mod = 2; } else { len_mod = 1; } }
8602 b'l' => { fi += 1; if *fmt.add(fi) as u8 == b'l' { fi += 1; len_mod = 4; } else { len_mod = 3; } }
8603 b'j' => { fi += 1; len_mod = 4; }
8604 b'z' | b't' => { fi += 1; len_mod = 3; }
8605 b'L' => { fi += 1; len_mod = 5; }
8606 _ => {}
8607 }
8608 let spec = *fmt.add(fi) as u8;
8609 let (real_spec, _real_len) = if spec==b'C' {(b'c',3u8)} else if spec==b'S' {(b's',3u8)} else {(spec,len_mod)};
8610 match real_spec {
8611 b'n' => {
8612 if !suppress { let out = args.next_arg::<*mut c_int>(); if !out.is_null() { *out = p as c_int; } }
8613 }
8614 b'd' | b'u' => {
8615 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8616 if p >= buf_len { input_eof = true; break; }
8617 let dest = if !suppress { Some(args.next_arg::<*mut c_int>()) } else { None };
8618 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 10, width);
8619 if !ok { break; }
8620 if let Some(out) = dest { if !out.is_null() {
8621 *out = if real_spec==b'd' && neg { -(val as i64) as c_int } else { val as c_int };
8622 }}
8623 if !suppress { assigned += 1; }
8624 }
8625 b'i' => {
8626 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8627 if p >= buf_len { input_eof = true; break; }
8628 let dest = if !suppress { Some(args.next_arg::<*mut c_int>()) } else { None };
8629 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 0, width);
8630 if !ok { break; }
8631 if let Some(out) = dest { if !out.is_null() { *out = if neg { -(val as i64) as c_int } else { val as c_int }; } }
8632 if !suppress { assigned += 1; }
8633 }
8634 b'o' => {
8635 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8636 if p >= buf_len { input_eof = true; break; }
8637 let dest = if !suppress { Some(args.next_arg::<*mut c_int>()) } else { None };
8638 let (val, _, ok) = scan_int_val(buf, &mut p, buf_len, 8, width);
8639 if !ok { break; }
8640 if let Some(out) = dest { if !out.is_null() { *out = val as c_int; } }
8641 if !suppress { assigned += 1; }
8642 }
8643 b'x' | b'X' => {
8644 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8645 if p >= buf_len { input_eof = true; break; }
8646 let dest = if !suppress { Some(args.next_arg::<*mut c_int>()) } else { None };
8647 let (val, _, ok) = scan_int_val(buf, &mut p, buf_len, 16, width);
8648 if !ok { break; }
8649 if let Some(out) = dest { if !out.is_null() { *out = val as c_int; } }
8650 if !suppress { assigned += 1; }
8651 }
8652 b'p' => {
8653 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8654 if p >= buf_len { input_eof = true; break; }
8655 let dest = if !suppress { Some(args.next_arg::<*mut *mut c_void>()) } else { None };
8656 let (val, _, ok) = scan_int_val(buf, &mut p, buf_len, 16, width);
8657 if !ok { break; }
8658 if let Some(out) = dest { if !out.is_null() { *out = val as usize as *mut c_void; } }
8659 if !suppress { assigned += 1; }
8660 }
8661 b'a' | b'e' | b'f' | b'g' | b'A' | b'E' | b'F' | b'G' => {
8662 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8663 if p >= buf_len { input_eof = true; break; }
8664 let (val, ok) = scan_float_val(buf, &mut p, buf_len, width);
8665 if !ok { break; }
8666 if !suppress {
8667 if _real_len == 3 {
8668 let out = args.next_arg::<*mut f64>(); if !out.is_null() { *out = val; }
8669 } else if _real_len == 5 {
8670 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
8671 { let out = args.next_arg::<*mut f128>(); if !out.is_null() { *out = val as f128; } }
8672 #[cfg(target_arch = "x86_64")]
8673 { let out = args.next_arg::<*mut f64>(); if !out.is_null() { *out = val; } }
8674 } else {
8675 let out = args.next_arg::<*mut f32>(); if !out.is_null() { *out = val as f32; }
8676 }
8677 }
8678 if !suppress { assigned += 1; }
8679 }
8680 b'c' => {
8681 let w = if width > 0 { width } else { 1 };
8682 if p >= buf_len { input_eof = true; break; }
8683 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8684 let start_p = p;
8685 let mut j = 0usize;
8686 while j < w && p < buf_len {
8687 if !dest_ptr.is_null() { *dest_ptr.add(j) = *buf.add(p) as c_char; }
8688 p += 1; j += 1;
8689 }
8690 if j != w { p = start_p; input_eof = true; break; }
8691 if !suppress { assigned += 1; }
8692 }
8693 b's' => {
8694 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8695 if p >= buf_len { input_eof = true; break; }
8696 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8697 let w = if width > 0 { width } else { usize::MAX };
8698 let mut j = 0usize;
8699 while p < buf_len && *buf.add(p) != 0 && !is_ws_byte(*buf.add(p)) && j < w {
8700 if !dest_ptr.is_null() { *dest_ptr.add(j) = *buf.add(p) as c_char; }
8701 p += 1; j += 1;
8702 }
8703 if j == 0 { break; }
8704 if !dest_ptr.is_null() { *dest_ptr.add(j) = 0; }
8705 if !suppress { assigned += 1; }
8706 }
8707 b'[' => {
8708 fi += 1;
8709 let negate = if *fmt.add(fi) as u8 == b'^' { fi += 1; true } else { false };
8710 let mut charset = [0u8; 256];
8711 if *fmt.add(fi) as u8 == b']' { charset[b']' as usize] = 1; fi += 1; }
8712 loop { let c = *fmt.add(fi) as u8; if c == b']' || c == 0 { break; } charset[c as usize] = 1; fi += 1; }
8713 if *fmt.add(fi) as u8 == b']' { fi += 1; }
8714 fi -= 1; if p >= buf_len { input_eof = true; break; }
8716 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8717 let w = if width > 0 { width } else { usize::MAX };
8718 let mut j = 0usize;
8719 while p < buf_len && *buf.add(p) != 0 && j < w {
8720 let c = *buf.add(p);
8721 let in_set = charset[c as usize] != 0;
8722 if negate { if in_set { break; } } else { if !in_set { break; } }
8723 if !dest_ptr.is_null() { *dest_ptr.add(j) = c as c_char; }
8724 p += 1; j += 1;
8725 }
8726 if j == 0 { break; }
8727 if !dest_ptr.is_null() { *dest_ptr.add(j) = 0; }
8728 if !suppress { assigned += 1; }
8729 }
8730 _ => break,
8731 }
8732 fi += 1;
8733 }
8734 if !consumed.is_null() { *consumed = p; }
8735 if assigned == 0 && input_eof { -1 } else { assigned }
8736}
8737
8738unsafe fn vsscanf_inner(buf: *const u8, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
8739 let len = strlen(buf as *const c_char);
8740 do_vsscanf(buf, len, fmt, args, core::ptr::null_mut())
8741}
8742
8743#[no_mangle]
8744pub unsafe extern "C" fn vsscanf(buf: *const c_char, fmt: *const c_char, mut args: VaList) -> c_int {
8745 vsscanf_inner(buf as *const u8, fmt, &mut args)
8746}
8747
8748#[no_mangle]
8749pub unsafe extern "C" fn vfscanf(stream: *mut FILE, fmt: *const c_char, mut args: VaList) -> c_int {
8750 let f = &mut *stream;
8751 let start_ungotten_count = f.ungotten_count as usize;
8752 let sfunc = f.seek_fn;
8753 let start_pos = sfunc.map(|s| s(stream, 0, SEEK_CUR)).unwrap_or(-1);
8754
8755 let mut line = [0u8; 4096];
8756 let mut pos = 0usize;
8757
8758 if start_pos >= 0 {
8759 while pos < line.len() - 1 {
8761 let c = fgetc(stream);
8762 if c == -1 { break; }
8763 line[pos] = c as u8;
8764 pos += 1;
8765 if c == b'\n' as c_int { break; }
8766 }
8767 } else {
8768 while f.ungotten_count > 0 && pos < line.len() - 1 {
8773 f.ungotten_count -= 1;
8774 line[pos] = f.ungotten[f.ungotten_count as usize] as u8;
8775 pos += 1;
8776 }
8777 while !f.rpos.is_null() && f.rpos < f.rend && pos < line.len() - 1 {
8779 line[pos] = *f.rpos;
8780 f.rpos = f.rpos.add(1);
8781 pos += 1;
8782 }
8783 let fd = f.fd;
8785 let old_flags = sys_fcntl(fd, F_GETFL, 0);
8786 if old_flags >= 0 {
8787 let _ = sys_fcntl(fd, F_SETFL, old_flags | O_NONBLOCK as i64);
8788 }
8789 while pos < line.len() - 1 {
8790 let n = sys_read(fd as i64, line.as_mut_ptr().add(pos), line.len() - 1 - pos);
8791 if n <= 0 { break; }
8792 pos += n as usize;
8793 }
8794 if old_flags >= 0 {
8795 let _ = sys_fcntl(fd, F_SETFL, old_flags);
8796 }
8797 f._eof = 0;
8799 f._err = 0;
8800 f.flags &= !(F_EOF | F_ERR);
8801 }
8802
8803 line[pos] = 0;
8804 if pos == 0 { return 0; }
8805
8806 let mut consumed = 0usize;
8807 let assigned = do_vsscanf(line.as_ptr(), pos, fmt, &mut args, &mut consumed);
8808
8809 if start_pos >= 0 {
8810 let file_consumed = consumed.saturating_sub(start_ungotten_count);
8812 let target = start_pos + file_consumed as i64;
8813 if let Some(sfunc) = sfunc {
8814 sfunc(stream, target, SEEK_SET);
8815 }
8816 f.rpos = core::ptr::null_mut();
8817 f.rend = core::ptr::null_mut();
8818 if consumed < pos { f._eof = 0; }
8819 let remaining = start_ungotten_count.saturating_sub(consumed);
8820 f.ungotten_count = remaining as c_int;
8821 } else {
8822 let unconsumed = pos.saturating_sub(consumed);
8824 if unconsumed > 0 && !f.buf.is_null() {
8825 let copy_count = core::cmp::min(unconsumed, f.buf_size);
8826 core::ptr::copy(
8827 line.as_ptr().add(consumed),
8828 f.buf,
8829 copy_count,
8830 );
8831 f.rpos = f.buf;
8832 f.rend = f.buf.add(copy_count);
8833 }
8834 f.ungotten_count = 0;
8835 f._eof = 0;
8836 f.flags &= !F_EOF;
8837 }
8838 assigned
8839}
8840
8841#[no_mangle]
8842pub unsafe extern "C" fn vscanf(fmt: *const c_char, args: VaList) -> c_int {
8843 vfscanf(stdin, fmt, args)
8844}
8845
8846#[no_mangle]
8847pub unsafe extern "C" fn sscanf(buf: *const c_char, fmt: *const c_char, mut args: ...) -> c_int {
8848 vsscanf_inner(buf as *const u8, fmt, &mut args)
8849}
8850
8851#[no_mangle]
8852pub unsafe extern "C" fn fscanf(stream: *mut FILE, fmt: *const c_char, args: ...) -> c_int {
8853 vfscanf(stream, fmt, args)
8854}
8855
8856#[no_mangle]
8857pub unsafe extern "C" fn scanf(fmt: *const c_char, args: ...) -> c_int {
8858 vfscanf(stdin, fmt, args)
8859}
8860
8861#[no_mangle]
8866pub unsafe extern "C" fn getdelim(
8867 lineptr: *mut *mut c_char, n: *mut usize, delim: c_int, stream: *mut FILE,
8868) -> isize {
8869 if lineptr.is_null() || n.is_null() { return -1; }
8870 let mut cap = *n;
8871 let mut buf = *lineptr;
8872 if buf.is_null() || cap == 0 {
8873 cap = 128;
8874 buf = realloc(buf as *mut c_void, cap) as *mut c_char;
8875 if buf.is_null() { return -1; }
8876 *lineptr = buf;
8877 *n = cap;
8878 }
8879 let mut len = 0usize;
8880 loop {
8881 let c = fgetc(stream);
8882 if c == -1 { if len == 0 { return -1; } break; }
8883 if len + 1 >= cap {
8884 let new_cap = cap.wrapping_mul(2);
8885 let new_buf = realloc(buf as *mut c_void, new_cap) as *mut c_char;
8886 if new_buf.is_null() { return -1; }
8887 buf = new_buf; cap = new_cap;
8888 *lineptr = buf; *n = cap;
8889 }
8890 *buf.add(len) = c as c_char;
8891 len += 1;
8892 if c == delim { break; }
8893 }
8894 *buf.add(len) = 0;
8895 len as isize
8896}
8897
8898#[no_mangle]
8899pub unsafe extern "C" fn getline(lineptr: *mut *mut c_char, n: *mut usize, stream: *mut FILE) -> isize {
8900 getdelim(lineptr, n, b'\n' as c_int, stream)
8901}
8902
8903#[no_mangle]
8908pub unsafe extern "C" fn popen(cmd: *const c_char, mode: *const c_char) -> *mut FILE {
8909 if cmd.is_null() || mode.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
8910 let m = *mode;
8911 if m != b'r' as c_char && m != b'w' as c_char { ERRNO = EINVAL; return core::ptr::null_mut(); }
8912 let mut p: [c_int; 2] = [0; 2];
8913 if sys_pipe2(p.as_mut_ptr(), O_CLOEXEC) < 0 { return core::ptr::null_mut(); }
8914 let op = if m == b'r' as c_char { 0 } else { 1 };
8915 let child_fd = p[1 - op];
8916 let f = fdopen(p[op], mode);
8917 if f.is_null() { sys_close(p[0] as i64); sys_close(p[1] as i64); return core::ptr::null_mut(); }
8918 let pid = sys_fork();
8919 if pid < 0 { fclose(f); sys_close(child_fd as i64); return core::ptr::null_mut(); }
8920 if pid == 0 {
8921 sys_close(p[op] as i64);
8922 if child_fd != (1 - op) as c_int { sys_dup3(child_fd, (1 - op) as c_int, 0); sys_close(child_fd as i64); }
8923 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
8924 let argv = [b"sh\0".as_ptr() as *const c_char, b"-c\0".as_ptr() as *const c_char, cmd, core::ptr::null()];
8925 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
8926 _exit(127);
8927 }
8928 sys_close(child_fd as i64);
8929 (*f).pipe_pid = pid as c_int;
8930 f
8931}
8932
8933#[no_mangle]
8934pub unsafe extern "C" fn pclose(f: *mut FILE) -> c_int {
8935 let pid = (*f).pipe_pid;
8936 let r = fclose(f);
8937 if pid <= 0 { return -1; }
8938 let mut status: c_int = 0;
8939 let mut w: c_int;
8940 loop {
8941 w = waitpid(pid, &mut status, 0);
8942 if w >= 0 || w != -EINTR { break; }
8943 }
8944 if w < 0 || r != 0 { return -1; }
8945 status
8946}
8947
8948const L_TMPNAM: usize = 20;
8953static mut TMPNAM_COUNTER: c_uint = 0;
8954
8955unsafe fn fill_tmpname(out: *mut c_char, seed: c_uint) {
8956 let prefix = b"/tmp/tmp\0";
8957 let mut k = 0;
8958 while k < prefix.len() - 1 { *out.add(k) = prefix[k] as c_char; k += 1; }
8959 let (buf, len) = format_hex(seed as u64, false);
8960 for j in 0..len.min(L_TMPNAM - k - 1) { *out.add(k + j) = buf[j] as c_char; k += 1; }
8961 *out.add(k) = 0;
8962}
8963
8964#[no_mangle]
8965pub unsafe extern "C" fn tmpfile() -> *mut FILE {
8966 let mut name = [0u8; L_TMPNAM];
8967 let mut ctr: c_uint = 0;
8968 loop {
8969 ctr = ctr.wrapping_add(1);
8970 let mut ts: timespec = core::mem::zeroed();
8971 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
8972 let seed = (ts.tv_nsec as c_uint).wrapping_add(ctr);
8973 fill_tmpname(name.as_mut_ptr() as *mut c_char, seed);
8974 let fd = sys_open(name.as_ptr(), (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
8975 if fd >= 0 {
8976 sys_unlinkat(AT_FDCWD, name.as_ptr(), 0);
8977 let f = fdopen(fd as c_int, b"w+\0".as_ptr() as *const c_char);
8978 if f.is_null() { sys_close(fd); }
8979 return f;
8980 }
8981 if ctr > 100 { return core::ptr::null_mut(); }
8982 }
8983}
8984
8985#[no_mangle]
8986pub unsafe extern "C" fn tmpnam(s: *mut c_char) -> *mut c_char {
8987 static mut BUF: [c_char; L_TMPNAM] = [0; L_TMPNAM];
8988 let out = if s.is_null() { core::ptr::addr_of_mut!(BUF) as *mut c_char } else { s };
8989 TMPNAM_COUNTER = TMPNAM_COUNTER.wrapping_add(1);
8990 let mut ts: timespec = core::mem::zeroed();
8991 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
8992 let seed = (ts.tv_nsec as c_uint).wrapping_add(TMPNAM_COUNTER);
8993 fill_tmpname(out, seed);
8994 out
8995}
8996
8997#[no_mangle]
8998pub unsafe extern "C" fn remove(path: *const c_char) -> c_int {
8999 if path.is_null() { ERRNO = EINVAL; return -1; }
9000 let r = sys_unlinkat(AT_FDCWD, path as *const u8, 0);
9001 if r == 0 { 0 } else { ERRNO = (-r) as c_int; -1 }
9002}
9003
9004#[no_mangle]
9005pub unsafe extern "C" fn rename(old: *const c_char, new_: *const c_char) -> c_int {
9006 if old.is_null() || new_.is_null() { ERRNO = EINVAL; return -1; }
9007 let r = sys_renameat2(AT_FDCWD, old as *const u8, AT_FDCWD, new_ as *const u8, 0);
9008 if r == 0 { 0 } else { ERRNO = (-r) as c_int; -1 }
9009}
9010
9011const MMAP_FAILED: *mut u8 = !0usize as *mut u8;
9016const PAGE: usize = 4096;
9017
9018#[no_mangle]
9023pub unsafe extern "C" fn _exit(code: c_int) -> ! {
9024 sys_exit_group(code)
9025}
9026
9027#[inline]
9028unsafe fn sys_exit_group(code: c_int) -> ! {
9029 <Arch as Syscalls>::syscall_noreturn1(SYS_EXIT_GROUP, code as i64)
9030}
9031
9032#[inline]
9033unsafe fn sys_exit_thread(code: c_int) -> ! {
9034 <Arch as Syscalls>::syscall_noreturn1(SYS_EXIT, code as i64)
9035}
9036
9037#[no_mangle]
9038pub unsafe extern "C" fn _Exit(code: c_int) -> ! {
9039 _exit(code);
9040}
9041
9042#[no_mangle]
9043pub unsafe extern "C" fn exit(code: c_int) -> ! {
9044 fflush(core::ptr::null_mut());
9045 __funcs_on_exit();
9046 _exit(code);
9047}
9048
9049#[no_mangle]
9050pub unsafe extern "C" fn abort() -> ! {
9051 raise(6); _exit(128 + 6);
9053}
9054
9055#[no_mangle]
9058pub static mut __stack_chk_guard: usize = 0;
9059
9060#[no_mangle]
9061pub unsafe extern "C" fn __stack_chk_fail() -> ! {
9062 const MSG: &[u8] = b"*** stack smashing detected ***: terminated\n";
9063 let _ = sys_write(2, MSG.as_ptr(), MSG.len());
9064 abort();
9065}
9066
9067type CmpRfn = unsafe extern "C" fn(*const c_void, *const c_void, *mut c_void) -> c_int;
9072
9073const AR_LEN: usize = 16 * core::mem::size_of::<usize>();
9074const AR_MASK: usize = AR_LEN - 1;
9075
9076unsafe fn qsort_pntz(p: &[usize; 2]) -> i32 {
9077 if p[0] != 1 {
9078 p[0].wrapping_sub(1).trailing_zeros() as i32
9079 } else if p[1] != 0 {
9080 (8 * core::mem::size_of::<usize>()) as i32 + p[1].trailing_zeros() as i32
9081 } else {
9082 0
9083 }
9084}
9085
9086unsafe fn qsort_cycle(width: usize, ar: &mut [*mut u8; AR_LEN], n: usize) {
9087 if n < 2 { return; }
9088 let mut tmp = [0u8; 256];
9089 ar[n] = tmp.as_mut_ptr();
9090 let mut w = width;
9091 while w > 0 {
9092 let l = if 256 < w { 256 } else { w };
9093 core::ptr::copy_nonoverlapping(ar[0], ar[n], l);
9094 for i in 0..n {
9095 core::ptr::copy_nonoverlapping(ar[i + 1], ar[i], l);
9096 ar[i] = ar[i].add(l);
9097 }
9098 w -= l;
9099 }
9100}
9101
9102unsafe fn qsort_shl(p: &mut [usize; 2], n: i32) {
9103 let bits = (8 * core::mem::size_of::<usize>()) as i32;
9104 if n >= bits {
9105 p[1] = p[0];
9106 p[0] = 0;
9107 let n = n - bits;
9108 if n == 0 { return; }
9109 }
9110 p[1] = (p[1] << n) | (p[0] >> (bits - n));
9111 p[0] <<= n;
9112}
9113
9114unsafe fn qsort_shr(p: &mut [usize; 2], n: i32) {
9115 let bits = (8 * core::mem::size_of::<usize>()) as i32;
9116 if n >= bits {
9117 p[0] = p[1];
9118 p[1] = 0;
9119 let n = n - bits;
9120 if n == 0 { return; }
9121 }
9122 p[0] = (p[0] >> n) | (p[1] << (bits - n));
9123 p[1] >>= n;
9124}
9125
9126unsafe fn qsort_sift(
9127 head: *mut u8, width: usize,
9128 cmp: CmpRfn, arg: *mut c_void,
9129 pshift: i32, lp: &[usize],
9130) {
9131 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
9132 ar[0] = head;
9133 let mut i = 1usize;
9134 let mut h = head;
9135 let mut ps = pshift;
9136
9137 while ps > 1 {
9138 let rt = h.sub(width);
9139 let lf = h.sub(width + lp[(ps - 2) as usize]);
9140
9141 if cmp(ar[0] as *const c_void, lf as *const c_void, arg) >= 0
9142 && cmp(ar[0] as *const c_void, rt as *const c_void, arg) >= 0
9143 {
9144 break;
9145 }
9146 if cmp(lf as *const c_void, rt as *const c_void, arg) >= 0 {
9147 ar[i & AR_MASK] = lf;
9148 i += 1;
9149 h = lf;
9150 ps -= 1;
9151 } else {
9152 ar[i & AR_MASK] = rt;
9153 i += 1;
9154 h = rt;
9155 ps -= 2;
9156 }
9157 }
9158 qsort_cycle(width, &mut ar, i & AR_MASK);
9159}
9160
9161unsafe fn qsort_trinkle(
9162 head: *mut u8, width: usize,
9163 cmp: CmpRfn, arg: *mut c_void,
9164 pp: &[usize; 2], pshift: i32, trusty: i32,
9165 lp: &[usize],
9166) {
9167 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
9168 let mut p = *pp;
9169 ar[0] = head;
9170 let mut i = 1usize;
9171 let mut h = head;
9172 let mut ps = pshift;
9173 let mut t = trusty;
9174
9175 while p[0] != 1 || p[1] != 0 {
9176 let stepson = h.sub(lp[ps as usize]);
9177 if cmp(stepson as *const c_void, ar[0] as *const c_void, arg) <= 0 {
9178 break;
9179 }
9180 if t == 0 && ps > 1 {
9181 let rt = h.sub(width);
9182 let lf = h.sub(width + lp[(ps - 2) as usize]);
9183 if cmp(rt as *const c_void, stepson as *const c_void, arg) >= 0
9184 || cmp(lf as *const c_void, stepson as *const c_void, arg) >= 0
9185 {
9186 break;
9187 }
9188 }
9189
9190 ar[i & AR_MASK] = stepson;
9191 i += 1;
9192 h = stepson;
9193 let trail = qsort_pntz(&p);
9194 qsort_shr(&mut p, trail);
9195 ps += trail;
9196 t = 0;
9197 }
9198 if t == 0 {
9199 qsort_cycle(width, &mut ar, i & AR_MASK);
9200 qsort_sift(h, width, cmp, arg, ps, lp);
9201 }
9202}
9203
9204#[no_mangle]
9205pub unsafe extern "C" fn __qsort_r(
9206 base: *mut c_void,
9207 nel: usize,
9208 width: usize,
9209 cmp: CmpRfn,
9210 arg: *mut c_void,
9211) {
9212 let size = width * nel;
9213 if size == 0 { return; }
9214
9215 let mut lp = [0usize; 96];
9216 lp[0] = width;
9217 lp[1] = width;
9218 let mut li = 2;
9219 while {
9220 lp[li] = lp[li - 2] + lp[li - 1] + width;
9221 lp[li] < size
9222 } {
9223 li += 1;
9224 }
9225
9226 let mut head = base as *mut u8;
9227 let high = head.add(size - width);
9228 let mut p: [usize; 2] = [1, 0];
9229 let mut pshift: i32 = 1;
9230
9231 while head < high {
9232 if (p[0] & 3) == 3 {
9233 qsort_sift(head, width, cmp, arg, pshift, &lp);
9234 qsort_shr(&mut p, 2);
9235 pshift += 2;
9236 } else {
9237 if lp[(pshift - 1) as usize] >= (high as usize) - (head as usize) {
9238 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
9239 } else {
9240 qsort_sift(head, width, cmp, arg, pshift, &lp);
9241 }
9242
9243 if pshift == 1 {
9244 qsort_shl(&mut p, 1);
9245 pshift = 0;
9246 } else {
9247 qsort_shl(&mut p, pshift - 1);
9248 pshift = 1;
9249 }
9250 }
9251
9252 p[0] |= 1;
9253 head = head.add(width);
9254 }
9255
9256 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
9257
9258 while pshift != 1 || p[0] != 1 || p[1] != 0 {
9259 if pshift <= 1 {
9260 let trail = qsort_pntz(&p);
9261 qsort_shr(&mut p, trail);
9262 pshift += trail;
9263 } else {
9264 qsort_shl(&mut p, 2);
9265 pshift -= 2;
9266 p[0] ^= 7;
9267 qsort_shr(&mut p, 1);
9268 qsort_trinkle(
9269 head.sub(lp[pshift as usize] + width),
9270 width, cmp, arg, &p, pshift + 1, 1, &lp,
9271 );
9272 qsort_shl(&mut p, 1);
9273 p[0] |= 1;
9274 qsort_trinkle(head.sub(width), width, cmp, arg, &p, pshift, 1, &lp);
9275 }
9276 head = head.sub(width);
9277 }
9278}
9279
9280#[no_mangle]
9281pub unsafe extern "C" fn qsort_r(
9282 base: *mut c_void,
9283 nel: usize,
9284 width: usize,
9285 cmp: CmpRfn,
9286 arg: *mut c_void,
9287) {
9288 __qsort_r(base, nel, width, cmp, arg);
9289}
9290
9291unsafe extern "C" fn qsort_wrap_cmp(
9292 a: *const c_void,
9293 b: *const c_void,
9294 cmp_ctx: *mut c_void,
9295) -> c_int {
9296 let cmp: CmpFn = core::mem::transmute(cmp_ctx);
9297 cmp(a, b)
9298}
9299
9300#[no_mangle]
9301pub unsafe extern "C" fn qsort(
9302 base: *mut c_void,
9303 nel: usize,
9304 width: usize,
9305 cmp: CmpFn,
9306) {
9307 __qsort_r(base, nel, width, qsort_wrap_cmp, cmp as *mut c_void);
9308}
9309
9310const ATEXIT_COUNT: usize = 32;
9315
9316#[repr(C)]
9317struct AtExitBlock {
9318 next: *mut AtExitBlock,
9319 f: [Option<unsafe extern "C" fn(*mut c_void)>; ATEXIT_COUNT],
9320 a: [*mut c_void; ATEXIT_COUNT],
9321}
9322
9323static mut ATEXIT_BUILTIN: AtExitBlock = AtExitBlock {
9324 next: core::ptr::null_mut(),
9325 f: [None; ATEXIT_COUNT],
9326 a: [core::ptr::null_mut(); ATEXIT_COUNT],
9327};
9328static mut ATEXIT_HEAD: *mut AtExitBlock = core::ptr::null_mut();
9329static mut ATEXIT_SLOT: usize = 0;
9330static mut ATEXIT_FINISHED: bool = false;
9331
9332#[no_mangle]
9333pub unsafe extern "C" fn __funcs_on_exit() {
9334 while !ATEXIT_HEAD.is_null() {
9335 let head = ATEXIT_HEAD;
9336 while ATEXIT_SLOT > 0 {
9337 ATEXIT_SLOT -= 1;
9338 if let Some(f) = (*head).f[ATEXIT_SLOT] {
9339 let a = (*head).a[ATEXIT_SLOT];
9340 f(a);
9341 }
9342 }
9343 ATEXIT_HEAD = (*head).next;
9344 ATEXIT_SLOT = ATEXIT_COUNT;
9345 }
9346 ATEXIT_FINISHED = true;
9347}
9348
9349#[no_mangle]
9350pub unsafe extern "C" fn __cxa_atexit(
9351 func: unsafe extern "C" fn(*mut c_void),
9352 arg: *mut c_void,
9353 _dso: *mut c_void,
9354) -> c_int {
9355 if ATEXIT_FINISHED {
9356 return -1;
9357 }
9358 if ATEXIT_HEAD.is_null() {
9359 ATEXIT_HEAD = core::ptr::addr_of_mut!(ATEXIT_BUILTIN);
9360 }
9361 if ATEXIT_SLOT == ATEXIT_COUNT {
9362 let new = calloc(1, core::mem::size_of::<AtExitBlock>()) as *mut AtExitBlock;
9363 if new.is_null() {
9364 return -1;
9365 }
9366 (*new).next = ATEXIT_HEAD;
9367 ATEXIT_HEAD = new;
9368 ATEXIT_SLOT = 0;
9369 }
9370 (*ATEXIT_HEAD).f[ATEXIT_SLOT] = Some(func);
9371 (*ATEXIT_HEAD).a[ATEXIT_SLOT] = arg;
9372 ATEXIT_SLOT += 1;
9373 0
9374}
9375
9376unsafe extern "C" fn atexit_caller(arg: *mut c_void) {
9377 let func: unsafe extern "C" fn() = core::mem::transmute(arg);
9378 func();
9379}
9380
9381#[no_mangle]
9382pub unsafe extern "C" fn atexit(func: unsafe extern "C" fn()) -> c_int {
9383 __cxa_atexit(atexit_caller, func as *mut c_void, core::ptr::null_mut())
9384}
9385
9386#[no_mangle]
9387pub unsafe extern "C" fn __cxa_finalize(_dso: *mut c_void) {}
9388
9389#[no_mangle]
9394pub static mut __environ: *mut *mut c_char = core::ptr::null_mut();
9395
9396const ENV_MAX_ALLOCED: usize = 256;
9398static mut ENV_ALLOCED: [*mut c_char; ENV_MAX_ALLOCED] = [core::ptr::null_mut(); ENV_MAX_ALLOCED];
9399static mut ENV_ALLOCED_N: usize = 0;
9400
9401unsafe fn env_rm_add(old: *mut c_char, mut new: *mut c_char) {
9402 for i in 0..ENV_ALLOCED_N {
9403 if ENV_ALLOCED[i] == old {
9404 ENV_ALLOCED[i] = new;
9405 if !old.is_null() {
9406 free(old as *mut c_void);
9407 }
9408 return;
9409 } else if ENV_ALLOCED[i].is_null() && !new.is_null() {
9410 ENV_ALLOCED[i] = new;
9411 new = core::ptr::null_mut();
9412 }
9413 }
9414 if !new.is_null() && ENV_ALLOCED_N < ENV_MAX_ALLOCED {
9415 ENV_ALLOCED[ENV_ALLOCED_N] = new;
9416 ENV_ALLOCED_N += 1;
9417 }
9418}
9419
9420unsafe fn strchrnul_u8(s: *const u8, c: u8) -> *const u8 {
9421 let mut p = s;
9422 while *p != 0 && *p != c {
9423 p = p.add(1);
9424 }
9425 p
9426}
9427
9428#[no_mangle]
9429pub unsafe extern "C" fn getenv(name: *const c_char) -> *mut c_char {
9430 if __environ.is_null() || name.is_null() {
9431 return core::ptr::null_mut();
9432 }
9433 let name = name as *const u8;
9434 let l = strchrnul_u8(name, b'=') as usize - name as usize;
9435 if l == 0 || *name.add(l) != 0 {
9436 return core::ptr::null_mut();
9437 }
9438 let mut e = __environ;
9439 while !(*e).is_null() {
9440 let entry = *e as *const u8;
9441 if strncmp(entry, name, l) == 0 && *entry.add(l) == b'=' {
9442 return entry.add(l + 1) as *mut c_char;
9443 }
9444 e = e.add(1);
9445 }
9446 core::ptr::null_mut()
9447}
9448
9449#[no_mangle]
9450pub unsafe extern "C" fn setenv(
9451 var: *const c_char,
9452 value: *const c_char,
9453 overwrite: c_int,
9454) -> c_int {
9455 if var.is_null() || value.is_null() {
9456 ERRNO = EINVAL;
9457 return -1;
9458 }
9459 let var = var as *const u8;
9460 let l1 = strchrnul_u8(var, b'=') as usize - var as usize;
9461 if l1 == 0 || *var.add(l1) != 0 {
9462 ERRNO = EINVAL;
9463 return -1;
9464 }
9465 if overwrite == 0 && !getenv(var as *const c_char).is_null() {
9466 return 0;
9467 }
9468 let l2 = strlen(value as *const c_char);
9469 let s = malloc(l1 + l2 + 2) as *mut u8;
9470 if s.is_null() {
9471 return -1;
9472 }
9473 core::ptr::copy_nonoverlapping(var, s, l1);
9474 *s.add(l1) = b'=';
9475 core::ptr::copy_nonoverlapping(value as *const u8, s.add(l1 + 1), l2 + 1);
9476 putenv_internal(s as *mut c_char, l1, s as *mut c_char)
9477}
9478
9479unsafe fn putenv_internal(s: *mut c_char, l: usize, r: *mut c_char) -> c_int {
9480 let mut i = 0;
9481 if !__environ.is_null() {
9482 let mut e = __environ;
9483 while !(*e).is_null() {
9484 if strncmp(s as *const u8, *e as *const u8, l + 1) == 0 {
9485 let tmp = *e;
9486 *e = s;
9487 env_rm_add(tmp, r);
9488 return 0;
9489 }
9490 e = e.add(1);
9491 i += 1;
9492 }
9493 }
9494 let newenv = malloc(core::mem::size_of::<*mut c_char>() * (i + 2)) as *mut *mut c_char;
9495 if newenv.is_null() {
9496 if !r.is_null() { free(r as *mut c_void); }
9497 return -1;
9498 }
9499 if i > 0 && !__environ.is_null() {
9500 core::ptr::copy_nonoverlapping(__environ, newenv, i);
9501 }
9502 *newenv.add(i) = s;
9503 *newenv.add(i + 1) = core::ptr::null_mut();
9504 __environ = newenv;
9506 environ = __environ;
9507 if !r.is_null() {
9508 env_rm_add(core::ptr::null_mut(), r);
9509 }
9510 0
9511}
9512
9513#[no_mangle]
9514pub unsafe extern "C" fn putenv(s: *mut c_char) -> c_int {
9515 if s.is_null() { return -1; }
9516 let l = strchrnul_u8(s as *const u8, b'=') as usize - s as *const u8 as usize;
9517 if l == 0 || *s.add(l) as u8 == 0 {
9518 return unsetenv(s);
9519 }
9520 putenv_internal(s, l, core::ptr::null_mut())
9521}
9522
9523#[no_mangle]
9524pub unsafe extern "C" fn unsetenv(name: *const c_char) -> c_int {
9525 if name.is_null() {
9526 ERRNO = EINVAL;
9527 return -1;
9528 }
9529 let name = name as *const u8;
9530 let l = strchrnul_u8(name, b'=') as usize - name as usize;
9531 if l == 0 || *name.add(l) != 0 {
9532 ERRNO = EINVAL;
9533 return -1;
9534 }
9535 if __environ.is_null() {
9536 return 0;
9537 }
9538 let mut e = __environ;
9539 let mut eo = e;
9540 while !(*e).is_null() {
9541 if strncmp(name, *e as *const u8, l) == 0 && *(*e as *const u8).add(l) == b'=' {
9542 env_rm_add(*e, core::ptr::null_mut());
9543 } else {
9544 if eo != e {
9545 *eo = *e;
9546 }
9547 eo = eo.add(1);
9548 }
9549 e = e.add(1);
9550 }
9551 if eo != e {
9552 *eo = core::ptr::null_mut();
9553 }
9554 environ = __environ;
9555 0
9556}
9557
9558#[no_mangle]
9559pub unsafe extern "C" fn clearenv() -> c_int {
9560 let e = __environ;
9561 __environ = core::ptr::null_mut();
9562 environ = core::ptr::null_mut();
9563 if !e.is_null() {
9564 let mut p = e;
9565 while !(*p).is_null() {
9566 env_rm_add(*p, core::ptr::null_mut());
9567 p = p.add(1);
9568 }
9569 }
9570 0
9571}
9572
9573static mut RANDOM_INIT: [u32; 32] = [
9579 0x00000000,0x5851f42d,0xc0b18ccf,0xcbb5f646,
9580 0xc7033129,0x30705b04,0x20fd5db4,0x9a8b7f78,
9581 0x502959d8,0xab894868,0x6c0356a7,0x88cdb7ff,
9582 0xb477d43f,0x70a3a52b,0xa8e4baf1,0xfd8341fc,
9583 0x8ae16fd9,0x742d2f7a,0x0d1f0796,0x76035e09,
9584 0x40f7702c,0x6fa72ca5,0xaaa84157,0x58a0df74,
9585 0xc74a0364,0xae533cc4,0x04185faf,0x6de3b115,
9586 0x0cab8628,0xf043bfa4,0x398150e9,0x37521657,
9587];
9588
9589static mut RANDOM_N: i32 = 31;
9590static mut RANDOM_I: i32 = 3;
9591static mut RANDOM_J: i32 = 0;
9592static mut RANDOM_X: *mut u32 = unsafe { core::ptr::addr_of_mut!(RANDOM_INIT).cast::<u32>().add(1) };
9593
9594unsafe fn random_lcg31(x: u32) -> u32 {
9595 (1103515245u32.wrapping_mul(x).wrapping_add(12345)) & 0x7fffffff
9596}
9597
9598unsafe fn random_lcg64(x: u64) -> u64 {
9599 6364136223846793005u64.wrapping_mul(x).wrapping_add(1)
9600}
9601
9602unsafe fn random_savestate() -> *mut u8 {
9603 (*RANDOM_X.offset(-1)) = ((RANDOM_N as u32) << 16) | ((RANDOM_I as u32) << 8) | (RANDOM_J as u32);
9604 RANDOM_X.offset(-1) as *mut u8
9605}
9606
9607unsafe fn random_loadstate(state: *mut u32) {
9608 RANDOM_X = state.add(1);
9609 RANDOM_N = ((*RANDOM_X.offset(-1)) >> 16) as i32;
9610 RANDOM_I = (((*RANDOM_X.offset(-1)) >> 8) & 0xff) as i32;
9611 RANDOM_J = ((*RANDOM_X.offset(-1)) & 0xff) as i32;
9612}
9613
9614unsafe fn random_srandom_inner(seed: u32) {
9615 let mut s = seed as u64;
9616 if RANDOM_N == 0 {
9617 *RANDOM_X = s as u32;
9618 return;
9619 }
9620 RANDOM_I = if RANDOM_N == 31 || RANDOM_N == 7 { 3 } else { 1 };
9621 RANDOM_J = 0;
9622 for k in 0..RANDOM_N as usize {
9623 s = random_lcg64(s);
9624 *RANDOM_X.add(k) = (s >> 32) as u32;
9625 }
9626 *RANDOM_X |= 1;
9627}
9628
9629#[no_mangle]
9630pub unsafe extern "C" fn srandom(seed: c_uint) {
9631 random_srandom_inner(seed);
9632}
9633
9634#[no_mangle]
9635pub unsafe extern "C" fn initstate(seed: c_uint, state: *mut c_char, size: usize) -> *mut c_char {
9636 if size < 8 { return core::ptr::null_mut(); }
9637 let old = random_savestate();
9638 RANDOM_N = if size < 32 { 0 }
9639 else if size < 64 { 7 }
9640 else if size < 128 { 15 }
9641 else if size < 256 { 31 }
9642 else { 63 };
9643 RANDOM_X = (state as *mut u32).add(1);
9644 random_srandom_inner(seed);
9645 random_savestate();
9646 old as *mut c_char
9647}
9648
9649#[no_mangle]
9650pub unsafe extern "C" fn setstate(state: *mut c_char) -> *mut c_char {
9651 let old = random_savestate();
9652 random_loadstate(state as *mut u32);
9653 old as *mut c_char
9654}
9655
9656#[no_mangle]
9657pub unsafe extern "C" fn random() -> c_long {
9658 let k: c_long;
9659 if RANDOM_N == 0 {
9660 *RANDOM_X = random_lcg31(*RANDOM_X);
9661 k = *RANDOM_X as c_long;
9662 } else {
9663 *RANDOM_X.add(RANDOM_I as usize) = (*RANDOM_X.add(RANDOM_I as usize)).wrapping_add(*RANDOM_X.add(RANDOM_J as usize));
9664 k = (*RANDOM_X.add(RANDOM_I as usize) >> 1) as c_long;
9665 RANDOM_I += 1;
9666 if RANDOM_I == RANDOM_N { RANDOM_I = 0; }
9667 RANDOM_J += 1;
9668 if RANDOM_J == RANDOM_N { RANDOM_J = 0; }
9669 }
9670 k
9671}
9672
9673const SA: u8 = 0xC2;
9678const SB: u8 = 0xF4;
9679
9680const BITTAB: [u32; 51] = [
9681 0xC000_0002, 0xC000_0003, 0xC000_0004, 0xC000_0005, 0xC000_0006, 0xC000_0007,
9682 0xC000_0008, 0xC000_0009, 0xC000_000A, 0xC000_000B, 0xC000_000C, 0xC000_000D,
9683 0xC000_000E, 0xC000_000F, 0xC000_0010, 0xC000_0011, 0xC000_0012, 0xC000_0013,
9684 0xC000_0014, 0xC000_0015, 0xC000_0016, 0xC000_0017, 0xC000_0018, 0xC000_0019,
9685 0xC000_001A, 0xC000_001B, 0xC000_001C, 0xC000_001D, 0xC000_001E, 0xC000_001F,
9686 0xB300_0000, 0xC300_0001, 0xC300_0002, 0xC300_0003, 0xC300_0004, 0xC300_0005,
9687 0xC300_0006, 0xC300_0007, 0xC300_0008, 0xC300_0009, 0xC300_000A, 0xC300_000B,
9688 0xC300_000C, 0xD300_000D, 0xC300_000E, 0xC300_000F, 0xBB0C_0000, 0xC30C_0001,
9689 0xC30C_0002, 0xC30C_0003, 0xDB0C_0004,
9690];
9691
9692#[inline]
9693fn mb_oob(c: u32, b: u8) -> u32 {
9694 let b3 = (b >> 3) as u32;
9695 ((b3.wrapping_sub(0x10)) | (b3.wrapping_add((c as i32 >> 26) as u32))) & !7
9696}
9697
9698static mut MB_STATE: c_uint = 0;
9699
9700const MB_CUR_MAX_VAL_UTF8: usize = 4;
9701const MB_CUR_MAX_VAL_C: usize = 1;
9702
9703#[no_mangle]
9704pub extern "C" fn __ctype_get_mb_cur_max() -> usize {
9705 unsafe { if LOCALE_CTYPE_UTF8 { MB_CUR_MAX_VAL_UTF8 } else { MB_CUR_MAX_VAL_C } }
9706}
9707
9708#[no_mangle]
9709pub unsafe extern "C" fn mbrtowc(
9710 wc: *mut c_int,
9711 src: *const c_char,
9712 n: usize,
9713 st: *mut c_uint,
9714) -> usize {
9715 let s = src as *const u8;
9716 let n0 = n;
9717 let mut dummy: c_int = 0;
9718 let wc = if wc.is_null() { &mut dummy } else { &mut *wc };
9719 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
9720
9721 let mut c: u32 = *st;
9722 let mut s = s;
9723 let mut n = n;
9724
9725 if s.is_null() {
9726 if c != 0 { *st = 0; ERRNO = EILSEQ; return !0usize; }
9727 return 0;
9728 }
9729
9730 if n == 0 { return !1usize; }
9731
9732 if unsafe { !LOCALE_CTYPE_UTF8 } {
9733 let b = *s;
9734 *wc = b as c_int;
9735 return if b == 0 { 0 } else { 1 };
9736 }
9737
9738 if c == 0 {
9739 if *s < 0x80 {
9740 let r = if *s == 0 { 0 } else { 1 };
9741 *wc = *s as c_int;
9742 return r;
9743 }
9744 if (*s).wrapping_sub(SA) as u32 > (SB - SA) as u32 {
9745 *st = 0; ERRNO = EILSEQ; return !0usize;
9746 }
9747 c = BITTAB[*s as usize - SA as usize];
9748 s = s.add(1);
9749 n -= 1;
9750 }
9751
9752 if n > 0 {
9753 if mb_oob(c, *s) != 0 {
9754 *st = 0; ERRNO = EILSEQ; return !0usize;
9755 }
9756 loop {
9757 c = (c << 6) | (*s as u32).wrapping_sub(0x80);
9758 s = s.add(1);
9759 n -= 1;
9760 if c & (1u32 << 31) == 0 {
9761 *st = 0;
9762 *wc = c as c_int;
9763 return n0 - n;
9764 }
9765 if n == 0 { break; }
9766 if (*s).wrapping_sub(0x80) >= 0x40 {
9767 *st = 0; ERRNO = EILSEQ; return !0usize;
9768 }
9769 }
9770 }
9771
9772 *st = c;
9773 !1usize
9774}
9775
9776#[no_mangle]
9777pub unsafe extern "C" fn wcrtomb(
9778 s: *mut c_char,
9779 wc: c_int,
9780 _st: *mut c_uint,
9781) -> usize {
9782 if s.is_null() { return 1; }
9783 let wc_u = wc as u32;
9784 if unsafe { !LOCALE_CTYPE_UTF8 } {
9785 if wc_u > 0xFF {
9786 ERRNO = EILSEQ;
9787 return !0usize;
9788 }
9789 *s = wc as c_char;
9790 return 1;
9791 }
9792 if wc_u < 0x80 {
9793 *s = wc as c_char;
9794 return 1;
9795 }
9796 if wc_u < 0x800 {
9797 *s = (0xC0 | (wc_u >> 6)) as c_char;
9798 *s.add(1) = (0x80 | (wc_u & 0x3F)) as c_char;
9799 return 2;
9800 }
9801 if wc_u < 0xD800 || wc_u.wrapping_sub(0xE000) < 0x2000 {
9802 *s = (0xE0 | (wc_u >> 12)) as c_char;
9803 *s.add(1) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
9804 *s.add(2) = (0x80 | (wc_u & 0x3F)) as c_char;
9805 return 3;
9806 }
9807 if wc_u.wrapping_sub(0x10000) < 0x100000 {
9808 *s = (0xF0 | (wc_u >> 18)) as c_char;
9809 *s.add(1) = (0x80 | ((wc_u >> 12) & 0x3F)) as c_char;
9810 *s.add(2) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
9811 *s.add(3) = (0x80 | (wc_u & 0x3F)) as c_char;
9812 return 4;
9813 }
9814 ERRNO = EILSEQ;
9815 !0usize
9816}
9817
9818#[no_mangle]
9819pub unsafe extern "C" fn mblen(s: *const c_char, n: usize) -> c_int {
9820 if s.is_null() { return 0; }
9821 mbtowc(core::ptr::null_mut(), s, n)
9822}
9823
9824#[no_mangle]
9825pub unsafe extern "C" fn mbtowc(
9826 wc: *mut c_int,
9827 src: *const c_char,
9828 n: usize,
9829) -> c_int {
9830 if src.is_null() { return 0; }
9831 if n == 0 { ERRNO = EILSEQ; return -1; }
9832 let mut state: c_uint = 0;
9833 let mut w: c_int = 0;
9834 let r = mbrtowc(&mut w, src, n, &mut state);
9835 if r == !0usize { return -1; }
9836 if !wc.is_null() { *wc = w; }
9837 r as c_int
9838}
9839
9840#[no_mangle]
9841pub unsafe extern "C" fn wctomb(s: *mut c_char, wc: c_int) -> c_int {
9842 if s.is_null() { return 0; }
9843 wcrtomb(s, wc, core::ptr::null_mut()) as c_int
9844}
9845
9846#[no_mangle]
9847pub unsafe extern "C" fn mbsrtowcs(
9848 ws: *mut c_int,
9849 src: *mut *const c_char,
9850 wn: usize,
9851 st: *mut c_uint,
9852) -> usize {
9853 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
9854 let mut s = *src as *const u8;
9855 let wn0 = wn;
9856 let mut wn = wn;
9857
9858 if ws.is_null() {
9859 while *s != 0 {
9860 if *s < 0x80 {
9861 s = s.add(1);
9862 wn = wn.wrapping_sub(1);
9863 continue;
9864 }
9865 let mut wc: c_int = 0;
9866 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
9867 if r == !0usize { return !0usize; }
9868 if r == !1usize { return wn0 - wn; }
9869 s = s.add(r);
9870 wn = wn.wrapping_sub(1);
9871 }
9872 wn0 - wn
9873 } else {
9874 let mut w = ws;
9875 while wn > 0 {
9876 if *s < 0x80 {
9877 let c = *s as c_int;
9878 *w = c;
9879 if c == 0 {
9880 *src = core::ptr::null();
9881 return wn0 - wn;
9882 }
9883 w = w.add(1);
9884 s = s.add(1);
9885 wn -= 1;
9886 continue;
9887 }
9888 let mut wc: c_int = 0;
9889 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
9890 if r == !0usize {
9891 *src = s as *const c_char;
9892 return !0usize;
9893 }
9894 if r == !1usize {
9895 *src = s as *const c_char;
9896 return wn0 - wn;
9897 }
9898 *w = wc;
9899 w = w.add(1);
9900 s = s.add(r);
9901 wn -= 1;
9902 }
9903 *src = s as *const c_char;
9904 wn0 - wn
9905 }
9906}
9907
9908#[no_mangle]
9909pub unsafe extern "C" fn wcsrtombs(
9910 s: *mut c_char,
9911 ws: *mut *const c_int,
9912 n: usize,
9913 _st: *mut c_uint,
9914) -> usize {
9915 let mut w = *ws;
9916 let n0 = n;
9917 let mut n = n;
9918
9919 if s.is_null() {
9920 let mut count = 0usize;
9921 while *w != 0 {
9922 if (*w as u32) < 0x80 {
9923 count += 1;
9924 } else {
9925 let mut buf = [0u8; 4];
9926 let r = wcrtomb(buf.as_mut_ptr() as *mut c_char, *w, core::ptr::null_mut());
9927 if r == !0usize { return !0usize; }
9928 count += r;
9929 }
9930 w = w.add(1);
9931 }
9932 return count;
9933 }
9934
9935 let mut dst = s;
9936 while n > 0 {
9937 if (*w as u32) < 0x80 {
9938 *dst = *w as c_char;
9939 if *w == 0 {
9940 *ws = core::ptr::null();
9941 return n0 - n;
9942 }
9943 dst = dst.add(1);
9944 n -= 1;
9945 } else {
9946 let r = wcrtomb(dst, *w, core::ptr::null_mut());
9947 if r == !0usize {
9948 *ws = w;
9949 return !0usize;
9950 }
9951 if r > n {
9952 *ws = w;
9953 return n0 - n;
9954 }
9955 dst = dst.add(r);
9956 n -= r;
9957 }
9958 w = w.add(1);
9959 }
9960 *ws = w;
9961 n0
9962}
9963
9964#[no_mangle]
9965pub unsafe extern "C" fn mbstowcs(
9966 ws: *mut c_int,
9967 src: *const c_char,
9968 wn: usize,
9969) -> usize {
9970 let mut src_ptr = src;
9971 mbsrtowcs(ws, &mut src_ptr, wn, core::ptr::null_mut())
9972}
9973
9974#[no_mangle]
9975pub unsafe extern "C" fn wcstombs(
9976 s: *mut c_char,
9977 ws: *const c_int,
9978 n: usize,
9979) -> usize {
9980 let mut ws_ptr = ws;
9981 wcsrtombs(s, &mut ws_ptr, n, core::ptr::null_mut())
9982}
9983
9984#[no_mangle]
9989pub extern "C" fn btowc(c: c_int) -> wint_t {
9990 if c == -1 { return WEOF; }
9991 unsafe {
9992 if LOCALE_CTYPE_UTF8 {
9993 if (c as u32) < 128 { c as wint_t } else { WEOF }
9994 } else {
9995 (c as u8) as wint_t
9996 }
9997 }
9998}
9999
10000#[no_mangle]
10001pub extern "C" fn wctob(c: wint_t) -> c_int {
10002 unsafe {
10003 if LOCALE_CTYPE_UTF8 {
10004 if c < 128 { c as c_int } else { -1 }
10005 } else {
10006 if c <= 0xFF { c as c_int } else { -1 }
10007 }
10008 }
10009}
10010
10011#[no_mangle]
10012pub unsafe extern "C" fn mbsinit(s: *const c_uint) -> c_int {
10013 if s.is_null() || *s == 0 { 1 } else { 0 }
10014}
10015
10016#[no_mangle]
10017pub unsafe extern "C" fn mbrlen(s: *const c_char, n: usize, ps: *mut c_uint) -> usize {
10018 mbrtowc(core::ptr::null_mut(), s, n, ps)
10019}
10020
10021#[no_mangle]
10026pub unsafe extern "C" fn wcslen(s: *const wchar_t) -> usize {
10027 let mut len = 0;
10028 while *s.add(len) != 0 { len += 1; }
10029 len
10030}
10031
10032#[no_mangle]
10033pub unsafe extern "C" fn wcschr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
10034 let mut i = 0;
10035 loop {
10036 let ch = *s.add(i);
10037 if ch == c { return s.add(i) as *mut wchar_t; }
10038 if ch == 0 { return null_mut(); }
10039 i += 1;
10040 }
10041}
10042
10043#[no_mangle]
10044pub unsafe extern "C" fn wcsrchr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
10045 let mut i = 0;
10046 let mut last: *mut wchar_t = null_mut();
10047 loop {
10048 let ch = *s.add(i);
10049 if ch == c { last = s.add(i) as *mut wchar_t; }
10050 if ch == 0 { return last; }
10051 i += 1;
10052 }
10053}
10054
10055#[no_mangle]
10056pub unsafe extern "C" fn wcsstr(haystack: *const wchar_t, needle: *const wchar_t) -> *mut wchar_t {
10057 if *needle == 0 { return haystack as *mut wchar_t; }
10058 let mut i = 0;
10059 loop {
10060 let h = *haystack.add(i);
10061 if h == 0 { return null_mut(); }
10062 if h == *needle {
10063 let mut j = 0;
10064 loop {
10065 let n = *needle.add(j);
10066 if n == 0 { return haystack.add(i) as *mut wchar_t; }
10067 if *haystack.add(i + j) != n { break; }
10068 j += 1;
10069 }
10070 }
10071 i += 1;
10072 }
10073}
10074
10075#[no_mangle]
10076pub unsafe extern "C" fn wcscmp(s1: *const wchar_t, s2: *const wchar_t) -> c_int {
10077 let mut i = 0;
10078 loop {
10079 let a = *s1.add(i);
10080 let b = *s2.add(i);
10081 if a != b { return a - b; }
10082 if a == 0 { return 0; }
10083 i += 1;
10084 }
10085}
10086
10087#[no_mangle]
10088pub unsafe extern "C" fn wcsncmp(s1: *const wchar_t, s2: *const wchar_t, n: usize) -> c_int {
10089 let mut i = 0;
10090 while i < n {
10091 let a = *s1.add(i);
10092 let b = *s2.add(i);
10093 if a != b { return a - b; }
10094 if a == 0 { return 0; }
10095 i += 1;
10096 }
10097 0
10098}
10099
10100#[no_mangle]
10101pub unsafe extern "C" fn wcscpy(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
10102 let mut i = 0;
10103 loop {
10104 let c = *src.add(i);
10105 *dst.add(i) = c;
10106 if c == 0 { break; }
10107 i += 1;
10108 }
10109 dst
10110}
10111
10112#[no_mangle]
10113pub unsafe extern "C" fn wcsncpy(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
10114 let mut i = 0;
10115 while i < n && *src.add(i) != 0 { *dst.add(i) = *src.add(i); i += 1; }
10116 while i < n { *dst.add(i) = 0; i += 1; }
10117 dst
10118}
10119
10120#[no_mangle]
10121pub unsafe extern "C" fn wcscat(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
10122 let mut i = 0;
10123 while *dst.add(i) != 0 { i += 1; }
10124 let mut j = 0;
10125 loop {
10126 let c = *src.add(j);
10127 *dst.add(i + j) = c;
10128 if c == 0 { break; }
10129 j += 1;
10130 }
10131 dst
10132}
10133
10134#[no_mangle]
10135pub unsafe extern "C" fn wcsncat(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
10136 let mut i = 0;
10137 while *dst.add(i) != 0 { i += 1; }
10138 let mut j = 0;
10139 while j < n && *src.add(j) != 0 { *dst.add(i + j) = *src.add(j); j += 1; }
10140 *dst.add(i + j) = 0;
10141 dst
10142}
10143
10144#[no_mangle]
10145pub unsafe extern "C" fn wcsdup(s: *const wchar_t) -> *mut wchar_t {
10146 let len = wcslen(s);
10147 let p = malloc((len + 1) * core::mem::size_of::<wchar_t>()) as *mut wchar_t;
10148 if p.is_null() { return null_mut(); }
10149 core::ptr::copy_nonoverlapping(s, p, len + 1);
10150 p
10151}
10152
10153#[no_mangle]
10154pub unsafe extern "C" fn wcsnlen(s: *const wchar_t, maxlen: usize) -> usize {
10155 let mut i = 0;
10156 while i < maxlen && *s.add(i) != 0 { i += 1; }
10157 i
10158}
10159
10160#[no_mangle]
10161pub unsafe extern "C" fn wcsspn(s: *const wchar_t, accept: *const wchar_t) -> usize {
10162 let mut i = 0;
10163 loop {
10164 let c = *s.add(i);
10165 if c == 0 { return i; }
10166 let mut found = false;
10167 let mut j = 0;
10168 loop {
10169 let a = *accept.add(j);
10170 if a == 0 { break; }
10171 if c == a { found = true; break; }
10172 j += 1;
10173 }
10174 if !found { return i; }
10175 i += 1;
10176 }
10177}
10178
10179#[no_mangle]
10180pub unsafe extern "C" fn wcscspn(s: *const wchar_t, reject: *const wchar_t) -> usize {
10181 let mut i = 0;
10182 loop {
10183 let c = *s.add(i);
10184 if c == 0 { return i; }
10185 let mut j = 0;
10186 loop {
10187 let r = *reject.add(j);
10188 if r == 0 { break; }
10189 if c == r { return i; }
10190 j += 1;
10191 }
10192 i += 1;
10193 }
10194}
10195
10196#[no_mangle]
10197pub unsafe extern "C" fn wcspbrk(s: *const wchar_t, accept: *const wchar_t) -> *mut wchar_t {
10198 let mut i = 0;
10199 loop {
10200 let c = *s.add(i);
10201 if c == 0 { return null_mut(); }
10202 let mut j = 0;
10203 loop {
10204 let a = *accept.add(j);
10205 if a == 0 { break; }
10206 if c == a { return s.add(i) as *mut wchar_t; }
10207 j += 1;
10208 }
10209 i += 1;
10210 }
10211}
10212
10213#[no_mangle]
10214pub unsafe extern "C" fn wcsxfrm(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> usize {
10215 let len = wcslen(src);
10216 if !dst.is_null() {
10217 let copy = if len < n { len } else { if n > 0 { n - 1 } else { 0 } };
10218 for i in 0..copy { *dst.add(i) = *src.add(i); }
10219 if n > 0 { *dst.add(copy) = 0; }
10220 }
10221 len
10222}
10223
10224unsafe fn wcs_to_bytes(ws: *const wchar_t, buf: *mut u8, bufsz: usize) -> usize {
10229 let mut i = 0;
10230 while i < bufsz - 1 {
10231 let c = *ws.add(i);
10232 if c == 0 { break; }
10233 if (c as u32) > 127 { break; }
10234 *buf.add(i) = c as u8;
10235 i += 1;
10236 }
10237 *buf.add(i) = 0;
10238 i
10239}
10240
10241#[no_mangle]
10242pub unsafe extern "C" fn wcstol(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_long {
10243 let mut buf = [0u8; 256];
10244 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10245 let mut end: *mut c_char = core::ptr::null_mut();
10246 let r = strtol(buf.as_ptr() as *const c_char, &mut end, base);
10247 if !endptr.is_null() {
10248 let offset = end as usize - buf.as_ptr() as usize;
10249 *endptr = s.add(offset) as *mut wchar_t;
10250 }
10251 r
10252}
10253
10254#[no_mangle]
10255pub unsafe extern "C" fn wcstoul(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulong {
10256 let mut buf = [0u8; 256];
10257 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10258 let mut end: *mut c_char = core::ptr::null_mut();
10259 let r = strtoul(buf.as_ptr() as *const c_char, &mut end, base);
10260 if !endptr.is_null() {
10261 let offset = end as usize - buf.as_ptr() as usize;
10262 *endptr = s.add(offset) as *mut wchar_t;
10263 }
10264 r
10265}
10266
10267#[no_mangle]
10268pub unsafe extern "C" fn wcstoll(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong {
10269 let mut buf = [0u8; 256];
10270 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10271 let mut end: *mut c_char = core::ptr::null_mut();
10272 let r = strtoll(buf.as_ptr() as *const c_char, &mut end, base);
10273 if !endptr.is_null() {
10274 let offset = end as usize - buf.as_ptr() as usize;
10275 *endptr = s.add(offset) as *mut wchar_t;
10276 }
10277 r
10278}
10279
10280#[no_mangle]
10281pub unsafe extern "C" fn wcstoull(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong {
10282 let mut buf = [0u8; 256];
10283 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10284 let mut end: *mut c_char = core::ptr::null_mut();
10285 let r = strtoull(buf.as_ptr() as *const c_char, &mut end, base);
10286 if !endptr.is_null() {
10287 let offset = end as usize - buf.as_ptr() as usize;
10288 *endptr = s.add(offset) as *mut wchar_t;
10289 }
10290 r
10291}
10292
10293#[no_mangle]
10294pub unsafe extern "C" fn wcstod(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 {
10295 let mut buf = [0u8; 256];
10296 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10297 let mut end: *mut c_char = core::ptr::null_mut();
10298 let r = strtod(buf.as_ptr() as *const c_char, &mut end);
10299 if !endptr.is_null() {
10300 let offset = end as usize - buf.as_ptr() as usize;
10301 *endptr = s.add(offset) as *mut wchar_t;
10302 }
10303 r
10304}
10305
10306#[no_mangle]
10307pub unsafe extern "C" fn wcstof(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f32 { wcstod(s, endptr) as f32 }
10308
10309#[no_mangle]
10310#[cfg(target_arch = "x86_64")]
10311pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 { wcstod(s, endptr) }
10312
10313#[no_mangle]
10314#[cfg(target_arch = "aarch64")]
10315pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
10316
10317#[no_mangle]
10318#[cfg(target_arch = "riscv64")]
10319pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
10320
10321#[no_mangle]
10322pub unsafe extern "C" fn wcstoimax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong { wcstoll(s, endptr, base) }
10323
10324#[no_mangle]
10325pub unsafe extern "C" fn wcstoumax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong { wcstoull(s, endptr, base) }
10326
10327const WC_ALPHA: c_int = 1;
10332const WC_DIGIT: c_int = 2;
10333const WC_SPACE: c_int = 4;
10334const WC_UPPER: c_int = 8;
10335const WC_LOWER: c_int = 16;
10336const WC_ALNUM: c_int = WC_ALPHA | WC_DIGIT;
10337const WC_BLANK: c_int = 32;
10338const WC_CNTRL: c_int = 64;
10339const WC_PUNCT: c_int = 128;
10340const WC_GRAPH: c_int = WC_ALNUM | WC_PUNCT;
10341const WC_PRINT: c_int = WC_GRAPH | WC_BLANK;
10342const WC_XDIGIT: c_int = 256;
10343
10344fn wc_flags(c: wint_t) -> c_int {
10345 if c < 128 {
10346 let f = CT_TABLE[c as usize];
10347 let mut r = 0;
10348 if f & (CT_UPPER | CT_LOWER) != 0 { r |= WC_ALPHA; }
10349 if f & CT_DIGIT != 0 { r |= WC_DIGIT; }
10350 if f & CT_SPACE != 0 { r |= WC_SPACE; }
10351 if f & CT_UPPER != 0 { r |= WC_UPPER; }
10352 if f & CT_LOWER != 0 { r |= WC_LOWER; }
10353 if f & CT_BLANK != 0 { r |= WC_BLANK; }
10354 if f & CT_CNTRL != 0 { r |= WC_CNTRL; }
10355 if f & CT_PUNCT != 0 { r |= WC_PUNCT; }
10356 if f & CT_XDIGIT != 0 { r |= WC_XDIGIT; }
10357 r
10358 } else {
10359 if c < 0x100 { 0 }
10360 else { WC_PRINT | WC_ALPHA }
10361 }
10362}
10363
10364#[no_mangle]
10365pub extern "C" fn iswalnum(c: wint_t) -> c_int { (wc_flags(c) & WC_ALNUM != 0) as c_int }
10366#[no_mangle]
10367pub extern "C" fn iswalpha(c: wint_t) -> c_int { (wc_flags(c) & WC_ALPHA != 0) as c_int }
10368#[no_mangle]
10369pub extern "C" fn iswblank(c: wint_t) -> c_int { (wc_flags(c) & WC_BLANK != 0) as c_int }
10370#[no_mangle]
10371pub extern "C" fn iswcntrl(c: wint_t) -> c_int { (wc_flags(c) & WC_CNTRL != 0) as c_int }
10372#[no_mangle]
10373pub extern "C" fn iswdigit(c: wint_t) -> c_int { ((c >= b'0' as wint_t) && (c <= b'9' as wint_t)) as c_int }
10374#[no_mangle]
10375pub extern "C" fn iswgraph(c: wint_t) -> c_int { (wc_flags(c) & WC_GRAPH != 0) as c_int }
10376#[no_mangle]
10377pub extern "C" fn iswlower(c: wint_t) -> c_int { (wc_flags(c) & WC_LOWER != 0) as c_int }
10378#[no_mangle]
10379pub extern "C" fn iswprint(c: wint_t) -> c_int {
10380 if c < 128 { (wc_flags(c) & WC_PRINT != 0) as c_int }
10381 else if c >= 0x100 && c < 0x110000 { 1 }
10382 else { 0 }
10383}
10384#[no_mangle]
10385pub extern "C" fn iswpunct(c: wint_t) -> c_int { (wc_flags(c) & WC_PUNCT != 0) as c_int }
10386#[no_mangle]
10387pub extern "C" fn iswspace(c: wint_t) -> c_int {
10388 if c < 128 { (wc_flags(c) & WC_SPACE != 0) as c_int }
10389 else {
10390 match c {
10391 0x1680 | 0x2000..=0x200A | 0x2028 | 0x2029 | 0x202F | 0x205F | 0x3000 => 1,
10392 _ => 0,
10393 }
10394 }
10395}
10396#[no_mangle]
10397pub extern "C" fn iswupper(c: wint_t) -> c_int { (wc_flags(c) & WC_UPPER != 0) as c_int }
10398#[no_mangle]
10399pub extern "C" fn iswxdigit(c: wint_t) -> c_int { (wc_flags(c) & WC_XDIGIT != 0) as c_int }
10400
10401static WCTYPE_ALNUM: c_int = WC_ALNUM;
10402static WCTYPE_ALPHA: c_int = WC_ALPHA;
10403static WCTYPE_BLANK: c_int = WC_BLANK;
10404static WCTYPE_CNTRL: c_int = WC_CNTRL;
10405static WCTYPE_DIGIT: c_int = WC_DIGIT;
10406static WCTYPE_GRAPH: c_int = WC_GRAPH;
10407static WCTYPE_LOWER: c_int = WC_LOWER;
10408static WCTYPE_PRINT: c_int = WC_PRINT;
10409static WCTYPE_PUNCT: c_int = WC_PUNCT;
10410static WCTYPE_SPACE: c_int = WC_SPACE;
10411static WCTYPE_UPPER: c_int = WC_UPPER;
10412static WCTYPE_XDIGIT: c_int = WC_XDIGIT;
10413
10414#[no_mangle]
10415pub unsafe extern "C" fn wctype(name: *const c_char) -> wctype_t {
10416 if name.is_null() { return core::ptr::null(); }
10417 let n = name as *const u8;
10418 if strcmp(n, b"alnum\0".as_ptr()) == 0 { return &WCTYPE_ALNUM; }
10419 if strcmp(n, b"alpha\0".as_ptr()) == 0 { return &WCTYPE_ALPHA; }
10420 if strcmp(n, b"blank\0".as_ptr()) == 0 { return &WCTYPE_BLANK; }
10421 if strcmp(n, b"cntrl\0".as_ptr()) == 0 { return &WCTYPE_CNTRL; }
10422 if strcmp(n, b"digit\0".as_ptr()) == 0 { return &WCTYPE_DIGIT; }
10423 if strcmp(n, b"graph\0".as_ptr()) == 0 { return &WCTYPE_GRAPH; }
10424 if strcmp(n, b"lower\0".as_ptr()) == 0 { return &WCTYPE_LOWER; }
10425 if strcmp(n, b"print\0".as_ptr()) == 0 { return &WCTYPE_PRINT; }
10426 if strcmp(n, b"punct\0".as_ptr()) == 0 { return &WCTYPE_PUNCT; }
10427 if strcmp(n, b"space\0".as_ptr()) == 0 { return &WCTYPE_SPACE; }
10428 if strcmp(n, b"upper\0".as_ptr()) == 0 { return &WCTYPE_UPPER; }
10429 if strcmp(n, b"xdigit\0".as_ptr()) == 0 { return &WCTYPE_XDIGIT; }
10430 core::ptr::null()
10431}
10432
10433#[no_mangle]
10434pub unsafe extern "C" fn iswctype(c: wint_t, desc: wctype_t) -> c_int {
10435 if desc.is_null() { return 0; }
10436 (wc_flags(c) & *desc != 0) as c_int
10437}
10438
10439static WCTRANS_LOWER: c_int = 1;
10440static WCTRANS_UPPER: c_int = 2;
10441
10442#[no_mangle]
10443pub unsafe extern "C" fn towlower(c: wint_t) -> wint_t {
10444 if c < 128 { tolower(c as c_int) as wint_t } else { c }
10445}
10446
10447#[no_mangle]
10448pub unsafe extern "C" fn towupper(c: wint_t) -> wint_t {
10449 if c < 128 { toupper(c as c_int) as wint_t } else { c }
10450}
10451
10452#[no_mangle]
10453pub unsafe extern "C" fn wctrans(name: *const c_char) -> wctrans_t {
10454 if name.is_null() { return core::ptr::null(); }
10455 let n = name as *const u8;
10456 if strcmp(n, b"tolower\0".as_ptr()) == 0 { return &WCTRANS_LOWER; }
10457 if strcmp(n, b"toupper\0".as_ptr()) == 0 { return &WCTRANS_UPPER; }
10458 core::ptr::null()
10459}
10460
10461#[no_mangle]
10462pub unsafe extern "C" fn towctrans(c: wint_t, desc: wctrans_t) -> wint_t {
10463 if desc.is_null() { return c; }
10464 match *desc {
10465 1 => towlower(c),
10466 2 => towupper(c),
10467 _ => c,
10468 }
10469}
10470
10471#[no_mangle]
10476pub unsafe extern "C" fn fgetwc(f: *mut FILE) -> wint_t {
10477 let mut state: c_uint = 0;
10478 let mut wc: wchar_t = 0;
10479 let mut buf = [0u8; 4];
10480 let c = fgetc(f);
10481 if c == -1 { return WEOF; }
10482 buf[0] = c as u8;
10483 if buf[0] < 0x80 { return buf[0] as wint_t; }
10484 let len = if buf[0] < 0xE0 { 2 } else if buf[0] < 0xF0 { 3 } else { 4 };
10485 let mut n = 1usize;
10486 while n < len {
10487 let c2 = fgetc(f);
10488 if c2 == -1 { return WEOF; }
10489 buf[n] = c2 as u8;
10490 n += 1;
10491 }
10492 let r = mbrtowc(&mut wc, buf.as_ptr() as *const c_char, n, &mut state);
10493 if r == !0usize || r == !1usize { WEOF } else { wc as wint_t }
10494}
10495
10496#[no_mangle]
10497pub unsafe extern "C" fn fputwc(c: wchar_t, f: *mut FILE) -> wint_t {
10498 let mut buf = [0u8; 4];
10499 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c, core::ptr::null_mut());
10500 if n == !0usize || n == 0 { return WEOF; }
10501 if fwrite(buf.as_ptr() as *const c_void, 1, n, f) != n { return WEOF; }
10502 c as wint_t
10503}
10504
10505#[no_mangle]
10506pub unsafe extern "C" fn fputws(s: *const wchar_t, f: *mut FILE) -> c_int {
10507 let mut i = 0;
10508 while *s.add(i) != 0 {
10509 if fputwc(*s.add(i), f) == WEOF { return -1; }
10510 i += 1;
10511 }
10512 0
10513}
10514
10515#[no_mangle]
10516pub unsafe extern "C" fn ungetwc(c: wint_t, f: *mut FILE) -> wint_t {
10517 if c == WEOF { return WEOF; }
10518 let mut buf = [0u8; 4];
10519 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c as wchar_t, core::ptr::null_mut());
10520 if n == !0usize || n == 0 { return WEOF; }
10521 let mut i = n;
10522 while i > 0 {
10523 i -= 1;
10524 if ungetc(buf[i] as c_int, f) == -1 { return WEOF; }
10525 }
10526 c
10527}
10528
10529#[no_mangle]
10530pub unsafe extern "C" fn getwchar() -> wint_t { fgetwc(stdin) }
10531
10532#[no_mangle]
10533pub unsafe extern "C" fn putwchar(c: wchar_t) -> wint_t { fputwc(c, stdout) }
10534
10535unsafe fn wfmt_write_str(dst: *mut wchar_t, pos: usize, cap: usize, s: *const u8, len: usize) -> usize {
10540 let mut i = 0;
10541 while i < len {
10542 if pos + i < cap { *dst.add(pos + i) = *s.add(i) as wchar_t; }
10543 i += 1;
10544 }
10545 pos + len
10546}
10547
10548#[no_mangle]
10549pub unsafe extern "C" fn vswprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, mut args: VaList) -> c_int {
10550 if n == 0 { return -1; }
10551 let cap = n - 1;
10552 let mut pos = 0usize;
10553 let mut fmt_narrow = [0u8; 256];
10555 let mut flen = 0usize;
10556 loop {
10557 let ch = *fmt.add(flen) as u32;
10558 if ch == 0 || flen >= 255 { break; }
10559 fmt_narrow[flen] = if ch < 128 { ch as u8 } else { b'?' };
10560 flen += 1;
10561 }
10562 fmt_narrow[flen] = 0;
10563 let mut fi = 0usize;
10564 macro_rules! wc {
10565 ($c:expr) => { if pos < cap { *s.add(pos) = $c as wchar_t; } pos += 1; }
10566 }
10567 loop {
10568 let c = fmt_narrow[fi];
10569 if c == 0 { break; }
10570 if c != b'%' { wc!(c); fi += 1; continue; }
10571 fi += 1;
10572 let mut flags: u8 = 0;
10573 loop {
10574 match fmt_narrow[fi] {
10575 b'-' => { flags |= FLAG_MINUS; fi += 1; }
10576 b'+' => { flags |= FLAG_PLUS; fi += 1; }
10577 b' ' => { flags |= FLAG_SPACE; fi += 1; }
10578 b'0' => { flags |= FLAG_ZERO; fi += 1; }
10579 b'#' => { flags |= FLAG_HASH; fi += 1; }
10580 _ => break,
10581 }
10582 }
10583 let mut width: usize = 0;
10584 if fmt_narrow[fi] == b'*' {
10585 let w = args.next_arg::<c_int>();
10586 if w < 0 { flags |= FLAG_MINUS; width = (-w) as usize; } else { width = w as usize; }
10587 fi += 1;
10588 } else {
10589 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10590 width = width * 10 + (fmt_narrow[fi] - b'0') as usize; fi += 1;
10591 }
10592 }
10593 let mut precision: i32 = -1;
10594 if fmt_narrow[fi] == b'.' {
10595 fi += 1;
10596 if fmt_narrow[fi] == b'*' {
10597 let p = args.next_arg::<c_int>();
10598 precision = if p < 0 { -1 } else { p }; fi += 1;
10599 } else {
10600 precision = 0;
10601 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10602 precision = precision * 10 + (fmt_narrow[fi] - b'0') as i32; fi += 1;
10603 }
10604 }
10605 }
10606 let len_mod = fmt_narrow[fi];
10607 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' {
10608 fi += 1;
10609 let spec = fmt_narrow[fi];
10610 if (len_mod == b'h' && spec == b'h') || (len_mod == b'l' && spec == b'l') {
10611 fi += 1;
10612 let spec2 = fmt_narrow[fi];
10613 match (len_mod, spec, spec2) {
10614 (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; } }
10615 (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; } }
10616 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
10617 let val = args.next_arg::<c_longlong>();
10618 let neg = val < 0;
10619 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10620 let b = format_u64(abs);
10621 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10622 let mut fbuf = [0u8; 32];
10623 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10624 for k in 0..len { wc!(fbuf[k]); }
10625 }
10626 (b'l', b'l', b'u') => {
10627 let val = args.next_arg::<c_ulonglong>();
10628 let b = format_u64(val as u64);
10629 let mut fbuf = [0u8; 32];
10630 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10631 for k in 0..len { wc!(fbuf[k]); }
10632 }
10633 (b'l', b'l', b'x') => {
10634 let val = args.next_arg::<c_ulonglong>();
10635 let b = format_hex(val as u64, false);
10636 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10637 let mut fbuf = [0u8; 32];
10638 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10639 for k in 0..len { wc!(fbuf[k]); }
10640 }
10641 (b'l', b'l', b'X') => {
10642 let val = args.next_arg::<c_ulonglong>();
10643 let b = format_hex(val as u64, true);
10644 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10645 let mut fbuf = [0u8; 32];
10646 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10647 for k in 0..len { wc!(fbuf[k]); }
10648 }
10649 (b'l', b'l', b'o') => {
10650 let val = args.next_arg::<c_ulonglong>();
10651 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10652 let mut fbuf = [0u8; 32];
10653 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10654 for k in 0..len { wc!(fbuf[k]); }
10655 }
10656 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); wc!(spec2); }
10657 }
10658 } else {
10659 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
10660 match (lm, spec) {
10661 (b'h', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut u16) = pos as u16; } }
10662 (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; } }
10663 (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; } }
10664 (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; } }
10665 (b'l', b'd') | (b'l', b'i') => {
10666 let val = args.next_arg::<c_long>();
10667 let neg = val < 0;
10668 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10669 let b = format_u64(abs);
10670 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10671 let mut fbuf = [0u8; 32];
10672 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10673 for k in 0..len { wc!(fbuf[k]); }
10674 }
10675 (b'l', b'u') => {
10676 let val = args.next_arg::<c_ulong>();
10677 let b = format_u64(val as u64);
10678 let mut fbuf = [0u8; 32];
10679 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10680 for k in 0..len { wc!(fbuf[k]); }
10681 }
10682 (b'l', b'x') => {
10683 let val = args.next_arg::<c_ulong>();
10684 let b = format_hex(val as u64, false);
10685 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10686 let mut fbuf = [0u8; 32];
10687 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10688 for k in 0..len { wc!(fbuf[k]); }
10689 }
10690 (b'l', b'X') => {
10691 let val = args.next_arg::<c_ulong>();
10692 let b = format_hex(val as u64, true);
10693 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10694 let mut fbuf = [0u8; 32];
10695 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10696 for k in 0..len { wc!(fbuf[k]); }
10697 }
10698 (b'l', b'o') => {
10699 let val = args.next_arg::<c_ulong>();
10700 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10701 let mut fbuf = [0u8; 32];
10702 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10703 for k in 0..len { wc!(fbuf[k]); }
10704 }
10705 (b'l', b'c') => {
10706 let ch = args.next_arg::<wint_t>();
10707 wc!(ch);
10708 }
10709 (b'l', b's') => {
10710 let ws_arg = args.next_arg::<*const wchar_t>();
10711 if ws_arg.is_null() {
10712 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
10713 if flags & FLAG_MINUS != 0 {
10714 for k in 0..slen { wc!(b"(null)"[k]); }
10715 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10716 } else {
10717 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10718 for k in 0..slen { wc!(b"(null)"[k]); }
10719 }
10720 } else {
10721 let mut wlen = 0usize;
10722 loop {
10723 let ch = *ws_arg.add(wlen);
10724 if ch == 0 { break; }
10725 if precision >= 0 && wlen >= precision as usize { break; }
10726 wlen += 1;
10727 }
10728 if flags & FLAG_MINUS != 0 {
10729 for k in 0..wlen { wc!(*ws_arg.add(k)); }
10730 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
10731 } else {
10732 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
10733 for k in 0..wlen { wc!(*ws_arg.add(k)); }
10734 }
10735 }
10736 }
10737 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
10738 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
10739 let val = args.next_arg::<f64>();
10740 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
10741 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
10742 let mut fbuf = [0u8; 4224];
10743 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
10744 let mut wbuf = [0u8; 4224];
10745 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
10746 for k in 0..wlen { wc!(wbuf[k]); }
10747 }
10748 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
10749 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
10750 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
10751 let val = {
10752 let lo: u64 = args.next_arg::<u64>();
10753 let hi: u64 = args.next_arg::<u64>();
10754 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
10755 f128::from_bits(combined) as f64
10756 };
10757 #[cfg(target_arch = "x86_64")]
10758 let val = args.next_arg::<f64>();
10759 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
10760 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
10761 let mut fbuf = [0u8; 4224];
10762 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
10763 let mut wbuf = [0u8; 4224];
10764 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
10765 for k in 0..wlen { wc!(wbuf[k]); }
10766 }
10767 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
10768 }
10769 }
10770 } else {
10771 let spec = fmt_narrow[fi];
10772 match spec {
10773 b'd' | b'i' => {
10774 let d = args.next_arg::<c_int>();
10775 let neg = d < 0;
10776 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
10777 let b = format_u64(abs);
10778 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10779 let mut fbuf = [0u8; 32];
10780 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10781 for k in 0..len { wc!(fbuf[k]); }
10782 }
10783 b'u' => {
10784 let u = args.next_arg::<c_uint>();
10785 let b = format_u64(u as u64);
10786 let mut fbuf = [0u8; 32];
10787 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10788 for k in 0..len { wc!(fbuf[k]); }
10789 }
10790 b'x' => {
10791 let x = args.next_arg::<c_uint>();
10792 let b = format_hex(x as u64, false);
10793 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10794 let mut fbuf = [0u8; 32];
10795 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10796 for k in 0..len { wc!(fbuf[k]); }
10797 }
10798 b'X' => {
10799 let x = args.next_arg::<c_uint>();
10800 let b = format_hex(x as u64, true);
10801 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10802 let mut fbuf = [0u8; 32];
10803 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10804 for k in 0..len { wc!(fbuf[k]); }
10805 }
10806 b'o' => {
10807 let o = args.next_arg::<c_uint>();
10808 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
10809 let mut fbuf = [0u8; 32];
10810 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10811 for k in 0..len { wc!(fbuf[k]); }
10812 }
10813 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
10814 let val = args.next_arg::<f64>();
10815 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
10816 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
10817 let mut fbuf = [0u8; 4224];
10818 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
10819 let mut wbuf = [0u8; 4224];
10820 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
10821 for k in 0..wlen { wc!(wbuf[k]); }
10822 }
10823 b'c' => {
10824 let ch = args.next_arg::<c_int>();
10825 wc!(ch as u8);
10826 }
10827 b's' => {
10828 let p = args.next_arg::<*const c_char>();
10829 if p.is_null() {
10830 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
10831 if flags & FLAG_MINUS != 0 {
10832 for k in 0..slen { wc!(b"(null)"[k]); }
10833 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10834 } else {
10835 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10836 for k in 0..slen { wc!(b"(null)"[k]); }
10837 }
10838 } else {
10839 let mut wbuf_local = [0i32; 256];
10840 let mut wcount = 0usize;
10841 let mut byte_pos = 0usize;
10842 let pbytes = p as *const u8;
10843 loop {
10844 if precision >= 0 && wcount >= precision as usize { break; }
10845 if wcount >= 256 { break; }
10846 let mut wc_val: c_int = 0;
10847 let consumed = mbrtowc(&mut wc_val as *mut c_int, p.add(byte_pos) as *const c_char, 256, core::ptr::null_mut());
10848 if consumed == !0usize || consumed == !1usize {
10849 wbuf_local[wcount] = *pbytes.add(byte_pos) as c_int;
10850 byte_pos += 1;
10851 wcount += 1;
10852 } else if consumed == 0 {
10853 break;
10854 } else {
10855 wbuf_local[wcount] = wc_val;
10856 byte_pos += consumed;
10857 wcount += 1;
10858 }
10859 }
10860 if flags & FLAG_MINUS != 0 {
10861 for k in 0..wcount { wc!(wbuf_local[k]); }
10862 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
10863 } else {
10864 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
10865 for k in 0..wcount { wc!(wbuf_local[k]); }
10866 }
10867 }
10868 }
10869 b'p' => {
10870 wc!(b'0'); wc!(b'x');
10871 let p = args.next_arg::<*const c_void>();
10872 let b = format_hex(p as u64, false);
10873 for k in 0..b.1 { wc!(b.0[k]); }
10874 }
10875 b'n' => {
10876 let p = args.next_arg::<*mut c_void>();
10877 if !p.is_null() { *(p as *mut c_int) = pos as c_int; }
10878 }
10879 b'%' => { wc!(b'%'); }
10880 _ => { wc!(b'%'); wc!(spec); }
10881 }
10882 }
10883 fi += 1;
10884 }
10885 let null_pos = if pos < cap { pos } else { cap };
10886 *s.add(null_pos) = 0;
10887 if pos > cap { -1 } else { pos as c_int }
10888}
10889
10890#[no_mangle]
10891pub unsafe extern "C" fn swprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, args: ...) -> c_int {
10892 vswprintf(s, n, fmt, args)
10893}
10894
10895#[no_mangle]
10896pub unsafe extern "C" fn vfwprintf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int {
10897 let mut buf = [0i32; 4096];
10898 let r = vswprintf(buf.as_mut_ptr(), 4096, fmt, args);
10899 if r < 0 { return r; }
10900 let mut i = 0;
10901 while i < r as usize {
10902 let mut mb = [0u8; 4];
10903 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, buf[i], core::ptr::null_mut());
10904 if n == !0usize { return -1; }
10905 if fwrite(mb.as_ptr() as *const c_void, 1, n, f) != n { return -1; }
10906 i += 1;
10907 }
10908 r
10909}
10910
10911#[no_mangle]
10912pub unsafe extern "C" fn fwprintf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
10913 vfwprintf(f, fmt, args)
10914}
10915
10916unsafe fn wcsfmt_to_mbs(dst: *mut u8, dst_len: usize, src: *const wchar_t) {
10922 let mut i = 0usize;
10923 loop {
10924 let ch = *src.add(i) as u32;
10925 if ch == 0 || i >= dst_len - 1 { break; }
10926 *dst.add(i) = if ch < 128 { ch as u8 } else { b'?' };
10927 i += 1;
10928 }
10929 *dst.add(i) = 0;
10930}
10931
10932#[no_mangle]
10933pub unsafe extern "C" fn vswscanf(s: *const wchar_t, fmt: *const wchar_t, mut args: VaList) -> c_int {
10934 let mut mbs_buf = [0u8; 4096];
10935 let mut i = 0usize;
10936 let mut mb_pos = 0usize;
10937 loop {
10938 let wc = *s.add(i) as c_int;
10939 if wc == 0 { break; }
10940 let mut mb = [0u8; 4];
10941 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, wc, core::ptr::null_mut());
10942 if n == !0usize || n == 0 { break; }
10943 if mb_pos + n >= mbs_buf.len() { break; }
10944 let mut k = 0usize;
10945 while k < n { mbs_buf[mb_pos + k] = mb[k]; k += 1; }
10946 mb_pos += n;
10947 i += 1;
10948 }
10949 mbs_buf[mb_pos] = 0;
10950 let mut mbs_fmt = [0u8; 4096];
10951 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
10952 do_vsscanf(mbs_buf.as_ptr(), mb_pos, mbs_fmt.as_ptr() as *const c_char, &mut args, core::ptr::null_mut())
10953}
10954
10955#[no_mangle]
10956pub unsafe extern "C" fn swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int {
10957 vswscanf(s, fmt, args)
10958}
10959
10960#[no_mangle]
10961pub unsafe extern "C" fn vfwscanf(f: *mut FILE, fmt: *const wchar_t, mut args: VaList) -> c_int {
10962 let start_pos = ftello(f);
10963 if start_pos < 0 { return -1; }
10964 let mut buf = [0u8; 4096];
10965 let mut n = 0usize;
10966 loop {
10967 if n >= buf.len() - 1 { break; }
10968 let c = fgetc(f);
10969 if c == -1 { break; }
10970 buf[n] = c as u8;
10971 n += 1;
10972 }
10973 buf[n] = 0;
10974 let mut mbs_fmt = [0u8; 4096];
10975 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
10976 let mut consumed = 0usize;
10977 let hit_eof = (*f)._eof != 0;
10978 let result = do_vsscanf(buf.as_ptr(), n, mbs_fmt.as_ptr() as *const c_char, &mut args, &mut consumed);
10979 let _ = fseeko(f, start_pos + consumed as i64, SEEK_SET);
10980 if hit_eof && consumed == n {
10981 (*f)._eof = 1;
10982 }
10983 result
10984}
10985
10986#[no_mangle]
10987pub unsafe extern "C" fn fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
10988 vfwscanf(f, fmt, args)
10989}
10990
10991#[no_mangle]
10992pub unsafe extern "C" fn vwscanf(fmt: *const wchar_t, args: VaList) -> c_int {
10993 vfwscanf(stdin, fmt, args)
10994}
10995
10996#[no_mangle]
10997pub unsafe extern "C" fn wscanf(fmt: *const wchar_t, args: ...) -> c_int {
10998 vfwscanf(stdin, fmt, args)
10999}
11000
11001const LEAPOCH: i64 = 946684800 + 86400 * (31 + 29);
11006const DAYS_PER_400Y: i64 = 365 * 400 + 97;
11007const DAYS_PER_100Y: i64 = 365 * 100 + 24;
11008const DAYS_PER_4Y: i64 = 365 * 4 + 1;
11009
11010const SECS_THROUGH_MONTH: [i32; 12] = [
11011 0, 31*86400, 59*86400, 90*86400, 120*86400, 151*86400,
11012 181*86400, 212*86400, 243*86400, 273*86400, 304*86400, 334*86400,
11013];
11014
11015const DAYS_IN_MONTH: [i32; 12] = [31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29];
11016
11017unsafe fn year_to_secs(year: i64, is_leap: &mut bool) -> i64 {
11018 if year - 2 <= 136 {
11019 let y = year as i32;
11020 let mut leaps = (y - 68) >> 2;
11021 if (y - 68) & 3 == 0 { leaps -= 1; *is_leap = true; } else { *is_leap = false; }
11022 return 31536000 * (y as i64 - 70) + 86400 * leaps as i64;
11023 }
11024 let mut cycles = ((year - 100) / 400) as i32;
11025 let mut rem = ((year - 100) % 400) as i32;
11026 if rem < 0 { cycles -= 1; rem += 400; }
11027 let (centuries, leaps);
11028 if rem == 0 { *is_leap = true; centuries = 0; leaps = 0; }
11029 else {
11030 let c;
11031 if rem >= 200 { if rem >= 300 { c = 3; rem -= 300; } else { c = 2; rem -= 200; } }
11032 else { if rem >= 100 { c = 1; rem -= 100; } else { c = 0; } }
11033 centuries = c;
11034 if rem == 0 { *is_leap = false; leaps = 0; }
11035 else { leaps = rem / 4; rem %= 4; *is_leap = rem == 0; }
11036 }
11037 let total_leaps = leaps + 97 * cycles + 24 * centuries - (*is_leap as i32);
11038 (year - 100) * 31536000 + total_leaps as i64 * 86400 + 946684800 + 86400
11039}
11040
11041fn month_to_secs(month: i32, is_leap: bool) -> i32 {
11042 let mut t = SECS_THROUGH_MONTH[month as usize];
11043 if is_leap && month >= 2 { t += 86400; }
11044 t
11045}
11046
11047unsafe fn secs_to_tm(t: i64, tm: &mut tm) -> bool {
11048 if t < (i32::MIN as i64) * 31622400 || t > (i32::MAX as i64) * 31622400 { return false; }
11049 let secs = t - LEAPOCH;
11050 let mut days = secs / 86400;
11051 let mut remsecs = (secs % 86400) as i32;
11052 if remsecs < 0 { remsecs += 86400; days -= 1; }
11053 let mut wday = ((3 + days) % 7) as i32;
11054 if wday < 0 { wday += 7; }
11055 let mut qc_cycles = (days / DAYS_PER_400Y) as i32;
11056 let mut remdays = (days % DAYS_PER_400Y) as i32;
11057 if remdays < 0 { remdays += DAYS_PER_400Y as i32; qc_cycles -= 1; }
11058 let mut c_cycles = remdays / DAYS_PER_100Y as i32;
11059 if c_cycles == 4 { c_cycles -= 1; }
11060 remdays -= c_cycles * DAYS_PER_100Y as i32;
11061 let mut q_cycles = remdays / DAYS_PER_4Y as i32;
11062 if q_cycles == 25 { q_cycles -= 1; }
11063 remdays -= q_cycles * DAYS_PER_4Y as i32;
11064 let mut remyears = remdays / 365;
11065 if remyears == 4 { remyears -= 1; }
11066 remdays -= remyears * 365;
11067 let leap = remyears == 0 && (q_cycles != 0 || c_cycles == 0);
11068 let mut yday = remdays + 31 + 28 + leap as i32;
11069 if yday >= 365 + leap as i32 { yday -= 365 + leap as i32; }
11070 let years = remyears as i64 + 4 * q_cycles as i64 + 100 * c_cycles as i64 + 400 * qc_cycles as i64;
11071 let mut months = 0i32;
11072 let mut rd = remdays;
11073 for m in 0..12 {
11074 if DAYS_IN_MONTH[m] <= rd { rd -= DAYS_IN_MONTH[m]; } else { months = m as i32; break; }
11075 }
11076 let mut adj_years = years;
11077 if months >= 10 { months -= 12; adj_years += 1; }
11078 if adj_years + 100 > i32::MAX as i64 || adj_years + 100 < i32::MIN as i64 { return false; }
11079 tm.tm_year = (adj_years + 100) as c_int;
11080 tm.tm_mon = months + 2;
11081 tm.tm_mday = rd + 1;
11082 tm.tm_wday = wday;
11083 tm.tm_yday = yday;
11084 tm.tm_hour = remsecs / 3600;
11085 tm.tm_min = remsecs / 60 % 60;
11086 tm.tm_sec = remsecs % 60;
11087 true
11088}
11089
11090unsafe fn tm_to_secs(tm: *const tm) -> i64 {
11091 let mut year = (*tm).tm_year as i64;
11092 let mut month = (*tm).tm_mon;
11093 if month >= 12 || month < 0 {
11094 let adj = month / 12;
11095 month %= 12;
11096 if month < 0 { month += 12; }
11097 year += adj as i64;
11098 }
11099 let mut is_leap = false;
11100 let mut t = year_to_secs(year, &mut is_leap);
11101 t += month_to_secs(month, is_leap) as i64;
11102 t += 86400 * ((*tm).tm_mday - 1) as i64;
11103 t += 3600 * (*tm).tm_hour as i64;
11104 t += 60 * (*tm).tm_min as i64;
11105 t += (*tm).tm_sec as i64;
11106 t
11107}
11108
11109static mut TM_BUF: tm = tm {
11110 tm_sec: 0, tm_min: 0, tm_hour: 0, tm_mday: 0, tm_mon: 0,
11111 tm_year: 0, tm_wday: 0, tm_yday: 0, tm_isdst: 0,
11112 tm_gmtoff: 0, tm_zone: core::ptr::null(),
11113};
11114
11115static mut UTC_STR: [c_char; 4] = [b'U' as c_char, b'T' as c_char, b'C' as c_char, 0];
11116
11117const CLOCK_PROCESS_CPUTIME_ID: c_int = 2;
11118
11119#[no_mangle]
11124pub unsafe extern "C" fn time(t: *mut TimeT) -> TimeT {
11125 let mut ts: timespec = core::mem::zeroed();
11126 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
11127 if !t.is_null() { *t = ts.tv_sec; }
11128 ts.tv_sec
11129}
11130
11131#[no_mangle]
11132pub unsafe extern "C" fn difftime(t1: TimeT, t0: TimeT) -> f64 {
11133 (t1 as i64 - t0 as i64) as f64
11134}
11135
11136#[no_mangle]
11137pub unsafe extern "C" fn clock() -> ClockT {
11138 let mut ts: timespec = core::mem::zeroed();
11139 let _ = sys_clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &mut ts);
11140 ts.tv_sec * 1000000 + ts.tv_nsec / 1000
11141}
11142
11143#[no_mangle]
11144pub unsafe extern "C" fn gmtime(t: *const TimeT) -> *mut tm {
11145 gmtime_r(t, &raw mut TM_BUF)
11146}
11147
11148#[no_mangle]
11149pub unsafe extern "C" fn gmtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm {
11150 if !secs_to_tm(*t as i64, &mut *tm) { ERRNO = EOVERFLOW; return core::ptr::null_mut(); }
11151 (*tm).tm_isdst = 0;
11152 (*tm).tm_gmtoff = 0;
11153 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11154 tm
11155}
11156
11157#[no_mangle]
11158pub unsafe extern "C" fn localtime(t: *const TimeT) -> *mut tm { gmtime(t) }
11159
11160#[no_mangle]
11161pub unsafe extern "C" fn localtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm { gmtime_r(t, tm) }
11162
11163#[no_mangle]
11164pub unsafe extern "C" fn mktime(tm: *mut tm) -> TimeT {
11165 let t = tm_to_secs(tm as *const tm);
11166 if !secs_to_tm(t, &mut *tm) { ERRNO = EOVERFLOW; return -1; }
11167 (*tm).tm_isdst = 0;
11168 (*tm).tm_gmtoff = 0;
11169 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11170 t as TimeT
11171}
11172
11173#[no_mangle]
11174pub unsafe extern "C" fn timegm(tm: *mut tm) -> TimeT {
11175 let t = tm_to_secs(tm as *const tm);
11176 if !secs_to_tm(t, &mut *tm) { ERRNO = EOVERFLOW; return -1; }
11177 (*tm).tm_isdst = 0;
11178 (*tm).tm_gmtoff = 0;
11179 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11180 t as TimeT
11181}
11182
11183static mut ASCTIME_BUF: [c_char; 26] = [0; 26];
11184
11185const 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"];
11186const 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"];
11187
11188#[no_mangle]
11189pub unsafe extern "C" fn asctime(tm: *const tm) -> *mut c_char {
11190 asctime_r(tm, core::ptr::addr_of_mut!(ASCTIME_BUF).cast::<c_char>())
11191}
11192
11193#[no_mangle]
11194pub unsafe extern "C" fn asctime_r(tm: *const tm, buf: *mut c_char) -> *mut c_char {
11195 let wday = if (*tm).tm_wday >= 0 && (*tm).tm_wday < 7 { (*tm).tm_wday as usize } else { 0 };
11196 let mon = if (*tm).tm_mon >= 0 && (*tm).tm_mon < 12 { (*tm).tm_mon as usize } else { 0 };
11197 let dn = DAY_NAMES[wday];
11198 let mn = MON_NAMES[mon];
11199 let mut p = 0;
11200 for k in 0..3 { *buf.add(p) = *dn.as_ptr().add(k) as c_char; p += 1; }
11201 *buf.add(p) = b' ' as c_char; p += 1;
11202 for k in 0..3 { *buf.add(p) = *mn.as_ptr().add(k) as c_char; p += 1; }
11203 *buf.add(p) = b' ' as c_char; p += 1;
11204 let v = (*tm).tm_mday;
11205 *buf.add(p) = (b'0' + (v / 10) as u8) as c_char; p += 1;
11206 *buf.add(p) = (b'0' + (v % 10) as u8) as c_char; p += 1;
11207 *buf.add(p) = b' ' as c_char; p += 1;
11208 let hh = (*tm).tm_hour;
11209 *buf.add(p) = (b'0' + (hh / 10) as u8) as c_char; p += 1;
11210 *buf.add(p) = (b'0' + (hh % 10) as u8) as c_char; p += 1;
11211 *buf.add(p) = b':' as c_char; p += 1;
11212 let mm = (*tm).tm_min;
11213 *buf.add(p) = (b'0' + (mm / 10) as u8) as c_char; p += 1;
11214 *buf.add(p) = (b'0' + (mm % 10) as u8) as c_char; p += 1;
11215 *buf.add(p) = b':' as c_char; p += 1;
11216 let ss = (*tm).tm_sec;
11217 *buf.add(p) = (b'0' + (ss / 10) as u8) as c_char; p += 1;
11218 *buf.add(p) = (b'0' + (ss % 10) as u8) as c_char; p += 1;
11219 *buf.add(p) = b' ' as c_char; p += 1;
11220 let yr = (*tm).tm_year + 1900;
11221 let mut tmp = [0u8; 4];
11222 let mut v2 = yr;
11223 for k in (0..4).rev() { tmp[k] = b'0' + (v2 % 10) as u8; v2 /= 10; }
11224 for k in 0..4 { *buf.add(p) = tmp[k] as c_char; p += 1; }
11225 *buf.add(p) = b'\n' as c_char; p += 1;
11226 *buf.add(p) = 0;
11227 buf
11228}
11229
11230#[no_mangle]
11231pub unsafe extern "C" fn ctime(t: *const TimeT) -> *mut c_char { asctime(gmtime(t)) }
11232
11233#[no_mangle]
11234pub unsafe extern "C" fn ctime_r(t: *const TimeT, buf: *mut c_char) -> *mut c_char {
11235 let mut tmp: tm = core::mem::zeroed();
11236 gmtime_r(t, &mut tmp);
11237 asctime_r(&tmp, buf)
11238}
11239
11240unsafe fn sys_clock_getres(clockid: c_int, ts: *mut timespec) -> i64 {
11245 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, clockid as i64, ts as i64)
11246}
11247
11248unsafe fn sys_clock_settime(clockid: c_int, ts: *const timespec) -> i64 {
11249 <Arch as Syscalls>::syscall2(SYS_CLOCK_SETTIME, clockid as i64, ts as i64)
11250}
11251
11252unsafe fn sys_clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> i64 {
11253 <Arch as Syscalls>::syscall4(SYS_CLOCK_NANOSLEEP, clockid as i64, flags as i64, req as i64, rem as i64)
11254}
11255
11256#[no_mangle]
11257pub unsafe extern "C" fn clock_getres(clockid: c_int, ts: *mut timespec) -> c_int { if sys_clock_getres(clockid, ts) < 0 { -1 } else { 0 } }
11258
11259#[no_mangle]
11260pub unsafe extern "C" fn clock_settime(clockid: c_int, ts: *const timespec) -> c_int { if sys_clock_settime(clockid, ts) < 0 { -1 } else { 0 } }
11261
11262#[no_mangle]
11263pub unsafe extern "C" fn clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> c_int {
11264 let r = sys_clock_nanosleep(clockid, flags, req, rem);
11265 if r < 0 { (-r) as c_int } else { 0 }
11266}
11267
11268#[no_mangle]
11269pub unsafe extern "C" fn gettimeofday(tv: *mut timeval, _tz: *mut c_void) -> c_int {
11270 if tv.is_null() { return 0; }
11271 let mut ts: timespec = core::mem::zeroed();
11272 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
11273 (*tv).tv_sec = ts.tv_sec;
11274 (*tv).tv_usec = ts.tv_nsec / 1000;
11275 0
11276}
11277
11278fn is_leap_year(y: i32) -> bool {
11283 let yr = if y > i32::MAX - 1900 { y - 2000 } else { y + 1900 };
11284 yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0)
11285}
11286
11287fn week_num(tm: &tm) -> i32 {
11288 let mut val = (tm.tm_yday + 7 - ((tm.tm_wday + 6) % 7)) / 7;
11289 if (tm.tm_wday + 371 - tm.tm_yday - 2).rem_euclid(7) <= 2 { val += 1; }
11290 if val == 0 {
11291 val = 52;
11292 let dec31 = (tm.tm_wday + 7 - tm.tm_yday - 1).rem_euclid(7);
11293 if dec31 == 4 || (dec31 == 5 && is_leap_year(tm.tm_year % 400 - 1)) { val += 1; }
11294 } else if val == 53 {
11295 let jan1 = (tm.tm_wday + 371 - tm.tm_yday).rem_euclid(7);
11296 if jan1 != 4 && (jan1 != 3 || !is_leap_year(tm.tm_year)) { val = 1; }
11297 }
11298 val
11299}
11300
11301const ABDAY_1: c_int = 0x20000;
11303const DAY_1: c_int = 0x20007;
11304const ABMON_1: c_int = 0x2000E;
11305const MON_1: c_int = 0x2001A;
11306const AM_STR_LI: c_int = 0x20026;
11307const PM_STR_LI: c_int = 0x20027;
11308const D_T_FMT: c_int = 0x20028;
11309const D_FMT: c_int = 0x20029;
11310const T_FMT: c_int = 0x2002A;
11311const T_FMT_AMPM: c_int = 0x2002B;
11312
11313unsafe fn num_fmt(buf: &mut [u8; 100], val: i64, pad: u8, width: usize) -> (*const u8, usize) {
11316 let negative = val < 0;
11317 let mut v = if negative { -val as u64 } else { val as u64 };
11318 let mut tmp = [0u8; 24];
11319 let mut pos = 24usize;
11320 if v == 0 { pos -= 1; tmp[pos] = b'0'; }
11321 while v > 0 { pos -= 1; tmp[pos] = b'0' + (v % 10) as u8; v /= 10; }
11322 let digits = 24 - pos;
11323 let sign_chars = if negative { 1 } else { 0 };
11324 let needed = sign_chars + digits;
11325 let fill = if width > needed { width - needed } else { 0 };
11326 let total = fill + needed;
11327 let mut p = 0usize;
11328 match pad {
11329 b'-' => { }
11330 b'_' => {
11331 for _ in 0..fill { buf[p] = b' '; p += 1; }
11332 if negative { buf[p] = b'-'; p += 1; }
11333 }
11334 _ => {
11335 if negative { buf[p] = b'-'; p += 1; }
11336 for _ in 0..fill { buf[p] = b'0'; p += 1; }
11337 }
11338 }
11339 for i in 0..digits { buf[p] = tmp[pos + i]; p += 1; }
11340 (buf.as_ptr(), total)
11341}
11342
11343unsafe fn str_to_buf(buf: &mut [u8; 100], s: *const c_char) -> (*const u8, usize) {
11345 let mut k = 0usize;
11346 while *s.add(k) != 0 {
11347 buf[k] = *s.add(k) as u8;
11348 k += 1;
11349 }
11350 (buf.as_ptr(), k)
11351}
11352
11353unsafe fn __strftime_fmt_1(buf: &mut [u8; 100], f: u8, tm: *const tm, pad: u8) -> (*const u8, usize) {
11356 let mut val: i64;
11357 let mut width: usize = 2;
11358 let mut def_pad: u8 = b'0';
11359 let fmt: *const c_char;
11360
11361 match f {
11362 b'a' => {
11363 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
11364 let p = nl_langinfo(ABDAY_1 + (*tm).tm_wday);
11365 return str_to_buf(buf, p);
11366 }
11367 b'A' => {
11368 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
11369 let p = nl_langinfo(DAY_1 + (*tm).tm_wday);
11370 return str_to_buf(buf, p);
11371 }
11372 b'h' | b'b' => {
11373 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11374 let p = nl_langinfo(ABMON_1 + (*tm).tm_mon);
11375 return str_to_buf(buf, p);
11376 }
11377 b'B' => {
11378 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11379 let p = nl_langinfo(MON_1 + (*tm).tm_mon);
11380 return str_to_buf(buf, p);
11381 }
11382 b'c' => {
11383 let p = nl_langinfo(D_T_FMT);
11384 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11385 return (buf.as_ptr(), l);
11386 }
11387 b'C' => {
11388 val = (1900i64 + (*tm).tm_year as i64) / 100;
11389 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11390 }
11391 b'e' => { def_pad = b'_'; }
11392 b'd' => {
11393 val = (*tm).tm_mday as i64;
11394 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11395 }
11396 b'D' => {
11397 fmt = b"%m/%d/%y\0".as_ptr() as *const c_char;
11398 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11399 return (buf.as_ptr(), l);
11400 }
11401 b'F' => {
11402 fmt = b"%Y-%m-%d\0".as_ptr() as *const c_char;
11403 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11404 return (buf.as_ptr(), l);
11405 }
11406 b'g' | b'G' => {
11407 val = (*tm).tm_year as i64 + 1900;
11408 if (*tm).tm_yday < 3 && week_num(&*tm) != 1 { val -= 1; }
11409 else if (*tm).tm_yday > 360 && week_num(&*tm) == 1 { val += 1; }
11410 if f == b'g' { val %= 100; }
11411 else { width = 4; }
11412 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11413 }
11414 b'H' => {
11415 val = (*tm).tm_hour as i64;
11416 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11417 }
11418 b'I' => {
11419 val = (*tm).tm_hour as i64;
11420 if val == 0 { val = 12; }
11421 else if val > 12 { val -= 12; }
11422 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11423 }
11424 b'j' => {
11425 val = (*tm).tm_yday as i64 + 1;
11426 width = 3;
11427 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11428 }
11429 b'm' => {
11430 val = (*tm).tm_mon as i64 + 1;
11431 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11432 }
11433 b'M' => {
11434 val = (*tm).tm_min as i64;
11435 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11436 }
11437 b'n' => { buf[0] = b'\n'; return (buf.as_ptr(), 1); }
11438 b'p' => {
11439 let p = if (*tm).tm_hour >= 12 { nl_langinfo(PM_STR_LI) } else { nl_langinfo(AM_STR_LI) };
11440 return str_to_buf(buf, p);
11441 }
11442 b'r' => {
11443 let p = nl_langinfo(T_FMT_AMPM);
11444 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11445 return (buf.as_ptr(), l);
11446 }
11447 b'R' => {
11448 fmt = b"%H:%M\0".as_ptr() as *const c_char;
11449 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11450 return (buf.as_ptr(), l);
11451 }
11452 b's' => {
11453 val = tm_to_secs(tm) - (*tm).tm_gmtoff as i64;
11454 width = 1;
11455 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11456 }
11457 b'S' => {
11458 val = (*tm).tm_sec as i64;
11459 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11460 }
11461 b't' => { buf[0] = b'\t'; return (buf.as_ptr(), 1); }
11462 b'T' => {
11463 fmt = b"%H:%M:%S\0".as_ptr() as *const c_char;
11464 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11465 return (buf.as_ptr(), l);
11466 }
11467 b'u' => {
11468 val = if (*tm).tm_wday != 0 { (*tm).tm_wday as i64 } else { 7 };
11469 width = 1;
11470 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11471 }
11472 b'U' => {
11473 val = ((*tm).tm_yday as u64 + 7 - (*tm).tm_wday as u64) as i64 / 7;
11474 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11475 }
11476 b'W' => {
11477 val = ((*tm).tm_yday as u64 + 7 - ((*tm).tm_wday as u64 + 6) % 7) as i64 / 7;
11478 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11479 }
11480 b'V' => {
11481 val = week_num(&*tm) as i64;
11482 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11483 }
11484 b'w' => {
11485 val = (*tm).tm_wday as i64;
11486 width = 1;
11487 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11488 }
11489 b'x' => {
11490 let p = nl_langinfo(D_FMT);
11491 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11492 return (buf.as_ptr(), l);
11493 }
11494 b'X' => {
11495 let p = nl_langinfo(T_FMT);
11496 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11497 return (buf.as_ptr(), l);
11498 }
11499 b'y' => {
11500 val = (1900i64 + (*tm).tm_year as i64) % 100;
11501 if val < 0 { val = -val; }
11502 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11503 }
11504 b'Y' => {
11505 val = (*tm).tm_year as i64 + 1900;
11506 if val >= 10000 {
11507 let mut tmp = [0u8; 100];
11508 let (_, k) = num_fmt(&mut tmp, val, b'-', 1);
11509 buf[0] = b'+';
11510 for i in 0..k { buf[1 + i] = tmp[i]; }
11511 return (buf.as_ptr(), 1 + k);
11512 }
11513 width = 4;
11514 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11515 }
11516 b'z' => {
11517 if (*tm).tm_isdst < 0 { return (b"\0".as_ptr(), 0); }
11518 let gmtoff = (*tm).tm_gmtoff as i64;
11519 let sign = if gmtoff >= 0 { b'+' } else { b'-' };
11520 let off = if gmtoff < 0 { -gmtoff } else { gmtoff };
11521 let hh = (off / 3600) as i32;
11522 let mm = ((off % 3600) / 60) as i32;
11523 buf[0] = sign;
11524 buf[1] = b'0' + (hh / 10) as u8;
11525 buf[2] = b'0' + (hh % 10) as u8;
11526 buf[3] = b'0' + (mm / 10) as u8;
11527 buf[4] = b'0' + (mm % 10) as u8;
11528 return (buf.as_ptr(), 5);
11529 }
11530 b'Z' => {
11531 if (*tm).tm_isdst < 0 || (*tm).tm_zone.is_null() { return (b"\0".as_ptr(), 0); }
11532 return str_to_buf(buf, (*tm).tm_zone);
11533 }
11534 b'%' => { buf[0] = b'%'; return (buf.as_ptr(), 1); }
11535 _ => { return (core::ptr::null(), 0); }
11536 }
11537 val = (*tm).tm_mday as i64;
11539 num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width)
11540}
11541
11542unsafe fn __strftime_l(s: *mut c_char, n: usize, f: *const c_char, tm: *const tm) -> usize {
11543 let mut l: usize = 0;
11544 let mut fi: usize = 0;
11545 while l < n {
11546 let ch = *f.add(fi) as u8;
11547 if ch == 0 {
11548 *s.add(l) = 0;
11549 return l;
11550 }
11551 if ch != b'%' {
11552 *s.add(l) = ch as c_char;
11553 l += 1;
11554 fi += 1;
11555 continue;
11556 }
11557 fi += 1;
11558 let mut pad: u8 = 0;
11560 let fc = *f.add(fi) as u8;
11561 if fc == b'-' || fc == b'_' || fc == b'0' { pad = fc; fi += 1; }
11562 let plus = *f.add(fi) as u8 == b'+';
11563 if plus { fi += 1; }
11564 let mut width: usize = 0;
11566 let mut p_idx = fi;
11567 {
11568 let fc2 = *f.add(fi) as u8;
11569 if fc2 >= b'0' && fc2 <= b'9' {
11570 let mut w: usize = 0;
11571 while { let c = *f.add(p_idx) as u8; c >= b'0' && c <= b'9' } {
11572 w = w * 10 + (*f.add(p_idx) as usize - b'0' as usize);
11573 p_idx += 1;
11574 }
11575 width = w;
11576 }
11577 }
11578 let spec_ch = *f.add(p_idx) as u8;
11579 if spec_ch == b'C' || spec_ch == b'F' || spec_ch == b'G' || spec_ch == b'Y' {
11580 if width == 0 && p_idx != fi { width = 1; }
11581 } else {
11582 width = 0;
11583 }
11584 fi = p_idx;
11585 let fc3 = *f.add(fi) as u8;
11587 if fc3 == b'E' || fc3 == b'O' { fi += 1; }
11588 let fch = *f.add(fi) as u8;
11589 let mut buf = [0u8; 100];
11591 let (t, k) = __strftime_fmt_1(&mut buf, fch, tm, pad);
11592 if t.is_null() { break; }
11593 let mut k = k;
11594 let mut t = t;
11595 if width != 0 {
11596 if *t == b'+' || *t == b'-' { t = t.add(1); k -= 1; }
11598 while k > 0 && *t == b'0' && k > 1 && *t.add(1) >= b'0' && *t.add(1) <= b'9' {
11599 t = t.add(1); k -= 1;
11600 }
11601 if width < k { width = k; }
11602 let mut d: usize = 0;
11603 while d < k && *t.add(d) >= b'0' && *t.add(d) <= b'9' { d += 1; }
11604 if (*tm).tm_year < -1900 {
11605 if l < n { *s.add(l) = b'-' as c_char; }
11606 l += 1;
11607 width -= 1;
11608 } else if plus && d + (width - k) >= (if spec_ch == b'C' { 3 } else { 5 }) {
11609 if l < n { *s.add(l) = b'+' as c_char; }
11610 l += 1;
11611 width -= 1;
11612 }
11613 while width > k && l < n {
11614 *s.add(l) = b'0' as c_char;
11615 l += 1;
11616 width -= 1;
11617 }
11618 }
11619 let copy = if k > n - l { n - l } else { k };
11620 core::ptr::copy_nonoverlapping(t, s.add(l) as *mut u8, copy);
11621 l += copy;
11622 fi += 1;
11623 }
11624 if n > 0 {
11625 if l == n { l = n - 1; }
11626 *s.add(l) = 0;
11627 }
11628 0
11629}
11630
11631#[no_mangle]
11632pub unsafe extern "C" fn strftime(s: *mut c_char, maxsize: usize, fmt: *const c_char, tm: *const tm) -> usize {
11633 __strftime_l(s, maxsize, fmt, tm)
11634}
11635
11636unsafe fn match_prefix(s: *const u8, prefix: &[u8]) -> bool {
11641 for i in 0..prefix.len() {
11642 if *s.add(i) == 0 || *s.add(i) != prefix[i] { return false; }
11643 }
11644 true
11645}
11646
11647unsafe fn match_ci_prefix(s: *const u8, prefix: &[u8]) -> bool {
11648 for i in 0..prefix.len() {
11649 let c = *s.add(i);
11650 if c == 0 { return false; }
11651 if c.to_ascii_lowercase() != prefix[i].to_ascii_lowercase() { return false; }
11652 }
11653 true
11654}
11655
11656unsafe fn parse_int(p: *const u8, max_digits: usize) -> (i32, *const u8) {
11657 let mut val = 0i32;
11658 let mut np = p;
11659 let mut count = 0;
11660 while *np >= b'0' && *np <= b'9' && count < max_digits {
11661 val = val * 10 + (*np - b'0') as i32;
11662 np = np.add(1);
11663 count += 1;
11664 }
11665 if count == 0 { (0, p) } else { (val, np) }
11666}
11667
11668unsafe fn parse_range(p: *const u8, min: i32, max: i32) -> (i32, *const u8) {
11669 let (val, np) = parse_int(p, 4);
11670 if np == p || val < min || val > max { (0, p) } else { (val, np) }
11671}
11672
11673fn is_ascii_space(c: u8) -> bool {
11674 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0c || c == 0x0b
11675}
11676
11677#[no_mangle]
11678pub unsafe extern "C" fn strptime(s: *const c_char, fmt: *const c_char, tm: *mut tm) -> *mut c_char {
11679 let mut p = s as *const u8;
11680 let mut f = fmt as *const u8;
11681 let mut want_century = 0i32;
11682 let mut century = 0i32;
11683 let mut relyear = 0i32;
11684 while *f != 0 {
11685 if *f != b'%' {
11686 if is_ascii_space(*f) {
11687 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
11688 } else {
11689 if *p != *f { return core::ptr::null_mut(); }
11690 p = p.add(1);
11691 }
11692 f = f.add(1);
11693 continue;
11694 }
11695 f = f.add(1);
11696 if *f == b'+' { f = f.add(1); }
11697 while *f >= b'0' && *f <= b'9' { f = f.add(1); }
11698 if *f == b'E' || *f == b'O' { f = f.add(1); }
11699 match *f {
11700 b'a' | b'A' => {
11701 let mut found = false;
11702 for i in 0..7 {
11703 let names: [&[u8]; 7] = [b"Sunday", b"Monday", b"Tuesday", b"Wednesday", b"Thursday", b"Friday", b"Saturday"];
11704 let snames: [&[u8]; 7] = [b"Sun", b"Mon", b"Tue", b"Wed", b"Thu", b"Fri", b"Sat"];
11705 if match_prefix(p, names[i]) { (*tm).tm_wday = i as c_int; p = p.add(names[i].len()); found = true; break; }
11706 if match_prefix(p, snames[i]) { (*tm).tm_wday = i as c_int; p = p.add(snames[i].len()); found = true; break; }
11707 }
11708 if !found { return core::ptr::null_mut(); }
11709 }
11710 b'b' | b'B' | b'h' => {
11711 let mut found = false;
11712 for i in 0..12 {
11713 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"];
11714 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"];
11715 if match_prefix(p, names[i]) { (*tm).tm_mon = i as c_int; p = p.add(names[i].len()); found = true; break; }
11716 if match_prefix(p, snames[i]) { (*tm).tm_mon = i as c_int; p = p.add(snames[i].len()); found = true; break; }
11717 }
11718 if !found { return core::ptr::null_mut(); }
11719 }
11720 b'C' => {
11721 let (v, np) = parse_int(p, 2);
11722 if np == p { return core::ptr::null_mut(); }
11723 century = v;
11724 want_century |= 2;
11725 p = np;
11726 }
11727 b'd' | b'e' => {
11728 let (v, np) = parse_range(p, 1, 31);
11729 if np == p { return core::ptr::null_mut(); }
11730 (*tm).tm_mday = v;
11731 p = np;
11732 }
11733 b'D' => {
11734 let r = strptime(p as *const c_char, b"%m/%d/%y\0".as_ptr() as *const c_char, tm);
11735 if r.is_null() { return core::ptr::null_mut(); }
11736 p = r as *const u8;
11737 }
11738 b'F' => {
11739 let (yv, ynp) = parse_int(p, 4);
11740 if ynp == p { return core::ptr::null_mut(); }
11741 (*tm).tm_year = yv - 1900;
11742 p = ynp;
11743 if *p != b'-' { return core::ptr::null_mut(); }
11744 p = p.add(1);
11745 let (mv, mnp) = parse_range(p, 1, 12);
11746 if mnp == p { return core::ptr::null_mut(); }
11747 (*tm).tm_mon = mv - 1;
11748 p = mnp;
11749 if *p != b'-' { return core::ptr::null_mut(); }
11750 p = p.add(1);
11751 let (dv, dnp) = parse_range(p, 1, 31);
11752 if dnp == p { return core::ptr::null_mut(); }
11753 (*tm).tm_mday = dv;
11754 p = dnp;
11755 }
11756 b'H' | b'I' => {
11757 let (v, np) = parse_range(p, 0, 23);
11758 if np == p { return core::ptr::null_mut(); }
11759 (*tm).tm_hour = v;
11760 p = np;
11761 }
11762 b'j' => {
11763 let (v, np) = parse_range(p, 1, 366);
11764 if np == p { return core::ptr::null_mut(); }
11765 (*tm).tm_yday = v - 1;
11766 p = np;
11767 }
11768 b'm' => {
11769 let (v, np) = parse_range(p, 1, 12);
11770 if np == p { return core::ptr::null_mut(); }
11771 (*tm).tm_mon = v - 1;
11772 p = np;
11773 }
11774 b'M' => {
11775 let (v, np) = parse_range(p, 0, 59);
11776 if np == p { return core::ptr::null_mut(); }
11777 (*tm).tm_min = v;
11778 p = np;
11779 }
11780 b'n' | b't' => {
11781 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
11782 }
11783 b'p' => {
11784 if match_ci_prefix(p, b"AM") {
11785 if (*tm).tm_hour == 12 { (*tm).tm_hour = 0; }
11786 p = p.add(2);
11787 } else if match_ci_prefix(p, b"PM") {
11788 if (*tm).tm_hour < 12 { (*tm).tm_hour += 12; }
11789 p = p.add(2);
11790 } else { return core::ptr::null_mut(); }
11791 }
11792 b'r' => {
11793 let r = strptime(p as *const c_char, b"%I:%M:%S %p\0".as_ptr() as *const c_char, tm);
11794 if r.is_null() { return core::ptr::null_mut(); }
11795 p = r as *const u8;
11796 }
11797 b'R' => {
11798 let r = strptime(p as *const c_char, b"%H:%M\0".as_ptr() as *const c_char, tm);
11799 if r.is_null() { return core::ptr::null_mut(); }
11800 p = r as *const u8;
11801 }
11802 b's' => {
11803 let neg = if *p == b'-' { p = p.add(1); true } else { false };
11804 if *p < b'0' || *p > b'9' { return core::ptr::null_mut(); }
11805 let mut val = 0i64;
11806 while *p >= b'0' && *p <= b'9' {
11807 val = val * 10 + (*p - b'0') as i64;
11808 p = p.add(1);
11809 }
11810 if neg { val = -val; }
11811 secs_to_tm(val, &mut *tm);
11812 }
11813 b'S' => {
11814 let (v, np) = parse_range(p, 0, 60);
11815 if np == p { return core::ptr::null_mut(); }
11816 (*tm).tm_sec = v;
11817 p = np;
11818 }
11819 b'T' => {
11820 let r = strptime(p as *const c_char, b"%H:%M:%S\0".as_ptr() as *const c_char, tm);
11821 if r.is_null() { return core::ptr::null_mut(); }
11822 p = r as *const u8;
11823 }
11824 b'U' | b'W' => {
11825 let (_, np) = parse_range(p, 0, 53);
11826 if np == p { return core::ptr::null_mut(); }
11827 p = np;
11828 }
11829 b'V' => {
11830 let (_, np) = parse_range(p, 1, 53);
11831 if np == p { return core::ptr::null_mut(); }
11832 p = np;
11833 }
11834 b'w' => {
11835 let (v, np) = parse_range(p, 0, 6);
11836 if np == p { return core::ptr::null_mut(); }
11837 (*tm).tm_wday = v;
11838 p = np;
11839 }
11840 b'y' => {
11841 let (v, np) = parse_int(p, 2);
11842 if np == p { return core::ptr::null_mut(); }
11843 relyear = v;
11844 want_century |= 1;
11845 p = np;
11846 }
11847 b'Y' => {
11848 let neg = if *p == b'-' { p = p.add(1); true } else { false };
11849 let (v, np) = parse_int(p, 4);
11850 if np == p { return core::ptr::null_mut(); }
11851 (*tm).tm_year = if neg { -(v + 1900) } else { v - 1900 };
11852 want_century = 0;
11853 p = np;
11854 }
11855 b'z' => {
11856 if *p != b'+' && *p != b'-' { return core::ptr::null_mut(); }
11857 let neg = *p == b'-';
11858 p = p.add(1);
11859 let mut off = 0i64;
11860 let mut digits = 0;
11861 while digits < 4 && *p >= b'0' && *p <= b'9' {
11862 off = off * 10 + (*p - b'0') as i64;
11863 p = p.add(1);
11864 digits += 1;
11865 }
11866 if digits == 0 { return core::ptr::null_mut(); }
11867 let (hh, mm) = if digits <= 2 { (off, 0i64) } else { (off / 100, off % 100) };
11868 (*tm).tm_gmtoff = (hh * 3600 + mm * 60) * if neg { -1 } else { 1 };
11869 }
11870 b'%' => {
11871 if *p != b'%' { return core::ptr::null_mut(); }
11872 p = p.add(1);
11873 }
11874 _ => { return core::ptr::null_mut(); }
11875 }
11876 f = f.add(1);
11877 }
11878 if want_century != 0 {
11879 (*tm).tm_year = relyear;
11880 if want_century & 2 != 0 { (*tm).tm_year += century * 100 - 1900; }
11881 else if (*tm).tm_year <= 68 { (*tm).tm_year += 100; }
11882 }
11883 p as *mut c_char
11884}
11885
11886#[no_mangle]
11891pub static mut daylight: c_int = 0;
11892#[no_mangle]
11893pub static mut timezone: c_long = 0;
11894#[no_mangle]
11895pub 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];
11896
11897#[no_mangle]
11898pub unsafe extern "C" fn tzset() {
11899 daylight = 0;
11900 timezone = 0;
11901}
11902
11903#[no_mangle]
11908pub unsafe extern "C" fn system(cmd: *const c_char) -> c_int {
11909 if cmd.is_null() {
11910 let pid = sys_fork();
11912 if pid == 0 {
11913 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
11914 let dash_c = b"-c\0".as_ptr() as *const c_char;
11915 let exit0 = b"exit 0\0".as_ptr() as *const c_char;
11916 let argv = [b"sh\0".as_ptr() as *const c_char, dash_c, exit0, core::ptr::null()];
11917 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
11918 _exit(127);
11919 }
11920 if pid < 0 { return -1; }
11921 let mut status: c_int = 0;
11922 loop {
11923 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
11924 if r >= 0 { return status; }
11925 if r != -4 { return -1; } }
11927 }
11928
11929 let sa_ignore = sigaction {
11930 sa_handler: SIG_IGN,
11931 sa_flags: SA_RESTORER,
11932 sa_restorer: sig_restorer as *const () as usize,
11933 sa_mask: [0],
11934 };
11935 let mut oldint: sigaction = core::mem::zeroed();
11936 let mut oldquit: sigaction = core::mem::zeroed();
11937
11938 sys_rt_sigaction(SIGINT, &sa_ignore, &mut oldint, 8);
11939 sys_rt_sigaction(SIGQUIT, &sa_ignore, &mut oldquit, 8);
11940
11941 let mut block_set: SigSetT = 0;
11942 block_set |= 1u64 << (SIGCHLD - 1);
11943 let mut oldmask: SigSetT = 0;
11944 sys_rt_sigprocmask(SIG_BLOCK, &block_set, &mut oldmask, 8);
11945
11946 let pid = sys_fork();
11947
11948 if pid == 0 {
11949 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
11950 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
11951 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
11952
11953 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
11954 let argv = [
11955 b"sh\0".as_ptr() as *const c_char,
11956 b"-c\0".as_ptr() as *const c_char,
11957 cmd,
11958 core::ptr::null(),
11959 ];
11960 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
11961 _exit(127);
11962 }
11963
11964 let mut status: c_int = -1;
11965 if pid > 0 {
11966 loop {
11967 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
11968 if r >= 0 { break; }
11969 if r != -4 { break; } }
11971 }
11972
11973 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
11974 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
11975 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
11976
11977 status
11978}
11979
11980const EPERM_VAL: c_int = 1;
11985const ENOENT_VAL: c_int = 2;
11986const ESRCH_VAL: c_int = 3;
11987const EINTR_VAL: c_int = 4;
11988const EIO_VAL: c_int = 5;
11989const ENXIO_VAL: c_int = 6;
11990const E2BIG_VAL: c_int = 7;
11991const ENOEXEC_VAL: c_int = 8;
11992const EBADF_VAL: c_int = 9;
11993const ECHILD_VAL: c_int = 10;
11994const EAGAIN_VAL: c_int = 11;
11995const ENOMEM_VAL: c_int = 12;
11996const EACCES_VAL: c_int = 13;
11997const EFAULT_VAL: c_int = 14;
11998const ENOTBLK_VAL: c_int = 15;
11999const EBUSY_VAL: c_int = 16;
12000const EEXIST_VAL: c_int = 17;
12001const EXDEV_VAL: c_int = 18;
12002const ENODEV_VAL: c_int = 19;
12003const ENOTDIR_VAL: c_int = 20;
12004const EISDIR_VAL: c_int = 21;
12005const EINVAL_VAL: c_int = 22;
12006const ENFILE_VAL: c_int = 23;
12007const EMFILE_VAL: c_int = 24;
12008const ENOTTY_VAL: c_int = 25;
12009const ETXTBSY_VAL: c_int = 26;
12010const EFBIG_VAL: c_int = 27;
12011const ENOSPC_VAL: c_int = 28;
12012const ESPIPE_VAL: c_int = 29;
12013const EROFS_VAL: c_int = 30;
12014const EMLINK_VAL: c_int = 31;
12015const EPIPE_VAL: c_int = 32;
12016const EDOM_VAL: c_int = 33;
12017const ERANGE_VAL: c_int = 34;
12018const EDEADLK_VAL: c_int = 35;
12019const ENAMETOOLONG_VAL: c_int = 36;
12020const ENOLCK_VAL: c_int = 37;
12021const ENOSYS_VAL: c_int = 38;
12022const ENOTEMPTY_VAL: c_int = 39;
12023const ELOOP_VAL: c_int = 40;
12024const EWOULDBLOCK_VAL: c_int = 11;
12025const ENOMSG_VAL: c_int = 42;
12026const EIDRM_VAL: c_int = 43;
12027const ECHRNG_VAL: c_int = 44;
12028const EL2NSYNC_VAL: c_int = 45;
12029const EL3HLT_VAL: c_int = 46;
12030const EL3RST_VAL: c_int = 47;
12031const ELNRNG_VAL: c_int = 48;
12032const EUNATCH_VAL: c_int = 49;
12033const ENOCSI_VAL: c_int = 50;
12034const EL2HLT_VAL: c_int = 51;
12035const EBADE_VAL: c_int = 52;
12036const EBADR_VAL: c_int = 53;
12037const EXFULL_VAL: c_int = 54;
12038const ENOANO_VAL: c_int = 55;
12039const EBADRQC_VAL: c_int = 56;
12040const EBADSLT_VAL: c_int = 57;
12041const EBFONT_VAL: c_int = 59;
12042const ENOSTR_VAL: c_int = 60;
12043const ENODATA_VAL: c_int = 61;
12044const ETIME_VAL: c_int = 62;
12045const ENOSR_VAL: c_int = 63;
12046const ENONET_VAL: c_int = 64;
12047const ENOPKG_VAL: c_int = 65;
12048const EREMOTE_VAL: c_int = 66;
12049const ENOLINK_VAL: c_int = 67;
12050const EADV_VAL: c_int = 68;
12051const ESRMNT_VAL: c_int = 69;
12052const ECOMM_VAL: c_int = 70;
12053const EPROTO_VAL: c_int = 71;
12054const EMULTIHOP_VAL: c_int = 72;
12055const EDOTDOT_VAL: c_int = 73;
12056const EBADMSG_VAL: c_int = 74;
12057const EOVERFLOW_VAL: c_int = 75;
12058const ENOTUNIQ_VAL: c_int = 76;
12059const EBADFD_VAL: c_int = 77;
12060const EREMCHG_VAL: c_int = 78;
12061const ELIBACC_VAL: c_int = 79;
12062const ELIBBAD_VAL: c_int = 80;
12063const ELIBSCN_VAL: c_int = 81;
12064const ELIBMAX_VAL: c_int = 82;
12065const ELIBEXEC_VAL: c_int = 83;
12066const EILSEQ_VAL: c_int = 84;
12067const ERESTART_VAL: c_int = 85;
12068const ESTRPIPE_VAL: c_int = 86;
12069const EUSERS_VAL: c_int = 87;
12070const ENOTSOCK_VAL: c_int = 88;
12071const EDESTADDRREQ_VAL: c_int = 89;
12072const EMSGSIZE_VAL: c_int = 90;
12073const EPROTOTYPE_VAL: c_int = 91;
12074const ENOPROTOOPT_VAL: c_int = 92;
12075const EPROTONOSUPPORT_VAL: c_int = 93;
12076const ESOCKTNOSUPPORT_VAL: c_int = 94;
12077const EOPNOTSUPP_VAL: c_int = 95;
12078const ENOTSUP_VAL: c_int = 95;
12079const EPFNOSUPPORT_VAL: c_int = 96;
12080const EAFNOSUPPORT_VAL: c_int = 97;
12081const EADDRINUSE_VAL: c_int = 98;
12082const EADDRNOTAVAIL_VAL: c_int = 99;
12083const ENETDOWN_VAL: c_int = 100;
12084const ENETUNREACH_VAL: c_int = 101;
12085const ENETRESET_VAL: c_int = 102;
12086const ECONNABORTED_VAL: c_int = 103;
12087const ECONNRESET_VAL: c_int = 104;
12088const ENOBUFS_VAL: c_int = 105;
12089const EISCONN_VAL: c_int = 106;
12090const ENOTCONN_VAL: c_int = 107;
12091const ESHUTDOWN_VAL: c_int = 108;
12092const ETOOMANYREFS_VAL: c_int = 109;
12093const ETIMEDOUT_VAL: c_int = 110;
12094const ECONNREFUSED_VAL: c_int = 111;
12095const EHOSTDOWN_VAL: c_int = 112;
12096const EHOSTUNREACH_VAL: c_int = 113;
12097const EALREADY_VAL: c_int = 114;
12098const EINPROGRESS_VAL: c_int = 115;
12099const ESTALE_VAL: c_int = 116;
12100const EUCLEAN_VAL: c_int = 117;
12101const ENOTNAM_VAL: c_int = 118;
12102const ENAVAIL_VAL: c_int = 119;
12103const EISNAM_VAL: c_int = 120;
12104const EREMOTEIO_VAL: c_int = 121;
12105const EDQUOT_VAL: c_int = 122;
12106const ENOMEDIUM_VAL: c_int = 123;
12107const EMEDIUMTYPE_VAL: c_int = 124;
12108const ECANCELED_VAL: c_int = 125;
12109const ENOKEY_VAL: c_int = 126;
12110const EKEYEXPIRED_VAL: c_int = 127;
12111const EKEYREVOKED_VAL: c_int = 128;
12112const EKEYREJECTED_VAL: c_int = 129;
12113const EOWNERDEAD_VAL: c_int = 130;
12114const ENOTRECOVERABLE_VAL: c_int = 131;
12115const ERFKILL_VAL: c_int = 132;
12116const EHWPOISON_VAL: c_int = 133;
12117
12118static ERR_STRS: [&[u8]; 134] = [
12120 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", ];
12255
12256#[no_mangle]
12257pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char {
12258 if errnum < 0 || errnum as usize >= ERR_STRS.len() {
12259 static mut UNKNOWN_BUF: [c_char; 32] = [0; 32];
12261 let prefix = b"Unknown error \0";
12262 let mut i = 0;
12263 while prefix[i] != 0 {
12264 UNKNOWN_BUF[i] = prefix[i] as c_char;
12265 i += 1;
12266 }
12267 let (buf, len) = format_u64(errnum as u64);
12268 for j in 0..len {
12269 UNKNOWN_BUF[i] = buf[20 - len + j] as c_char;
12270 i += 1;
12271 }
12272 UNKNOWN_BUF[i] = 0;
12273 return core::ptr::addr_of_mut!(UNKNOWN_BUF).cast::<c_char>();
12274 }
12275 ERR_STRS[errnum as usize].as_ptr() as *mut c_char
12276}
12277
12278#[no_mangle]
12279pub unsafe extern "C" fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: usize) -> c_int {
12280 let s = strerror(errnum);
12281 let slen = strlen(s as *const c_char);
12282 if slen >= buflen {
12283 if buflen > 0 {
12284 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, buflen - 1);
12285 *buf.add(buflen - 1) = 0;
12286 }
12287 return 34; }
12289 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, slen + 1);
12290 0
12291}
12292
12293#[no_mangle]
12295pub static mut environ: *mut *mut c_char = core::ptr::null_mut();
12296
12297unsafe fn sync_environ() {
12299 environ = __environ;
12300}
12301
12302#[inline]
12307unsafe fn sys_dup(oldfd: i32) -> i64 {
12308 <Arch as Syscalls>::syscall1(SYS_DUP, oldfd as i64)
12309}
12310
12311#[inline]unsafe fn sys_dup2(oldfd: i32, newfd: i32) -> i64 {
12312 sys_dup3(oldfd, newfd, 0)
12314}
12315
12316#[inline]
12317unsafe fn sys_access(path: *const u8, mode: i32) -> i64 {
12318 <Arch as Syscalls>::syscall4(SYS_FACCESSAT, AT_FDCWD as i64, path as i64, mode as i64, 0)
12319}
12320
12321#[inline]unsafe fn sys_unlink(path: *const u8) -> i64 {
12322 sys_unlinkat(AT_FDCWD, path, 0)
12323}
12324
12325#[inline]unsafe fn sys_rmdir(path: *const u8) -> i64 {
12326 sys_unlinkat(AT_FDCWD, path, 512) }
12328
12329#[inline]
12330unsafe fn sys_chdir(path: *const u8) -> i64 {
12331 <Arch as Syscalls>::syscall1(SYS_CHDIR, path as i64)
12332}
12333
12334#[inline]
12335unsafe fn sys_getcwd(buf: *mut u8, size: usize) -> i64 {
12336 <Arch as Syscalls>::syscall2(SYS_GETCWD, buf as i64, size as i64)
12337}
12338
12339#[inline]
12340unsafe fn sys_sethostname(name: *const u8, len: usize) -> i64 {
12341 <Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64)
12342}
12343
12344#[inline]
12345unsafe fn sys_gethostname(buf: *mut u8, len: usize) -> i64 {
12346 #[repr(C)]
12347 struct UtsName {
12348 sysname: [u8; 65],
12349 nodename: [u8; 65],
12350 release: [u8; 65],
12351 version: [u8; 65],
12352 machine: [u8; 65],
12353 domainname: [u8; 65],
12354 }
12355 let mut uts: UtsName = core::mem::zeroed();
12356 let result = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
12357 if result < 0 {
12358 return result;
12359 }
12360 let nlen = strlen(uts.nodename.as_ptr() as *const c_char);
12361 let copylen = if nlen < len { nlen } else { if len > 0 { len - 1 } else { 0 } };
12362 core::ptr::copy_nonoverlapping(uts.nodename.as_ptr(), buf, copylen);
12363 if len > 0 { *buf.add(copylen) = 0; }
12364 0
12365}
12366
12367unsafe fn sys_truncate(path: *const u8, length: i64) -> i64 {
12368 <Arch as Syscalls>::syscall2(SYS_TRUNCATE, path as i64, length as i64)
12369}
12370
12371unsafe fn sys_ftruncate(fd: i32, length: i64) -> i64 {
12372 <Arch as Syscalls>::syscall2(SYS_FTRUNCATE, fd as i64, length as i64)
12373}
12374
12375unsafe fn sys_nanosleep(req: *const timespec, rem: *mut timespec) -> i64 {
12376 <Arch as Syscalls>::syscall2(SYS_NANOSLEEP, req as i64, rem as i64)
12377}
12378
12379const ITIMER_REAL: i32 = 0;
12380
12381#[repr(C)]
12382struct itimerval {
12383 it_interval: timeval,
12384 it_value: timeval,
12385}
12386
12387unsafe fn sys_alarm(seconds: c_uint) -> i64 {
12388 let mut new: itimerval = core::mem::zeroed();
12389 new.it_value.tv_sec = seconds as c_long;
12390 let mut old: itimerval = core::mem::zeroed();
12391 let r = <Arch as Syscalls>::syscall3(
12392 SYS_SETITIMER,
12393 ITIMER_REAL as i64,
12394 &new as *const _ as i64,
12395 &mut old as *mut _ as i64,
12396 );
12397 if r < 0 {
12398 return r;
12399 }
12400 old.it_value.tv_sec as i64
12401}
12402
12403unsafe fn sys_pause() -> i64 {
12404 #[cfg(target_arch = "x86_64")]
12405 { <Arch as Syscalls>::syscall0(SYS_PAUSE) }
12406 #[cfg(target_arch = "aarch64")]
12407 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12408 #[cfg(target_arch = "riscv64")]
12409 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12410}
12411
12412unsafe fn sys_fsync(fd: i32) -> i64 {
12413 <Arch as Syscalls>::syscall1(SYS_FSYNC, fd as i64)
12414}
12415
12416unsafe fn sys_fdatasync(fd: i32) -> i64 {
12417 <Arch as Syscalls>::syscall1(SYS_FDATASYNC, fd as i64)
12418}
12419
12420unsafe fn sys_sync() {
12421 let _ = <Arch as Syscalls>::syscall0(SYS_SYNC);
12422}
12423
12424unsafe fn sys_symlink(target: *const u8, linkpath: *const u8) -> i64 {
12425 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, AT_FDCWD as i64, linkpath as i64)
12426}
12427
12428unsafe fn sys_symlinkat(target: *const u8, newdirfd: i32, linkpath: *const u8) -> i64 {
12429 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64)
12430}
12431
12432unsafe fn sys_readlinkat(dirfd: i32, path: *const u8, buf: *mut u8, bufsiz: usize) -> i64 {
12433 <Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, path as i64, buf as i64, bufsiz as i64)
12434}
12435
12436unsafe fn sys_linkat(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: i32) -> i64 {
12437 <Arch as Syscalls>::syscall5(SYS_LINKAT, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
12438}
12439
12440unsafe fn sys_fchmod(fd: i32, mode: u32) -> i64 {
12441 <Arch as Syscalls>::syscall2(SYS_FCHMOD, fd as i64, mode as i64)
12442}
12443
12444unsafe fn sys_fchmodat(dirfd: i32, path: *const u8, mode: u32, flags: i32) -> i64 {
12445 <Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, path as i64, mode as i64, flags as i64)
12446}
12447
12448unsafe fn sys_umask(mask: u32) -> u32 {
12449 <Arch as Syscalls>::syscall1(SYS_UMASK, mask as i64) as u32
12450}
12451
12452unsafe fn sys_getgroups(size: i32, list: *mut c_uint) -> i64 {
12453 <Arch as Syscalls>::syscall2(SYS_GETGROUPS, size as i64, list as i64)
12454}
12455
12456unsafe fn sys_setuid(uid: c_uint) -> i64 {
12457 <Arch as Syscalls>::syscall1(SYS_SETUID, uid as i64)
12458}
12459
12460unsafe fn sys_setgid(gid: c_uint) -> i64 {
12461 <Arch as Syscalls>::syscall1(SYS_SETGID, gid as i64)
12462}
12463
12464unsafe fn sys_setsid() -> i64 {
12465 <Arch as Syscalls>::syscall0(SYS_SETSID)
12466}
12467
12468unsafe fn sys_setpgid(pid: c_int, pgid: c_int) -> i64 {
12469 <Arch as Syscalls>::syscall2(SYS_SETPGID, pid as i64, pgid as i64)
12470}
12471
12472unsafe fn sys_getpgid(pid: c_int) -> i64 {
12473 <Arch as Syscalls>::syscall1(SYS_GETPGID, pid as i64)
12474}
12475
12476unsafe fn sys_getsid(pid: c_int) -> i64 {
12477 <Arch as Syscalls>::syscall1(SYS_GETSID, pid as i64)
12478}
12479
12480unsafe fn sys_mkdirat(dirfd: i32, path: *const u8, mode: u32) -> i64 {
12481 <Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, path as i64, mode as i64)
12482}
12483
12484#[no_mangle]
12487pub unsafe extern "C" fn pipe(fds: *mut c_int) -> c_int {
12488 let r = sys_pipe2(fds, 0);
12489 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12490 0
12491}
12492
12493#[no_mangle]
12494pub unsafe extern "C" fn pipe2(fds: *mut c_int, flags: c_int) -> c_int {
12495 let r = sys_pipe2(fds, flags);
12496 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12497 0
12498}
12499
12500#[no_mangle]
12501pub unsafe extern "C" fn dup(oldfd: c_int) -> c_int {
12502 let r = sys_dup(oldfd);
12503 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12504 r as c_int
12505}
12506
12507#[no_mangle]
12508pub unsafe extern "C" fn dup2(oldfd: c_int, newfd: c_int) -> c_int {
12509 let r = sys_dup2(oldfd, newfd);
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 dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int {
12516 let r = sys_dup3(oldfd, newfd, flags);
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 fcntl(fd: c_int, cmd: c_int, mut args: ...) -> c_int {
12523 let r = match cmd {
12524 F_GETFD | F_GETFL => sys_fcntl(fd, cmd, 0),
12525 F_SETFD | F_SETFL | F_DUPFD | F_DUPFD_CLOEXEC => {
12526 let arg = args.next_arg::<c_int>();
12527 sys_fcntl(fd, cmd, arg as i64)
12528 }
12529 F_GETLK | F_SETLK | F_SETLKW => {
12530 let arg = args.next_arg::<*mut c_void>();
12531 sys_fcntl(fd, cmd, arg as i64)
12532 }
12533 _ => sys_fcntl(fd, cmd, 0),
12534 };
12535 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12536 r as c_int
12537}
12538
12539#[no_mangle]
12540pub unsafe extern "C" fn access(path: *const c_char, mode: c_int) -> c_int {
12541 let r = sys_access(path as *const u8, mode);
12542 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12543 0
12544}
12545
12546#[no_mangle]
12547pub unsafe extern "C" fn unlink(path: *const c_char) -> c_int {
12548 let r = sys_unlink(path as *const u8);
12549 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12550 0
12551}
12552
12553#[no_mangle]
12554pub unsafe extern "C" fn rmdir(path: *const c_char) -> c_int {
12555 let r = sys_rmdir(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 chdir(path: *const c_char) -> c_int {
12562 let r = sys_chdir(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 getcwd(buf: *mut c_char, size: usize) -> *mut c_char {
12569 if buf.is_null() {
12570 let alloc_size = if size == 0 { 256 } else { size };
12572 let p = malloc(alloc_size) as *mut c_char;
12573 if p.is_null() { ERRNO = ENOMEM; return core::ptr::null_mut(); }
12574 let r = sys_getcwd(p as *mut u8, alloc_size);
12575 if r < 0 { free(p as *mut c_void); ERRNO = (-r) as c_int; return core::ptr::null_mut(); }
12576 return p;
12577 }
12578 if size == 0 { ERRNO = EINVAL; return core::ptr::null_mut(); }
12579 let r = sys_getcwd(buf as *mut u8, size);
12580 if r < 0 { ERRNO = (-r) as c_int; return core::ptr::null_mut(); }
12581 buf
12582}
12583
12584#[no_mangle]
12585pub unsafe extern "C" fn gethostname(name: *mut c_char, len: usize) -> c_int {
12586 let r = sys_gethostname(name as *mut u8, len);
12587 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12588 0
12589}
12590
12591#[no_mangle]
12593pub extern "C" fn getpagesize() -> c_int {
12594 4096
12595}
12596
12597#[no_mangle]
12598pub unsafe extern "C" fn truncate(path: *const c_char, length: i64) -> c_int {
12599 let r = sys_truncate(path as *const u8, length);
12600 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12601 0
12602}
12603
12604#[no_mangle]
12605pub unsafe extern "C" fn ftruncate(fd: c_int, length: i64) -> c_int {
12606 let r = sys_ftruncate(fd, length);
12607 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12608 0
12609}
12610
12611#[no_mangle]
12612pub unsafe extern "C" fn nanosleep(req: *const timespec, rem: *mut timespec) -> c_int {
12613 pthread_testcancel();
12614 let r = sys_nanosleep(req, rem);
12615 pthread_testcancel();
12616 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12617 0
12618}
12619
12620#[no_mangle]
12621pub unsafe extern "C" fn sleep(seconds: c_uint) -> c_uint {
12622 let req = timespec { tv_sec: seconds as c_long, tv_nsec: 0 };
12623 let mut rem: timespec = core::mem::zeroed();
12624 pthread_testcancel();
12625 let r = sys_nanosleep(&req, &mut rem);
12626 pthread_testcancel();
12627 if r < 0 {
12628 let e = (-r) as c_int;
12629 if e == EINTR { return rem.tv_sec as c_uint; }
12630 }
12631 0
12632}
12633
12634#[no_mangle]
12635pub unsafe extern "C" fn usleep(usec: c_uint) -> c_int {
12636 let req = timespec { tv_sec: (usec / 1000000) as c_long, tv_nsec: ((usec % 1000000) * 1000) as c_long };
12637 pthread_testcancel();
12638 let r = sys_nanosleep(&req, core::ptr::null_mut());
12639 pthread_testcancel();
12640 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12641 0
12642}
12643
12644#[no_mangle]
12645pub unsafe extern "C" fn alarm(seconds: c_uint) -> c_uint {
12646 sys_alarm(seconds) as c_uint
12647}
12648
12649#[no_mangle]
12650pub unsafe extern "C" fn pause() -> c_int {
12651 pthread_testcancel();
12652 sys_pause();
12653 pthread_testcancel();
12654 ERRNO = EINTR;
12655 -1
12656}
12657
12658#[no_mangle]
12659pub unsafe extern "C" fn fsync(fd: c_int) -> c_int {
12660 let r = sys_fsync(fd);
12661 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12662 0
12663}
12664
12665#[no_mangle]
12666pub unsafe extern "C" fn fdatasync(fd: c_int) -> c_int {
12667 let r = sys_fdatasync(fd);
12668 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12669 0
12670}
12671
12672#[no_mangle]
12673pub unsafe extern "C" fn sync() {
12674 sys_sync();
12675}
12676
12677#[no_mangle]
12678pub unsafe extern "C" fn symlink(target: *const c_char, linkpath: *const c_char) -> c_int {
12679 let r = sys_symlinkat(target as *const u8, AT_FDCWD, linkpath as *const u8);
12680 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12681 0
12682}
12683
12684#[no_mangle]
12685pub unsafe extern "C" fn readlink(path: *const c_char, buf: *mut c_char, bufsiz: usize) -> isize {
12686 let r = sys_readlinkat(AT_FDCWD, path as *const u8, buf as *mut u8, bufsiz);
12687 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12688 r as isize
12689}
12690
12691#[no_mangle]
12692pub unsafe extern "C" fn link(oldpath: *const c_char, newpath: *const c_char) -> c_int {
12693 let r = sys_linkat(AT_FDCWD, oldpath as *const u8, AT_FDCWD, newpath as *const u8, 0);
12694 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12695 0
12696}
12697
12698#[no_mangle]
12699pub unsafe extern "C" fn chmod(path: *const c_char, mode: c_uint) -> c_int {
12700 let r = sys_fchmodat(AT_FDCWD, path as *const u8, mode, 0);
12701 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12702 0
12703}
12704
12705#[no_mangle]
12706pub unsafe extern "C" fn fchmod(fd: c_int, mode: c_uint) -> c_int {
12707 let r = sys_fchmod(fd, mode);
12708 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12709 0
12710}
12711
12712#[no_mangle]
12713pub unsafe extern "C" fn umask(mask: c_uint) -> c_uint {
12714 sys_umask(mask) as c_uint
12715}
12716
12717#[no_mangle]
12718pub unsafe extern "C" fn isatty(fd: c_int) -> c_int {
12719 let mut ws: winsize = core::mem::zeroed();
12720 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 { 1 } else { 0 }
12721}
12722
12723#[no_mangle]
12724pub unsafe extern "C" fn getlogin() -> *mut c_char {
12725 static mut LOGIN_BUF: [c_char; 32] = [0; 32];
12726 let pw = getpwuid(crate::getuid());
12727 if pw.is_null() { return core::ptr::null_mut(); }
12728 let n = crate::strlen((*pw).pw_name);
12729 if n + 1 > LOGIN_BUF.len() { return core::ptr::null_mut(); }
12730 core::ptr::copy_nonoverlapping((*pw).pw_name, LOGIN_BUF.as_mut_ptr(), n + 1);
12731 LOGIN_BUF.as_mut_ptr()
12732}
12733
12734#[no_mangle]
12735pub unsafe extern "C" fn getgroups(size: c_int, list: *mut c_uint) -> c_int {
12736 let r = sys_getgroups(size, list);
12737 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12738 r as c_int
12739}
12740
12741#[no_mangle]
12742pub unsafe extern "C" fn setuid(uid: c_uint) -> c_int {
12743 let r = sys_setuid(uid);
12744 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12745 0
12746}
12747
12748#[no_mangle]
12749pub unsafe extern "C" fn setgid(gid: c_uint) -> c_int {
12750 let r = sys_setgid(gid);
12751 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12752 0
12753}
12754
12755#[no_mangle]
12756pub unsafe extern "C" fn seteuid(euid: c_uint) -> c_int {
12757 let r = sys_setuid(euid);
12759 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12760 0
12761}
12762
12763#[no_mangle]
12764pub unsafe extern "C" fn setegid(egid: c_uint) -> c_int {
12765 let r = sys_setgid(egid);
12766 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12767 0
12768}
12769
12770#[no_mangle]
12771pub unsafe extern "C" fn setreuid(ruid: c_uint, euid: c_uint) -> c_int {
12772 let r = <Arch as Syscalls>::syscall2(sysno(113, 145), ruid as i64, euid as i64);
12773 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
12774}
12775
12776
12777
12778#[no_mangle]
12779pub unsafe extern "C" fn setsid() -> c_int {
12780 let r = sys_setsid();
12781 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12782 r as c_int
12783}
12784
12785#[no_mangle]
12786pub unsafe extern "C" fn setpgid(pid: c_int, pgid: c_int) -> c_int {
12787 let r = sys_setpgid(pid, pgid);
12788 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12789 0
12790}
12791
12792#[no_mangle]
12793pub unsafe extern "C" fn getpgid(pid: c_int) -> c_int {
12794 let r = sys_getpgid(pid);
12795 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12796 r as c_int
12797}
12798
12799#[no_mangle]
12800pub unsafe extern "C" fn getsid(pid: c_int) -> c_int {
12801 let r = sys_getsid(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 getpgrp() -> c_int {
12808 sys_getpgid(0) as c_int
12809}
12810
12811#[no_mangle]
12812pub unsafe extern "C" fn setpgrp() -> c_int {
12813 setpgid(0, 0)
12814}
12815
12816#[no_mangle]
12817pub unsafe extern "C" fn mkstemp(template: *mut c_char) -> c_int {
12818 if template.is_null() { ERRNO = EINVAL; return -1; }
12819 let len = strlen(template as *const c_char);
12820 if len < 6 { ERRNO = EINVAL; return -1; }
12821 let x_start = len - 6;
12822 for i in x_start..len {
12824 if *template.add(i) != b'X' as c_char { ERRNO = EINVAL; return -1; }
12825 }
12826 let mut ts: timespec = core::mem::zeroed();
12827 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
12828 let mut ctr: u32 = ts.tv_nsec as u32;
12829 for _ in 0..100 {
12830 ctr = ctr.wrapping_mul(1103515245).wrapping_add(12345);
12831 let seed = ctr;
12832 let hex = b"0123456789abcdef";
12834 let mut s = seed;
12835 for i in x_start..len {
12836 *template.add(i) = hex[(s & 0xf) as usize] as c_char;
12837 s >>= 4;
12838 }
12839 let fd = sys_open(template as *const u8, (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
12840 if fd >= 0 { return fd as c_int; }
12841 let e = (-fd) as c_int;
12842 if e != EEXIST_VAL { ERRNO = e; return -1; }
12843 }
12844 ERRNO = EEXIST_VAL;
12845 -1
12846}
12847
12848#[no_mangle]
12849pub unsafe extern "C" fn mkdir(path: *const c_char, mode: c_uint) -> c_int {
12850 let r = sys_mkdirat(AT_FDCWD, path as *const u8, mode);
12851 if r < 0 { ERRNO = (-r) as c_int; return -1; }
12852 0
12853}
12854
12855#[no_mangle]
12860pub unsafe extern "C" fn dirname(s: *mut c_char) -> *mut c_char {
12861 if s.is_null() || *s == 0 {
12862 return b".\0".as_ptr() as *mut c_char;
12863 }
12864 let mut i = strlen(s as *const c_char);
12865 i = i.wrapping_sub(1);
12866 while i > 0 && *s.add(i) == b'/' as c_char {
12868 i = i.wrapping_sub(1);
12869 }
12870 if i == 0 && *s.add(0) == b'/' as c_char {
12871 return b"/\0".as_ptr() as *mut c_char;
12872 }
12873 while i > 0 && *s.add(i) != b'/' as c_char {
12875 i = i.wrapping_sub(1);
12876 }
12877 if i == 0 {
12878 if *s.add(0) == b'/' as c_char {
12879 return b"/\0".as_ptr() as *mut c_char;
12880 }
12881 return b".\0".as_ptr() as *mut c_char;
12882 }
12883 while i > 0 && *s.add(i - 1) == b'/' as c_char {
12885 i = i.wrapping_sub(1);
12886 }
12887 if i == 0 {
12888 return b"/\0".as_ptr() as *mut c_char;
12889 }
12890 *s.add(i) = 0;
12891 s
12892}
12893
12894#[no_mangle]
12895pub unsafe extern "C" fn basename(s: *mut c_char) -> *mut c_char {
12896 if s.is_null() || *s == 0 {
12897 return b".\0".as_ptr() as *mut c_char;
12898 }
12899 let mut i = strlen(s as *const c_char);
12900 i = i.wrapping_sub(1);
12901 while i > 0 && *s.add(i) == b'/' as c_char {
12903 *s.add(i) = 0;
12904 i = i.wrapping_sub(1);
12905 }
12906 while i > 0 && *s.add(i - 1) != b'/' as c_char {
12908 i = i.wrapping_sub(1);
12909 }
12910 s.add(i)
12911}
12912
12913const AF_INET_VAL: c_int = 2;
12918const AF_INET6_VAL: c_int = 10;
12919const EAFNOSUPPORT: c_int = 97;
12920const ENOSPC_VAL2: c_int = 28;
12921
12922unsafe fn inet_pton_v4(s: *const u8, a: *mut u8) -> c_int {
12923 let mut p = s;
12924 let mut i = 0;
12925 while i < 4 {
12926 let oct_start = p;
12927 let mut v: u32 = 0;
12928 let mut j: u32 = 0;
12929 while j < 3 && *p >= b'0' && *p <= b'9' {
12930 v = v * 10 + (*p - b'0') as u32;
12931 p = p.add(1);
12932 j += 1;
12933 }
12934 if j == 0 || (j > 1 && *oct_start == b'0') || v > 255 { return 0; }
12935 *a.add(i) = v as u8;
12936 if *p == 0 && i == 3 { return 1; }
12937 if *p != b'.' { return 0; }
12938 p = p.add(1);
12939 i += 1;
12940 }
12941 0
12942}
12943
12944unsafe fn inet_pton_v6(s: *const u8, a: *mut u8) -> c_int {
12945 let mut ip = [0u16; 8];
12946 let mut p = s;
12947 let mut i: usize = 0;
12948 let mut brk: isize = -1;
12949 let mut need_v4 = false;
12950 let mut v4_start: *const u8 = core::ptr::null();
12951
12952 if *p == b':' {
12953 p = p.add(1);
12954 if *p != b':' { return 0; }
12955 }
12956
12957 loop {
12958 if *p == b':' && brk < 0 {
12959 brk = i as isize;
12960 ip[i & 7] = 0;
12961 p = p.add(1);
12962 if *p == 0 { break; }
12963 if i == 7 { return 0; }
12964 i += 1;
12965 continue;
12966 }
12967 v4_start = p;
12968 let mut v: u16 = 0;
12969 let mut j = 0;
12970 while j < 4 {
12971 let d = hex_digit(*p);
12972 if d < 0 { break; }
12973 v = v * 16 + d as u16;
12974 p = p.add(1);
12975 j += 1;
12976 }
12977 if j == 0 { return 0; }
12978 ip[i & 7] = v;
12979 if *p == 0 && (brk >= 0 || i == 7) { break; }
12980 if i == 7 { return 0; }
12981 if *p != b':' {
12982 if *p != b'.' || (i < 6 && brk < 0) { return 0; }
12983 need_v4 = true;
12984 i += 1;
12985 ip[i & 7] = 0;
12986 break;
12987 }
12988 p = p.add(1);
12989 i += 1;
12990 }
12991
12992 if brk >= 0 {
12993 let trail_count = i + 1 - brk as usize;
12995 let dest_start = brk as usize + 7 - i;
12996 for j in (0..trail_count).rev() {
12998 ip[dest_start + j] = ip[brk as usize + j];
12999 }
13000 for j in 0..(7 - i) {
13001 ip[brk as usize + j] = 0;
13002 }
13003 }
13004
13005 for k in 0..8 {
13006 *a.add(k * 2) = (ip[k] >> 8) as u8;
13007 *a.add(k * 2 + 1) = (ip[k] & 0xff) as u8;
13008 }
13009
13010 if need_v4 {
13011 if inet_pton_v4(v4_start, a.add(12)) <= 0 { return 0; }
13012 }
13013 1
13014}
13015
13016unsafe fn hex_digit(c: u8) -> i32 {
13017 if c >= b'0' && c <= b'9' { (c - b'0') as i32 }
13018 else if c >= b'a' && c <= b'f' { (c - b'a' + 10) as i32 }
13019 else if c >= b'A' && c <= b'F' { (c - b'A' + 10) as i32 }
13020 else { -1 }
13021}
13022
13023#[no_mangle]
13024pub unsafe extern "C" fn inet_pton(af: c_int, s: *const c_char, a: *mut c_void) -> c_int {
13025 if af == AF_INET_VAL {
13026 inet_pton_v4(s as *const u8, a as *mut u8)
13027 } else if af == AF_INET6_VAL {
13028 inet_pton_v6(s as *const u8, a as *mut u8)
13029 } else {
13030 ERRNO = EAFNOSUPPORT;
13031 -1
13032 }
13033}
13034
13035#[no_mangle]
13036pub unsafe extern "C" fn inet_ntop(af: c_int, a: *const c_void, s: *mut c_char, size: u32) -> *mut c_char {
13037 if af == AF_INET_VAL {
13038 let b = a as *const u8;
13039 let needed = 16; if size < needed as u32 { ERRNO = ENOSPC_VAL2; return core::ptr::null_mut(); }
13041 let mut pos = 0;
13042 for i in 0..4 {
13043 if i > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
13044 let (buf, len) = format_u64(*b.add(i) as u64);
13045 for j in 0..len { *s.add(pos) = buf[j] as c_char; pos += 1; }
13046 }
13047 *s.add(pos) = 0;
13048 s
13049 } else if af == AF_INET6_VAL {
13050 let b = a as *const u8;
13051 let needed = 46; if size < needed as u32 { ERRNO = ENOSPC_VAL2; return core::ptr::null_mut(); }
13053 let mut words = [0u16; 8];
13054 for i in 0..8 {
13055 words[i] = ((*b.add(i * 2) as u16) << 8) | (*b.add(i * 2 + 1) as u16);
13056 }
13057 let mut pos = 0usize;
13059 if words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0
13060 && words[4] == 0 && words[5] == 0xffff
13061 {
13062 let prefix = b"::ffff:";
13063 for k in 0..prefix.len() { *s.add(pos) = prefix[k] as c_char; pos += 1; }
13064 for idx in 0..4 {
13065 if idx > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
13066 let octet = *b.add(12 + idx);
13067 if octet >= 100 {
13068 *s.add(pos) = (b'0' + octet / 100) as c_char; pos += 1;
13069 *s.add(pos) = (b'0' + (octet / 10) % 10) as c_char; pos += 1;
13070 } else if octet >= 10 {
13071 *s.add(pos) = (b'0' + octet / 10) as c_char; pos += 1;
13072 }
13073 *s.add(pos) = (b'0' + octet % 10) as c_char; pos += 1;
13074 }
13075 *s.add(pos) = 0;
13076 return s;
13077 }
13078 let mut best_start: isize = -1;
13080 let mut best_len: usize = 0;
13081 let mut j: usize = 0;
13082 while j < 8 {
13083 if words[j] == 0 {
13084 let mut k = j;
13085 while k < 8 && words[k] == 0 { k += 1; }
13086 let run = k - j;
13087 if run > best_len { best_start = j as isize; best_len = run; }
13088 j = k;
13089 } else {
13090 j += 1;
13091 }
13092 }
13093 let mut i: usize = 0;
13094 let mut prev_in_run = false;
13095 while i < 8 {
13096 let in_run = best_len >= 2 && i >= best_start as usize && i < best_start as usize + best_len;
13097 if in_run {
13098 if i == best_start as usize {
13099 *s.add(pos) = b':' as c_char; pos += 1;
13100 *s.add(pos) = b':' as c_char; pos += 1;
13101 }
13102 i += 1;
13103 prev_in_run = true;
13104 continue;
13105 }
13106 if i > 0 && !prev_in_run {
13107 *s.add(pos) = b':' as c_char; pos += 1;
13108 }
13109 let (buf, len) = format_hex(words[i] as u64, false);
13110 for k in 0..len { *s.add(pos) = buf[k] as c_char; pos += 1; }
13111 i += 1;
13112 prev_in_run = false;
13113 }
13114 *s.add(pos) = 0;
13115 s
13116 } else {
13117 ERRNO = EAFNOSUPPORT;
13118 core::ptr::null_mut()
13119 }
13120}
13121
13122#[no_mangle]
13123pub unsafe extern "C" fn inet_aton(s: *const c_char, dest: *mut c_void) -> c_int {
13124 let a = dest as *mut u8;
13125 let mut p = s as *const u8;
13126 let mut vals = [0u64; 4];
13127 let mut i = 0usize;
13128 while i < 4 {
13129 if *p < b'0' || *p > b'9' { return 0; }
13130 let mut base = 10u32;
13131 if *p == b'0' {
13132 let c = *p.add(1);
13133 if c == b'x' || c == b'X' {
13134 base = 16;
13135 p = p.add(2);
13136 if !((*p >= b'0' && *p <= b'9')
13137 || (*p >= b'a' && *p <= b'f')
13138 || (*p >= b'A' && *p <= b'F')) {
13139 return 0;
13140 }
13141 } else {
13142 base = 8;
13143 }
13144 }
13145 let mut v: u64 = 0;
13146 let start = p;
13147 loop {
13148 let c = *p;
13149 let d = if c >= b'0' && c <= b'9' {
13150 (c - b'0') as u64
13151 } else if base == 16 && c >= b'a' && c <= b'f' {
13152 (c - b'a' + 10) as u64
13153 } else if base == 16 && c >= b'A' && c <= b'F' {
13154 (c - b'A' + 10) as u64
13155 } else {
13156 break;
13157 };
13158 v = v * (base as u64) + d;
13159 p = p.add(1);
13160 }
13161 if p == start { return 0; }
13162 vals[i] = v;
13163 if *p == 0 {
13164 break;
13165 }
13166 if *p != b'.' || i == 3 { return 0; }
13167 p = p.add(1);
13168 i += 1;
13169 }
13170 if i == 4 { return 0; }
13171 if i < 1 { vals[1] = vals[0] & 0xffffff; vals[0] >>= 24; }
13172 if i < 2 { vals[2] = vals[1] & 0xffff; vals[1] >>= 16; }
13173 if i < 3 { vals[3] = vals[2] & 0xff; vals[2] >>= 8; }
13174 for j in 0..4 {
13175 if vals[j] > 255 { return 0; }
13176 *a.add(j) = vals[j] as u8;
13177 }
13178 1
13179}
13180
13181#[no_mangle]
13182pub unsafe extern "C" fn inet_addr(s: *const c_char) -> u32 {
13183 let mut a = [0u8; 4];
13184 if inet_aton(s, a.as_mut_ptr() as *mut c_void) == 1 {
13185 u32::from_ne_bytes(a)
13186 } else {
13187 !0u32 }
13189}
13190
13191#[no_mangle]
13192pub unsafe extern "C" fn inet_ntoa(addr: u32) -> *mut c_char {
13193 static mut NTOA_BUF: [c_char; 16] = [0; 16];
13194 let b = addr.to_ne_bytes();
13195 let mut pos = 0;
13196 for i in 0..4 {
13197 if i > 0 { NTOA_BUF[pos] = b'.' as c_char; pos += 1; }
13198 let (buf, len) = format_u64(b[i] as u64);
13199 for j in 0..len { NTOA_BUF[pos] = buf[j] as c_char; pos += 1; }
13200 }
13201 NTOA_BUF[pos] = 0;
13202 core::ptr::addr_of_mut!(NTOA_BUF).cast::<c_char>()
13203}
13204
13205#[no_mangle]
13207pub unsafe extern "C" fn inet_network(s: *const c_char) -> u32 {
13208 inet_addr(s).to_be()
13209}
13210
13211#[no_mangle]
13212pub extern "C" fn inet_makeaddr(net: c_int, host: c_int) -> u32 {
13213 let addr: u32;
13214 if (net as u32) < 128 {
13215 addr = (net as u32) << 24;
13216 } else if (net as u32) < 0x10000 {
13217 addr = (net as u32) << 16;
13218 } else if (net as u32) < 0x1000000 {
13219 addr = (net as u32) << 8;
13220 } else {
13221 addr = net as u32;
13222 }
13223 addr | (host as u32 & 0xffffffff)
13224}
13225
13226#[no_mangle]
13227pub extern "C" fn inet_lnaof(addr: u32) -> c_int {
13228 let h = u32::from_be(addr);
13229 if h < 0x80000000 { (h & 0x00ffffff) as c_int }
13230 else if h < 0xc0000000 { (h & 0x0000ffff) as c_int }
13231 else { (h & 0x000000ff) as c_int }
13232}
13233
13234#[no_mangle]
13235pub extern "C" fn inet_netof(addr: u32) -> c_int {
13236 let h = u32::from_be(addr);
13237 if h < 0x80000000 { (h >> 24) as c_int }
13238 else if h < 0xc0000000 { (h >> 16) as c_int }
13239 else { (h >> 8) as c_int }
13240}
13241
13242unsafe fn parse_float(s: *const u8, endptr: *mut *mut u8, is_f32: bool) -> f64 {
13251 let mut p = s;
13252 while *p == b' ' || *p == b'\t' || *p == b'\n' || *p == b'\r' { p = p.add(1); }
13254 let mut neg = false;
13255 if *p == b'-' { neg = true; p = p.add(1); }
13256 else if *p == b'+' { p = p.add(1); }
13257
13258 if (*p | 0x20) == b'i'
13260 && (*p.add(1) | 0x20) == b'n'
13261 && (*p.add(2) | 0x20) == b'f'
13262 {
13263 p = p.add(3);
13264 if (*p | 0x20) == b'i'
13266 && (*p.add(1) | 0x20) == b't'
13267 && (*p.add(2) | 0x20) == b'y'
13268 {
13269 p = p.add(3);
13270 }
13271 if !endptr.is_null() { *endptr = p as *mut u8; }
13272 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13273 }
13274 if (*p | 0x20) == b'n'
13276 && (*p.add(1) | 0x20) == b'a'
13277 && (*p.add(2) | 0x20) == b'n'
13278 {
13279 p = p.add(3);
13280 if *p == b'(' {
13282 p = p.add(1);
13283 while *p != 0 && *p != b')' { p = p.add(1); }
13284 if *p == b')' { p = p.add(1); }
13285 }
13286 if !endptr.is_null() { *endptr = p as *mut u8; }
13287 return if neg { -f64::NAN } else { f64::NAN };
13288 }
13289
13290 if *p == b'0' && (*p.add(1) == b'x' || *p.add(1) == b'X') {
13292 p = p.add(2);
13293 let mut mant: u128 = 0;
13294 let mut frac_hex: u32 = 0;
13295 let mut found = false;
13296 let mut in_frac = false;
13297
13298 loop {
13299 if let Some(d) = hex_val(*p) {
13300 if mant <= u128::MAX / 16 {
13301 mant = mant * 16 + d as u128;
13302 }
13303 if in_frac { frac_hex += 1; }
13304 p = p.add(1);
13305 found = true;
13306 } else if *p == b'.' && !in_frac {
13307 in_frac = true;
13308 p = p.add(1);
13309 } else {
13310 break;
13311 }
13312 }
13313
13314 if !found {
13315 if !endptr.is_null() { *endptr = s as *mut u8; }
13316 return 0.0;
13317 }
13318
13319 let mut bin_exp: i32 = 0;
13321 if *p == b'p' || *p == b'P' {
13322 p = p.add(1);
13323 let mut exp_neg = false;
13324 if *p == b'-' { exp_neg = true; p = p.add(1); }
13325 else if *p == b'+' { p = p.add(1); }
13326 while *p >= b'0' && *p <= b'9' {
13327 if bin_exp < 100000 {
13328 bin_exp = bin_exp * 10 + (*p - b'0') as i32;
13329 }
13330 p = p.add(1);
13331 }
13332 if exp_neg { bin_exp = -bin_exp; }
13333 }
13334
13335 if !endptr.is_null() { *endptr = p as *mut u8; }
13336 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13337
13338 let total_exp = bin_exp as i64 - 4 * frac_hex as i64;
13339 return hex_mant_to_f64(mant, total_exp, neg);
13340 }
13341
13342 let mut buf = [0u8; 65536];
13344 let mut n = 0usize;
13345 let mut found_digit = false;
13346
13347 while *p >= b'0' && *p <= b'9' {
13348 if n < 65535 { buf[n] = *p; n += 1; }
13349 p = p.add(1);
13350 found_digit = true;
13351 }
13352 if *p == b'.' {
13353 if n < 65535 { buf[n] = b'.'; n += 1; }
13354 p = p.add(1);
13355 while *p >= b'0' && *p <= b'9' {
13356 if n < 65535 { buf[n] = *p; n += 1; }
13357 p = p.add(1);
13358 found_digit = true;
13359 }
13360 }
13361 if !found_digit {
13362 if !endptr.is_null() { *endptr = s as *mut u8; }
13363 return 0.0;
13364 }
13365 if *p == b'e' || *p == b'E' {
13366 if n < 65535 { buf[n] = b'e'; n += 1; }
13367 p = p.add(1);
13368 if *p == b'-' || *p == b'+' {
13369 if n < 65535 { buf[n] = *p; n += 1; }
13370 p = p.add(1);
13371 }
13372 while *p >= b'0' && *p <= b'9' {
13373 if n < 65535 { buf[n] = *p; n += 1; }
13374 p = p.add(1);
13375 }
13376 }
13377
13378 if !endptr.is_null() { *endptr = p as *mut u8; }
13379 let s_str = core::str::from_utf8_unchecked(
13380 core::slice::from_raw_parts(buf.as_ptr(), n),
13381 );
13382 if is_f32 {
13383 match <f32 as core::str::FromStr>::from_str(s_str) {
13384 Ok(v) => { let r = v as f64; if neg { -r } else { r } }
13385 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13386 }
13387 } else {
13388 match <f64 as core::str::FromStr>::from_str(s_str) {
13389 Ok(v) => if neg { -v } else { v },
13390 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13391 }
13392 }
13393}
13394
13395fn hex_mant_to_f64(mant: u128, total_exp: i64, neg: bool) -> f64 {
13399 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13400
13401 let msb = (127 - mant.leading_zeros()) as i64;
13402 let unbiased_exp = msb + total_exp;
13403 let biased_exp = unbiased_exp + 1023;
13404
13405 if biased_exp >= 2047 {
13407 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13408 }
13409
13410 if biased_exp <= 0 {
13412 let shift = total_exp + 1074;
13415 if shift < 0 {
13416 return if neg { -0.0 } else { 0.0 };
13417 }
13418 if shift > 128 {
13419 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13420 }
13421 let shifted = mant << (shift as u32);
13422 let mantissa52 = (shifted as u64) & 0x000FFFFFFFFFFFFF;
13423 let guard = ((shifted >> 52) & 1) != 0;
13424 let sticky = (shifted >> 53) != 0;
13425 let mut result = mantissa52;
13426 if guard && (sticky || (result & 1) != 0) {
13427 result += 1;
13428 if result > 0x000FFFFFFFFFFFFF {
13429 return if neg { -f64::from_bits(1u64 << 52) } else { f64::from_bits(1u64 << 52) };
13431 }
13432 }
13433 return if neg { -f64::from_bits(result) } else { f64::from_bits(result) };
13434 }
13435
13436 let shift = msb - 52;
13438
13439 if shift <= 0 {
13440 let mantissa = ((mant as u64) & ((1u64 << msb as u32) - 1)) << ((-shift) as u32);
13442 let bits = ((biased_exp as u64) << 52) | mantissa;
13443 return if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) };
13444 }
13445
13446 let mantissa = ((mant >> shift as u32) as u64) & 0x000FFFFFFFFFFFFF;
13448 let guard = ((mant >> (shift as u32 - 1)) & 1) != 0;
13449 let sticky = if shift > 1 {
13450 (mant & ((1u128 << (shift as u32 - 1)) - 1)) != 0
13451 } else { false };
13452
13453 let mut result_mant = mantissa;
13454 let mut result_exp = biased_exp;
13455 if guard && (sticky || (result_mant & 1) != 0) {
13456 result_mant += 1;
13457 if result_mant > 0x000FFFFFFFFFFFFF {
13458 result_mant = 0;
13459 result_exp += 1;
13460 if result_exp >= 2047 {
13461 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13462 }
13463 }
13464 }
13465
13466 let bits = ((result_exp as u64) << 52) | result_mant;
13467 if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) }
13468}
13469
13470unsafe fn hex_val(c: u8) -> Option<u8> {
13471 if c >= b'0' && c <= b'9' { Some(c - b'0') }
13472 else if c >= b'a' && c <= b'f' { Some(c - b'a' + 10) }
13473 else if c >= b'A' && c <= b'F' { Some(c - b'A' + 10) }
13474 else { None }
13475}
13476
13477#[no_mangle]
13478pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13479 let mut end: *mut u8 = s as *mut u8;
13480 let r = parse_float(s as *const u8, &mut end, false);
13481 if !endptr.is_null() { *endptr = end as *mut c_char; }
13482 r
13483}
13484
13485#[no_mangle]
13486pub unsafe extern "C" fn strtof(s: *const c_char, endptr: *mut *mut c_char) -> f32 {
13487 let mut end: *mut u8 = s as *mut u8;
13488 let r = parse_float(s as *const u8, &mut end, true);
13489 if !endptr.is_null() { *endptr = end as *mut c_char; }
13490 r as f32
13491}
13492
13493#[no_mangle]
13494#[cfg(target_arch = "x86_64")]
13495pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13496 strtod(s, endptr)
13497}
13498
13499#[no_mangle]
13500#[cfg(target_arch = "aarch64")]
13501pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13502 strtod(s, endptr) as f128
13503}
13504
13505#[no_mangle]
13506#[cfg(target_arch = "riscv64")]
13507pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13508 strtod(s, endptr) as f128
13509}
13510
13511#[no_mangle]
13512pub unsafe extern "C" fn atof(s: *const c_char) -> f64 {
13513 strtod(s, core::ptr::null_mut())
13514}
13515
13516#[repr(C)]
13521struct MsCookie {
13522 bufp: *mut *mut c_char,
13523 sizep: *mut usize,
13524 pos: usize,
13525 len: usize,
13526 buf: *mut u8,
13527 space: usize,
13528}
13529
13530#[repr(C)]
13531struct MfCookie {
13532 pos: usize,
13533 len: usize,
13534 size: usize,
13535 buf: *mut u8,
13536 mode: c_char,
13537}
13538
13539unsafe extern "C" fn ms_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13540 let c = (*f).cookie as *mut MsCookie;
13541 if whence < 0 || whence > 2 { ERRNO = EINVAL; return -1; }
13542 let base: i64 = match whence {
13543 0 => 0,
13544 1 => (*c).pos as i64,
13545 2 => (*c).len as i64,
13546 _ => { ERRNO = EINVAL; return -1; }
13547 };
13548 if off < -base || off > isize::MAX as i64 - base { ERRNO = EINVAL; return -1; }
13549 (*c).pos = (base + off) as usize;
13550 (*c).pos as i64
13551}
13552
13553unsafe extern "C" fn ms_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13554 let c = (*f).cookie as *mut MsCookie;
13555 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13556 if buffered > 0 {
13557 (*f).wpos = (*f).wbase;
13558 if ms_write(f, (*f).wbase, buffered) < buffered { return 0; }
13559 }
13560 if len == 0 { return 0; }
13561 if (*c).pos + len >= (*c).space {
13562 let new_space = 2 * (*c).space + 1 | (*c).pos + len + 1;
13563 let newbuf = realloc((*c).buf as *mut c_void, new_space) as *mut u8;
13564 if newbuf.is_null() { return 0; }
13565 *(*c).bufp = newbuf as *mut c_char;
13566 core::ptr::write_bytes(newbuf.add((*c).space), 0, new_space - (*c).space);
13567 (*c).buf = newbuf;
13568 (*c).space = new_space;
13569 }
13570 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), len);
13571 (*c).pos += len;
13572 if (*c).pos >= (*c).len { (*c).len = (*c).pos; }
13573 *(*c).sizep = (*c).pos;
13574 len
13575}
13576
13577unsafe extern "C" fn ms_close(_f: *mut FILE) -> c_int {
13578 0
13579}
13580
13581#[no_mangle]
13582pub unsafe extern "C" fn open_memstream(bufp: *mut *mut c_char, sizep: *mut usize) -> *mut FILE {
13583 if bufp.is_null() || sizep.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
13584 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
13585 if f.is_null() { ERRNO = ENOMEM; return core::ptr::null_mut(); }
13586 let buf_area = buf_ptr(f);
13587 init_file(f, -1, b"w\0".as_ptr() as *const c_char, Some(ms_close), buf_area, BUFSIZ);
13588 (*f).flags = F_NORD | F_SVB;
13589 (*f).lbf = -1;
13590 let c = calloc(1, core::mem::size_of::<MsCookie>()) as *mut MsCookie;
13591 if c.is_null() { free(f as *mut c_void); ERRNO = ENOMEM; return core::ptr::null_mut(); }
13592 (*c).bufp = bufp;
13593 (*c).sizep = sizep;
13594 (*c).pos = 0;
13595 (*c).len = 0;
13596 (*c).buf = core::ptr::null_mut();
13597 (*c).space = 0;
13598 (*f).cookie = c as *mut c_void;
13599 (*f).write_fn = Some(ms_write);
13600 (*f).seek_fn = Some(ms_seek);
13601 *bufp = core::ptr::null_mut();
13602 *sizep = 0;
13603 f
13604}
13605
13606unsafe extern "C" fn mseek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13607 let c = (*f).cookie as *mut MfCookie;
13608 if whence < 0 || whence > 2 { ERRNO = EINVAL; return -1; }
13609 let base: i64 = match whence {
13610 0 => 0,
13611 1 => (*c).pos as i64,
13612 2 => (*c).len as i64,
13613 _ => { ERRNO = EINVAL; return -1; }
13614 };
13615 if off < -base || off > (*c).size as i64 - base { ERRNO = EINVAL; return -1; }
13616 (*c).pos = (base + off) as usize;
13617 (*c).pos as i64
13618}
13619
13620unsafe extern "C" fn mread(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
13621 let c = (*f).cookie as *mut MfCookie;
13622 let mut rem = if (*c).pos <= (*c).len { (*c).len - (*c).pos } else { 0 };
13623 let mut l = len;
13624 if l > rem {
13625 l = rem;
13626 (*f).flags |= F_EOF;
13627 }
13628 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), buf, l);
13629 (*c).pos += l;
13630 rem -= l;
13631 if rem > (*f).buf_size { rem = (*f).buf_size; }
13632 (*f).rpos = (*f).buf;
13633 (*f).rend = (*f).buf.add(rem);
13634 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), (*f).rpos, rem);
13635 (*c).pos += rem;
13636 l
13637}
13638
13639unsafe extern "C" fn mwrite(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13640 let c = (*f).cookie as *mut MfCookie;
13641 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13642 if buffered > 0 {
13643 (*f).wpos = (*f).wbase;
13644 if mwrite(f, (*f).wbase, buffered) < buffered { return 0; }
13645 }
13646 if len == 0 { return 0; }
13647 if (*c).mode == b'a' as c_char { (*c).pos = (*c).len; }
13648 let rem = (*c).size - (*c).pos;
13649 let mut l = len;
13650 if l > rem { l = rem; }
13651 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), l);
13652 (*c).pos += l;
13653 if (*c).pos > (*c).len {
13654 (*c).len = (*c).pos;
13655 if (*c).len < (*c).size {
13656 *(*c).buf.add((*c).len) = 0;
13657 } else if ((*f).flags & F_NORD) != 0 && (*c).size > 0 {
13658 *(*c).buf.add((*c).size - 1) = 0;
13659 }
13660 }
13661 l
13662}
13663
13664unsafe extern "C" fn mclose(_f: *mut FILE) -> c_int {
13665 0
13666}
13667
13668#[no_mangle]
13669pub unsafe extern "C" fn fmemopen(buf: *mut c_void, size: usize, mode: *const c_char) -> *mut FILE {
13670 if mode.is_null() { ERRNO = EINVAL; return core::ptr::null_mut(); }
13671 let m = *mode;
13672 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
13673 ERRNO = EINVAL; return core::ptr::null_mut();
13674 }
13675 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
13676 let need_alloc = buf.is_null();
13677 let alloc_size = core::mem::size_of::<FILE>() + UNGET + BUFSIZ + if need_alloc { size } else { 0 };
13678 let f = calloc(1, alloc_size) as *mut FILE;
13679 if f.is_null() { ERRNO = ENOMEM; return core::ptr::null_mut(); }
13680 let buf_area = buf_ptr(f);
13681 init_file(f, -1, mode, Some(mclose), buf_area, BUFSIZ);
13682 (*f).flags |= F_SVB;
13683 let actual_buf: *mut u8 = if need_alloc {
13684 (f as *mut u8).add(alloc_size - size)
13685 } else {
13686 buf as *mut u8
13687 };
13688 if need_alloc { core::ptr::write_bytes(actual_buf, 0, size); }
13689 let c = calloc(1, core::mem::size_of::<MfCookie>()) as *mut MfCookie;
13690 if c.is_null() { free(f as *mut c_void); ERRNO = ENOMEM; return core::ptr::null_mut(); }
13691 (*c).buf = actual_buf;
13692 (*c).size = size;
13693 (*c).mode = m;
13694 (*f).cookie = c as *mut c_void;
13695 (*f).read_fn = Some(mread);
13696 (*f).write_fn = Some(mwrite);
13697 (*f).seek_fn = Some(mseek);
13698 if !has_plus { (*f).flags = if m == b'r' as c_char { F_NOWR } else { F_NORD }; }
13699 if m == b'r' as c_char {
13700 (*c).len = size;
13701 } else if m == b'a' as c_char {
13702 (*c).len = strnlen(actual_buf, size);
13703 (*c).pos = (*c).len;
13704 } else if has_plus {
13705 *actual_buf = 0;
13706 }
13707 f
13708}
13709
13710#[repr(C)]
13715struct kernel_stat64 {
13716 st_dev: u64,
13717 st_ino: u64,
13718 st_nlink: u64,
13719 st_mode: u32,
13720 st_uid: u32,
13721 st_gid: u32,
13722 __pad0: c_int,
13723 st_rdev: u64,
13724 st_size: i64,
13725 st_blksize: i64,
13726 st_blocks: i64,
13727 st_atime: i64,
13728 st_atime_nsec: i64,
13729 st_mtime: i64,
13730 st_mtime_nsec: i64,
13731 st_ctime: i64,
13732 st_ctime_nsec: i64,
13733 __unused: [i64; 3],
13734}
13735
13736#[inline]
13738unsafe fn sys_stat(path: *const u8, statbuf: *mut kernel_stat64) -> i64 {
13739 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, statbuf as i64, 0)
13740}
13741
13742const HSEARCH_MINSIZE: usize = 8;
13747
13748#[repr(C)]
13749#[derive(Copy, Clone)]
13750pub struct HSearchEntry {
13751 key: *mut c_char,
13752 data: *mut c_void,
13753}
13754
13755#[repr(C)]
13756struct HTab {
13757 entries: *mut HSearchEntry,
13758 mask: usize,
13759 used: usize,
13760}
13761
13762#[repr(C)]
13763pub struct HSearchData {
13764 tab: *mut HTab,
13765 __unused1: c_uint,
13766 __unused2: c_uint,
13767}
13768
13769static mut HTAB_DATA: HSearchData = HSearchData {
13771 tab: core::ptr::null_mut(),
13772 __unused1: 0,
13773 __unused2: 0,
13774};
13775
13776unsafe fn keyhash(k: *const c_char) -> usize {
13777 let mut h: usize = 0;
13778 let mut p = k;
13779 while *p != 0 {
13780 h = h.wrapping_mul(31).wrapping_add(*p as usize);
13781 p = p.add(1);
13782 }
13783 h
13784}
13785
13786unsafe fn htab_lookup(key: *const c_char, hash: usize, htab: *mut HSearchData) -> *mut HSearchEntry {
13787 let tab = (*htab).tab;
13788 let mask = (*tab).mask;
13789 let entries = (*tab).entries;
13790 let mut i = hash;
13791 let mut j: usize = 1;
13792 loop {
13793 let e = entries.add(i & mask);
13794 if (*e).key.is_null() || strcmp((*e).key as *const u8, key as *const u8) == 0 {
13795 return e;
13796 }
13797 i = i.wrapping_add(j);
13798 j += 1;
13799 }
13800}
13801
13802unsafe fn htab_resize(nel: usize, htab: *mut HSearchData) -> c_int {
13803 let tab = (*htab).tab;
13804 let old_entries = (*tab).entries;
13805 let old_size = (*tab).mask + 1;
13806
13807 let mut newsize: usize = HSEARCH_MINSIZE;
13808 while newsize < nel {
13809 let Some(next) = newsize.checked_mul(2) else {
13810 ERRNO = ENOMEM;
13811 return 0;
13812 };
13813 newsize = next;
13814 }
13815
13816 let new_entries = calloc(newsize, core::mem::size_of::<HSearchEntry>()) as *mut HSearchEntry;
13817 if new_entries.is_null() {
13818 ERRNO = ENOMEM;
13819 return 0;
13820 }
13821 (*tab).entries = new_entries;
13822 (*tab).mask = newsize - 1;
13823
13824 if !old_entries.is_null() {
13825 for idx in 0..old_size {
13826 let old_e = old_entries.add(idx);
13827 if !(*old_e).key.is_null() {
13828 let h = keyhash((*old_e).key);
13829 let mut i = h;
13830 let mut j: usize = 1;
13831 loop {
13832 let e = new_entries.add(i & (*tab).mask);
13833 if (*e).key.is_null() {
13834 *e = *old_e;
13835 break;
13836 }
13837 i = i.wrapping_add(j);
13838 j += 1;
13839 }
13840 }
13841 }
13842 free(old_entries as *mut c_void);
13843 }
13844 1
13845}
13846
13847unsafe fn hcreate_r_impl(nel: usize, htab: *mut HSearchData) -> c_int {
13848 if nel == 0 || nel > (1usize << 30) {
13849 ERRNO = ENOMEM;
13850 return 0;
13851 }
13852 (*htab).tab = calloc(1, core::mem::size_of::<HTab>()) as *mut HTab;
13853 if (*htab).tab.is_null() {
13854 ERRNO = ENOMEM;
13855 return 0;
13856 }
13857 if htab_resize(nel, htab) == 0 {
13858 free((*htab).tab as *mut c_void);
13859 (*htab).tab = core::ptr::null_mut();
13860 return 0;
13861 }
13862 1
13863}
13864
13865unsafe fn hdestroy_r_impl(htab: *mut HSearchData) {
13866 if !(*htab).tab.is_null() {
13867 if !(*(*htab).tab).entries.is_null() {
13868 free((*(*htab).tab).entries as *mut c_void);
13869 }
13870 free((*htab).tab as *mut c_void);
13871 (*htab).tab = core::ptr::null_mut();
13872 }
13873}
13874
13875unsafe fn hsearch_r_impl(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
13876 let hash = keyhash(item.key);
13877 let e = htab_lookup(item.key, hash, htab);
13878
13879 if !(*e).key.is_null() {
13880 *retval = e;
13881 return 1;
13882 }
13883 if action == 0 { *retval = core::ptr::null_mut();
13885 return 0;
13886 }
13887 let item_key = item.key;
13889 *e = item;
13890 (*(*htab).tab).used += 1;
13891 if (*(*htab).tab).used > (*(*htab).tab).mask - (*(*htab).tab).mask / 4 {
13892 if htab_resize(2 * (*(*htab).tab).used, htab) == 0 {
13893 (*(*htab).tab).used -= 1;
13894 (*e).key = core::ptr::null_mut();
13895 *retval = core::ptr::null_mut();
13896 return 0;
13897 }
13898 let e2 = htab_lookup(item_key, hash, htab);
13899 *retval = e2;
13900 return 1;
13901 }
13902 *retval = e;
13903 1
13904}
13905
13906#[no_mangle]
13907pub unsafe extern "C" fn hcreate(nel: usize) -> c_int {
13908 hcreate_r_impl(nel, core::ptr::addr_of_mut!(HTAB_DATA))
13909}
13910
13911#[no_mangle]
13912pub unsafe extern "C" fn hdestroy() {
13913 hdestroy_r_impl(core::ptr::addr_of_mut!(HTAB_DATA));
13914}
13915
13916#[no_mangle]
13917pub unsafe extern "C" fn hsearch(item: HSearchEntry, action: c_int) -> *mut HSearchEntry {
13918 let mut e: *mut HSearchEntry = core::ptr::null_mut();
13919 hsearch_r_impl(item, action, &mut e, core::ptr::addr_of_mut!(HTAB_DATA));
13920 e
13921}
13922
13923#[no_mangle]
13924pub unsafe extern "C" fn hcreate_r(nel: usize, htab: *mut HSearchData) -> c_int {
13925 hcreate_r_impl(nel, htab)
13926}
13927
13928#[no_mangle]
13929pub unsafe extern "C" fn hdestroy_r(htab: *mut HSearchData) {
13930 hdestroy_r_impl(htab);
13931}
13932
13933#[no_mangle]
13934pub unsafe extern "C" fn hsearch_r(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
13935 hsearch_r_impl(item, action, retval, htab)
13936}
13937
13938#[repr(C)]
13943struct QueNode {
13944 next: *mut QueNode,
13945 prev: *mut QueNode,
13946}
13947
13948#[no_mangle]
13949pub unsafe extern "C" fn insque(element: *mut c_void, pred: *mut c_void) {
13950 let e = element as *mut QueNode;
13951 let p = pred as *mut QueNode;
13952 if p.is_null() {
13953 (*e).next = core::ptr::null_mut();
13954 (*e).prev = core::ptr::null_mut();
13955 return;
13956 }
13957 (*e).next = (*p).next;
13958 (*e).prev = p;
13959 (*p).next = e;
13960 if !(*e).next.is_null() {
13961 (*(*e).next).prev = e;
13962 }
13963}
13964
13965#[no_mangle]
13966pub unsafe extern "C" fn remque(element: *mut c_void) {
13967 let e = element as *mut QueNode;
13968 if !(*e).next.is_null() {
13969 (*(*e).next).prev = (*e).prev;
13970 }
13971 if !(*e).prev.is_null() {
13972 (*(*e).prev).next = (*e).next;
13973 }
13974}
13975
13976#[no_mangle]
13981pub unsafe extern "C" fn lsearch(
13982 key: *const c_void,
13983 base: *mut c_void,
13984 nelp: *mut usize,
13985 width: usize,
13986 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
13987) -> *mut c_void {
13988 let n = *nelp;
13989 let p = base as *mut u8;
13990 for i in 0..n {
13991 let elem = p.add(i * width);
13992 if compar.unwrap()(key, elem as *const c_void) == 0 {
13993 return elem as *mut c_void;
13994 }
13995 }
13996 let dest = p.add(n * width);
13997 memcpy(dest as *mut c_void, key as *const c_void, width);
13998 *nelp = n + 1;
13999 dest as *mut c_void
14000}
14001
14002#[no_mangle]
14003pub unsafe extern "C" fn lfind(
14004 key: *const c_void,
14005 base: *const c_void,
14006 nelp: *mut usize,
14007 width: usize,
14008 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
14009) -> *mut c_void {
14010 let n = *nelp;
14011 let p = base as *const u8;
14012 for i in 0..n {
14013 let elem = p.add(i * width);
14014 if compar.unwrap()(key, elem as *const c_void) == 0 {
14015 return elem as *mut c_void;
14016 }
14017 }
14018 core::ptr::null_mut()
14019}
14020
14021#[repr(C)]
14027pub struct TreeNode {
14028 key: *const c_void,
14029 left: *mut TreeNode,
14030 right: *mut TreeNode,
14031}
14032
14033type ComparFn = Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>;
14034
14035unsafe fn bst_new(key: *const c_void) -> *mut TreeNode {
14036 let n = calloc(1, core::mem::size_of::<TreeNode>()) as *mut TreeNode;
14037 if !n.is_null() {
14038 (*n).key = key;
14039 (*n).left = core::ptr::null_mut();
14040 (*n).right = core::ptr::null_mut();
14041 }
14042 n
14043}
14044
14045#[no_mangle]
14046pub unsafe extern "C" fn tsearch(
14047 key: *const c_void,
14048 rootp: *mut *mut TreeNode,
14049 compar: ComparFn,
14050) -> *mut c_void {
14051 if rootp.is_null() {
14052 return core::ptr::null_mut();
14053 }
14054 let mut pp = rootp;
14055 loop {
14056 let n = *pp;
14057 if n.is_null() {
14058 let r = bst_new(key);
14059 if r.is_null() {
14060 return core::ptr::null_mut();
14061 }
14062 *pp = r;
14063 return r as *mut c_void;
14064 }
14065 let c = compar.unwrap()(key, (*n).key);
14066 if c == 0 {
14067 return n as *mut c_void;
14068 }
14069 if c < 0 {
14070 pp = &mut (*n).left;
14071 } else {
14072 pp = &mut (*n).right;
14073 }
14074 }
14075}
14076
14077#[no_mangle]
14078pub unsafe extern "C" fn tfind(
14079 key: *const c_void,
14080 rootp: *const *mut TreeNode,
14081 compar: ComparFn,
14082) -> *mut c_void {
14083 if rootp.is_null() {
14084 return core::ptr::null_mut();
14085 }
14086 let mut n = *rootp;
14087 loop {
14088 if n.is_null() {
14089 return core::ptr::null_mut();
14090 }
14091 let c = compar.unwrap()(key, (*n).key);
14092 if c == 0 {
14093 return n as *mut c_void;
14094 }
14095 if c < 0 {
14096 n = (*n).left;
14097 } else {
14098 n = (*n).right;
14099 }
14100 }
14101}
14102
14103#[no_mangle]
14104pub unsafe extern "C" fn tdelete(
14105 key: *const c_void,
14106 rootp: *mut *mut TreeNode,
14107 compar: ComparFn,
14108) -> *mut c_void {
14109 if rootp.is_null() {
14110 return core::ptr::null_mut();
14111 }
14112 let mut pp = rootp;
14113 loop {
14114 let n = *pp;
14115 if n.is_null() {
14116 return core::ptr::null_mut();
14117 }
14118 let c = compar.unwrap()(key, (*n).key);
14119 if c == 0 {
14120 break;
14121 }
14122 if c < 0 {
14123 pp = &mut (*n).left;
14124 } else {
14125 pp = &mut (*n).right;
14126 }
14127 }
14128 let n = *pp;
14129 let parent = *rootp;
14131 if !(*n).left.is_null() {
14132 let mut q = &mut (*n).left;
14134 while !(*(*q)).right.is_null() {
14135 q = &mut (*(*q)).right;
14136 }
14137 let pred = *q;
14138 (*n).key = (*pred).key;
14140 *q = (*pred).left;
14142 free(pred as *mut c_void);
14143 } else {
14144 *pp = (*n).right;
14146 free(n as *mut c_void);
14147 }
14148 parent as *mut c_void
14149}
14150
14151#[no_mangle]
14152pub unsafe extern "C" fn twalk(
14153 root: *const TreeNode,
14154 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
14155) {
14156 unsafe fn walk(
14157 node: *const TreeNode,
14158 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
14159 depth: c_int,
14160 ) {
14161 if node.is_null() {
14162 return;
14163 }
14164 let is_leaf = (*node).left.is_null() && (*node).right.is_null();
14165 if is_leaf {
14166 action.unwrap()(node as *const c_void, 3, depth); } else {
14168 action.unwrap()(node as *const c_void, 0, depth); walk((*node).left, action, depth + 1);
14170 action.unwrap()(node as *const c_void, 1, depth); walk((*node).right, action, depth + 1);
14172 action.unwrap()(node as *const c_void, 2, depth); }
14174 }
14175 walk(root, action, 0);
14176}
14177
14178#[no_mangle]
14179pub unsafe extern "C" fn tdestroy(root: *mut TreeNode, freekey: Option<unsafe extern "C" fn(*mut c_void)>) {
14180 if root.is_null() {
14181 return;
14182 }
14183 tdestroy((*root).left, freekey);
14184 tdestroy((*root).right, freekey);
14185 if let Some(f) = freekey {
14186 f((*root).key as *mut c_void);
14187 }
14188 free(root as *mut c_void);
14189}
14190
14191const FNM_PATHNAME: c_int = 0x1;
14196const FNM_NOESCAPE: c_int = 0x2;
14197const FNM_PERIOD: c_int = 0x4;
14198const FNM_LEADING_DIR: c_int = 0x8;
14199const FNM_CASEFOLD: c_int = 0x10;
14200const FNM_NOMATCH: c_int = 1;
14201
14202const FNM_END: c_int = 0;
14203const FNM_STAR: c_int = -5;
14204const FNM_QUESTION: c_int = -4;
14205const FNM_BRACKET: c_int = -3;
14206const FNM_UNMATCHABLE: c_int = -2;
14207
14208fn ascii_tolower(c: u8) -> u8 {
14209 if c >= b'A' && c <= b'Z' { c + 32 } else { c }
14210}
14211
14212fn ascii_toupper(c: u8) -> u8 {
14213 if c >= b'a' && c <= b'z' { c - 32 } else { c }
14214}
14215
14216fn ascii_casefold(k: u8) -> u8 {
14217 let upper = ascii_toupper(k);
14218 if upper != k { upper } else { ascii_tolower(k) }
14219}
14220
14221unsafe fn pat_next(pat: *const u8, m: usize, flags: c_int) -> (c_int, usize) {
14224 if m == 0 || *pat == 0 {
14225 return (FNM_END, 0);
14226 }
14227 let mut p = pat;
14228 let mut step = 1usize;
14229 let mut esc = false;
14230 if *p == b'\\' && !(flags & FNM_NOESCAPE != 0) && *p.add(1) != 0 {
14231 p = p.add(1);
14232 step = 2;
14233 esc = true;
14234 }
14235 if *p == b'[' && !esc {
14236 let mut k = 1usize;
14238 if k < m && (*pat.add(k) == b'^' || *pat.add(k) == b'!') { k += 1; }
14239 if k < m && *pat.add(k) == b']' { k += 1; }
14240 while k < m && *pat.add(k) != 0 && *pat.add(k) != b']' {
14241 if k + 1 < m && *pat.add(k) == b'[' &&
14242 (*pat.add(k+1) == b':' || *pat.add(k+1) == b'.' || *pat.add(k+1) == b'=') {
14243 let z = *pat.add(k+1);
14244 k += 2;
14245 if k < m { k += 1; }
14246 while k < m && *pat.add(k) != 0 && (*pat.add(k-1) != z || *pat.add(k) != b']') { k += 1; }
14247 if k == m || *pat.add(k) == 0 { break; }
14248 }
14249 k += 1;
14250 }
14251 if k == m || *pat.add(k) == 0 {
14252 return (b'[' as c_int, 1);
14254 }
14255 return (FNM_BRACKET, k + 1);
14256 }
14257 if *p == b'*' && !esc {
14258 return (FNM_STAR, 1);
14259 }
14260 if *p == b'?' && !esc {
14261 return (FNM_QUESTION, 1);
14262 }
14263 (*p as c_int, step)
14264}
14265
14266unsafe fn match_class(name: &[u8], k: u8, kfold: u8) -> bool {
14267 let eq = |c: u8| k == c || kfold == c;
14268 let in_range = |lo: u8, hi: u8| (k >= lo && k <= hi) || (kfold >= lo && kfold <= hi);
14269 match name {
14270 b"alnum" => in_range(b'0', b'9') || in_range(b'A', b'Z') || in_range(b'a', b'z'),
14271 b"alpha" => in_range(b'A', b'Z') || in_range(b'a', b'z'),
14272 b"blank" => eq(b' ') || eq(b'\t'),
14273 b"cntrl" => k < 0x20 || k == 0x7f,
14274 b"digit" => in_range(b'0', b'9'),
14275 b"graph" => k >= 0x21 && k <= 0x7e,
14276 b"lower" => in_range(b'a', b'z'),
14277 b"print" => k >= 0x20 && k <= 0x7e,
14278 b"punct" =>
14279 (k >= 0x21 && k <= 0x2f) ||
14280 (k >= 0x3a && k <= 0x40) ||
14281 (k >= 0x5b && k <= 0x60) ||
14282 (k >= 0x7b && k <= 0x7e),
14283 b"space" => eq(b' ') || eq(b'\t') || eq(b'\n') || eq(b'\r') || eq(0x0c) || eq(0x0b),
14284 b"upper" => in_range(b'A', b'Z'),
14285 b"xdigit" => in_range(b'0', b'9') || in_range(b'A', b'F') || in_range(b'a', b'f'),
14286 _ => false,
14287 }
14288}
14289
14290unsafe fn match_bracket(mut p: *const u8, k: u8, kfold: u8) -> bool {
14292 let mut inv = false;
14293 p = p.add(1); if *p == b'^' || *p == b'!' {
14295 inv = true;
14296 p = p.add(1);
14297 }
14298 if *p == b']' {
14300 if k == b']' { return !inv; }
14301 p = p.add(1);
14302 } else if *p == b'-' {
14303 if k == b'-' { return !inv; }
14304 p = p.add(1);
14305 }
14306 while *p != b']' && *p != 0 {
14307 if *p == b'-' && *p.add(1) != b']' && *p.add(1) != 0 {
14308 let lo = *p.sub(1);
14310 let hi = *p.add(1);
14311 if lo <= hi && (k >= lo && k <= hi || kfold >= lo && kfold <= hi) {
14312 return !inv;
14313 }
14314 p = p.add(2);
14315 } else if *p == b'[' && (*p.add(1) == b':' || *p.add(1) == b'.' || *p.add(1) == b'=') {
14316 let z = *p.add(1);
14317 let start = p.add(2);
14318 let mut q = start;
14319 while *q != 0 && (*q != z || *q.add(1) != b']') { q = q.add(1); }
14320 if *q != 0 {
14321 let len = (q as usize) - (start as usize);
14322 if len > 0 {
14323 let inner = core::slice::from_raw_parts(start, len);
14324 let matched =
14325 if z == b':' { match_class(inner, k, kfold) }
14326 else { len == 1 && (inner[0] == k || inner[0] == kfold) };
14327 if matched { return !inv; }
14328 }
14329 p = q.add(2);
14330 continue;
14331 }
14332 } else {
14333 if *p == k || *p == kfold {
14334 return !inv;
14335 }
14336 p = p.add(1);
14337 }
14338 }
14339 inv
14340}
14341
14342unsafe fn fnmatch_internal(pat: *const u8, str: *const u8, flags: c_int) -> c_int {
14344 if flags & FNM_PERIOD != 0 && *str == b'.' && *pat != b'.' {
14346 return FNM_NOMATCH;
14347 }
14348
14349 let mut p = pat;
14350 let mut s = str;
14351
14352 loop {
14354 let (tok, step) = pat_next(p, usize::MAX, flags);
14355 match tok {
14356 FNM_END => {
14357 return if *s == 0 { 0 } else { FNM_NOMATCH };
14358 }
14359 FNM_STAR => {
14360 p = p.add(1);
14361 break;
14362 }
14363 FNM_QUESTION => {
14364 if *s == 0 { return FNM_NOMATCH; }
14365 s = s.add(1);
14366 p = p.add(step);
14367 }
14368 FNM_BRACKET => {
14369 if *s == 0 { return FNM_NOMATCH; }
14370 let k = *s;
14371 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14372 if !match_bracket(p, k, kfold) { return FNM_NOMATCH; }
14373 p = p.add(step);
14374 s = s.add(1);
14375 }
14376 c => {
14377 if *s == 0 { return FNM_NOMATCH; }
14378 let k = *s;
14379 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14380 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14381 p = p.add(step);
14382 s = s.add(1);
14383 }
14384 }
14385 }
14386
14387 let mut ptail = p;
14390 let mut tailcnt: usize = 0;
14391 let mut pp = p;
14392 loop {
14393 let (tok, step) = pat_next(pp, usize::MAX, flags);
14394 if tok == FNM_END { break; }
14395 if tok == FNM_STAR {
14396 tailcnt = 0;
14397 ptail = pp.add(1);
14398 } else {
14399 tailcnt += 1;
14400 }
14401 pp = pp.add(step);
14402 }
14403
14404 let slen = strlen(s as *const c_char);
14406 if slen < tailcnt { return FNM_NOMATCH; }
14407
14408 let stail = s.add(slen - tailcnt);
14410 let mut tp = ptail;
14411 let mut ts = stail;
14412 loop {
14413 let (tok, step) = pat_next(tp, usize::MAX, flags);
14414 tp = tp.add(step);
14415 if tok == FNM_END {
14416 break;
14417 }
14418 let k = *ts;
14419 if k == 0 { return FNM_NOMATCH; }
14420 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14421 match tok {
14422 FNM_QUESTION => { ts = ts.add(1); }
14423 FNM_BRACKET => {
14424 if !match_bracket(tp.sub(step), k, kfold) { return FNM_NOMATCH; }
14425 ts = ts.add(1);
14426 }
14427 c => {
14428 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14429 ts = ts.add(1);
14430 }
14431 }
14432 }
14433
14434 let endstr = stail;
14435 let endpat = ptail;
14436
14437 let mut cp = p;
14438 let mut cs = s;
14439 while cp < endpat {
14440 let (tok, step) = pat_next(cp, usize::MAX, flags);
14441 if tok == FNM_STAR {
14442 cp = cp.add(step);
14443 cs = s;
14444 continue;
14445 }
14446 let comp_start = cp;
14447 let mut ok = false;
14448 let mut try_s = cs;
14449 while try_s < endstr {
14450 let mut tmp_p = comp_start;
14451 let mut tmp_s = try_s;
14452 let mut matched = true;
14453 loop {
14454 let (t, st) = pat_next(tmp_p, usize::MAX, flags);
14455 if t == FNM_STAR || t == FNM_END {
14456 cp = tmp_p;
14457 cs = tmp_s;
14458 ok = true;
14459 break;
14460 }
14461 if *tmp_s == 0 {
14462 matched = false;
14463 break;
14464 }
14465 let k = *tmp_s;
14466 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14467 match t {
14468 FNM_QUESTION => {
14469 tmp_s = tmp_s.add(1);
14470 }
14471 FNM_BRACKET => {
14472 if !match_bracket(tmp_p, k, kfold) {
14473 matched = false;
14474 break;
14475 }
14476 tmp_s = tmp_s.add(1);
14477 }
14478 c => {
14479 if k as c_int != c && kfold as c_int != c {
14480 matched = false;
14481 break;
14482 }
14483 tmp_s = tmp_s.add(1);
14484 }
14485 }
14486 tmp_p = tmp_p.add(st);
14487 }
14488 if ok { break; }
14489 if !matched {
14490 try_s = try_s.add(1);
14491 }
14492 }
14493 if !ok {
14494 return FNM_NOMATCH;
14495 }
14496 }
14497 0
14498}
14499
14500#[no_mangle]
14501pub unsafe extern "C" fn fnmatch(pat: *const c_char, str: *const c_char, flags: c_int) -> c_int {
14502 let pat = pat as *const u8;
14503 let str = str as *const u8;
14504
14505 if flags & FNM_PATHNAME != 0 {
14506 let mut s = str;
14508 let mut p = pat;
14509 loop {
14510 let mut send = s;
14512 while *send != 0 && *send != b'/' { send = send.add(1); }
14513 let mut pend = p;
14515 loop {
14516 let (tok, step) = pat_next(pend, usize::MAX, flags);
14517 if tok == FNM_END || (tok >= 0 && tok as u8 == b'/') {
14518 break;
14519 }
14520 pend = pend.add(step);
14521 }
14522 let (ptok, pstep) = pat_next(pend, usize::MAX, flags);
14523 let pat_is_slash = ptok >= 0 && ptok as u8 == b'/';
14524 let str_is_slash = *send == b'/';
14525 if pat_is_slash != str_is_slash && (*send != 0 || !(flags & FNM_LEADING_DIR != 0)) {
14526 return FNM_NOMATCH;
14527 }
14528 let plen = (pend as usize) - (p as usize);
14531 let slen = (send as usize) - (s as usize);
14532 if plen > 1024 || slen > 1024 { return FNM_NOMATCH; }
14535 let mut pbuf = [0u8; 1025];
14536 let mut sbuf = [0u8; 1025];
14537 core::ptr::copy_nonoverlapping(p, pbuf.as_mut_ptr(), plen);
14538 pbuf[plen] = 0;
14539 core::ptr::copy_nonoverlapping(s, sbuf.as_mut_ptr(), slen);
14540 sbuf[slen] = 0;
14541 if fnmatch_internal(pbuf.as_ptr(), sbuf.as_ptr(), flags & !FNM_LEADING_DIR) != 0 {
14542 return FNM_NOMATCH;
14543 }
14544 if !pat_is_slash {
14545 return 0;
14546 }
14547 s = send.add(1);
14548 p = pend.add(pstep);
14549 }
14550 }
14551
14552 if flags & FNM_LEADING_DIR != 0 {
14553 let mut s = str;
14555 while *s != 0 {
14556 if *s == b'/' {
14557 let len = (s as usize) - (str as usize);
14560 if len < 4096 {
14562 let mut buf = [0u8; 4096];
14563 core::ptr::copy_nonoverlapping(str, buf.as_mut_ptr(), len);
14564 buf[len] = 0;
14565 if fnmatch_internal(pat, buf.as_ptr(), flags) == 0 {
14566 return 0;
14567 }
14568 }
14569 }
14570 s = s.add(1);
14571 }
14572 }
14573
14574 fnmatch_internal(pat, str, flags)
14575}
14576
14577#[no_mangle]
14582pub unsafe extern "C" fn setmntent(name: *const c_char, mode: *const c_char) -> *mut FILE {
14583 fopen(name, mode)
14584}
14585
14586#[no_mangle]
14587pub unsafe extern "C" fn endmntent(f: *mut FILE) -> c_int {
14588 if !f.is_null() {
14589 fclose(f);
14590 }
14591 1
14592}
14593
14594static mut MNTENT_MNT: MntEnt = MntEnt {
14596 mnt_fsname: core::ptr::null_mut(),
14597 mnt_dir: core::ptr::null_mut(),
14598 mnt_type: core::ptr::null_mut(),
14599 mnt_opts: core::ptr::null_mut(),
14600 mnt_freq: 0,
14601 mnt_passno: 0,
14602};
14603
14604#[repr(C)]
14605pub struct MntEnt {
14606 mnt_fsname: *mut c_char,
14607 mnt_dir: *mut c_char,
14608 mnt_type: *mut c_char,
14609 mnt_opts: *mut c_char,
14610 mnt_freq: c_int,
14611 mnt_passno: c_int,
14612}
14613
14614unsafe fn unescape_ent(beg: *mut c_char) -> *mut c_char {
14615 let mut dest = beg;
14616 let mut src = beg;
14617 while *src != 0 {
14618 if *src != b'\\' as c_char {
14619 *dest = *src;
14620 dest = dest.add(1);
14621 src = src.add(1);
14622 continue;
14623 }
14624 if *src.add(1) == b'\\' as c_char {
14626 src = src.add(1);
14627 *dest = *src;
14628 dest = dest.add(1);
14629 src = src.add(1);
14630 continue;
14631 }
14632 let mut val: u8 = 0;
14634 let mut cnt = 0;
14635 let mut sp = src.add(1);
14636 while cnt < 3 && *sp >= b'0' as c_char && *sp <= b'7' as c_char {
14637 val = val * 8 + (*sp as u8 - b'0');
14638 sp = sp.add(1);
14639 cnt += 1;
14640 }
14641 if cnt > 0 {
14642 *dest = val as c_char;
14643 dest = dest.add(1);
14644 src = sp;
14645 } else {
14646 *dest = *src;
14647 dest = dest.add(1);
14648 src = src.add(1);
14649 }
14650 }
14651 *dest = 0;
14652 beg
14653}
14654
14655unsafe fn parse_mntent_line(
14656 linebuf: *mut c_char,
14657 mnt: *mut MntEnt,
14658) -> *mut MntEnt {
14659 let _len = strlen(linebuf as *const c_char);
14660 let mut p = linebuf;
14663 while *p == b' ' as c_char || *p == b'\t' as c_char || *p == b'\n' as c_char || *p == b'\r' as c_char {
14665 p = p.add(1);
14666 }
14667 if *p == 0 || *p == b'#' as c_char {
14668 return core::ptr::null_mut();
14669 }
14670
14671 (*mnt).mnt_fsname = p;
14673 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14674 p = p.add(1);
14675 }
14676 if *p == 0 { return core::ptr::null_mut(); }
14677 *p = 0;
14678 p = p.add(1);
14679 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14680
14681 (*mnt).mnt_dir = p;
14683 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14684 p = p.add(1);
14685 }
14686 if *p == 0 { return core::ptr::null_mut(); }
14687 *p = 0;
14688 p = p.add(1);
14689 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14690
14691 (*mnt).mnt_type = p;
14693 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14694 p = p.add(1);
14695 }
14696 if *p == 0 { return core::ptr::null_mut(); }
14697 *p = 0;
14698 p = p.add(1);
14699 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14700
14701 (*mnt).mnt_opts = p;
14703 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14704 p = p.add(1);
14705 }
14706 if *p != 0 {
14707 *p = 0;
14708 p = p.add(1);
14709 }
14710 if *(*mnt).mnt_opts == 0 {
14711 (*mnt).mnt_opts = b"defaults\0".as_ptr() as *mut c_char;
14712 }
14713
14714 (*mnt).mnt_freq = 0;
14716 (*mnt).mnt_passno = 0;
14717 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14719 if *p >= b'0' as c_char && *p <= b'9' as c_char {
14720 (*mnt).mnt_freq = (*p - b'0' as c_char) as c_int;
14721 p = p.add(1);
14722 while *p >= b'0' as c_char && *p <= b'9' as c_char {
14723 (*mnt).mnt_freq = (*mnt).mnt_freq * 10 + (*p - b'0' as c_char) as c_int;
14724 p = p.add(1);
14725 }
14726 }
14727 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14728 if *p >= b'0' as c_char && *p <= b'9' as c_char {
14729 (*mnt).mnt_passno = (*p - b'0' as c_char) as c_int;
14730 p = p.add(1);
14731 while *p >= b'0' as c_char && *p <= b'9' as c_char {
14732 (*mnt).mnt_passno = (*mnt).mnt_passno * 10 + (*p - b'0' as c_char) as c_int;
14733 p = p.add(1);
14734 }
14735 }
14736
14737 unescape_ent((*mnt).mnt_fsname);
14739 unescape_ent((*mnt).mnt_dir);
14740 unescape_ent((*mnt).mnt_type);
14741 unescape_ent((*mnt).mnt_opts);
14742
14743 mnt
14744}
14745
14746static SENTINEL_PTR: usize = 1;
14749
14750unsafe fn mntent_fgetc(f: *mut FILE) -> c_int {
14752 fgetc(f)
14753}
14754
14755unsafe fn mntent_fgets(buf: *mut c_char, n: usize, f: *mut FILE) -> *mut c_char {
14756 if n == 0 { return core::ptr::null_mut(); }
14757 let max = n - 1;
14758 let mut i = 0usize;
14759 while i < max {
14760 let c = mntent_fgetc(f);
14761 if c == -1 { if i == 0 { return core::ptr::null_mut(); } break; }
14762 *buf.add(i) = c as c_char;
14763 i += 1;
14764 if c == b'\n' as c_int { break; }
14765 }
14766 *buf.add(i) = 0;
14767 buf
14768}
14769
14770#[no_mangle]
14771pub unsafe extern "C" fn getmntent_r(
14772 f: *mut FILE,
14773 mnt: *mut MntEnt,
14774 mut linebuf: *mut c_char,
14775 _buflen: c_int,
14776) -> *mut MntEnt {
14777 let use_internal = linebuf as usize == SENTINEL_PTR;
14778
14779 (*mnt).mnt_freq = 0;
14780 (*mnt).mnt_passno = 0;
14781
14782 static mut INTERNAL_BUF: [c_char; 4096] = [0; 4096];
14784
14785 loop {
14786 if use_internal {
14787 linebuf = core::ptr::addr_of_mut!(INTERNAL_BUF).cast::<c_char>();
14788 }
14789 let res = mntent_fgets(linebuf, 4096, f);
14790 if res.is_null() {
14791 return core::ptr::null_mut();
14792 }
14793 let mut has_newline = false;
14794 let mut p = linebuf;
14795 while *p != 0 { if *p == b'\n' as c_char { has_newline = true; break; } p = p.add(1); }
14796 if !has_newline {
14797 ERRNO = 34;
14798 return core::ptr::null_mut();
14799 }
14800 let result = parse_mntent_line(linebuf, mnt);
14801 if !result.is_null() {
14802 return result;
14803 }
14804 }
14805}
14806
14807#[no_mangle]
14808pub unsafe extern "C" fn getmntent(f: *mut FILE) -> *mut MntEnt {
14809 getmntent_r(f, core::ptr::addr_of_mut!(MNTENT_MNT), SENTINEL_PTR as *mut c_char, 0)
14810}
14811
14812#[no_mangle]
14813pub unsafe extern "C" fn addmntent(f: *mut FILE, mnt: *const MntEnt) -> c_int {
14814 fseek(f, 0, 2); let written = fprintf(
14816 f,
14817 b"%s\t%s\t%s\t%s\t%d\t%d\n\0".as_ptr() as *const c_char,
14818 (*mnt).mnt_fsname,
14819 (*mnt).mnt_dir,
14820 (*mnt).mnt_type,
14821 (*mnt).mnt_opts,
14822 (*mnt).mnt_freq,
14823 (*mnt).mnt_passno,
14824 );
14825 if written < 0 { 1 } else { 0 }
14826}
14827
14828#[no_mangle]
14829pub unsafe extern "C" fn hasmntopt(mnt: *const MntEnt, opt: *const c_char) -> *mut c_char {
14830 let l = strlen(opt as *const c_char);
14831 let mut p = (*mnt).mnt_opts;
14832 loop {
14833 if strncmp(p as *const u8, opt as *const u8, l) == 0 {
14834 let after = *p.add(l);
14835 if after == 0 || after == b',' as c_char || after == b'=' as c_char {
14836 return p;
14837 }
14838 }
14839 let comma = strchr(p as *const u8, b',' as c_int);
14840 if comma.is_null() {
14841 return core::ptr::null_mut();
14842 }
14843 p = comma.add(1) as *mut c_char;
14844 }
14845}
14846
14847const EEXIST: c_int = 17;
14855const ENAMETOOLONG: c_int = 36;
14856const EMFILE: c_int = 24;
14857const EIDRM: c_int = 43;
14858
14859#[inline]
14860unsafe fn sys_msgget(key: c_int, msgflg: c_int) -> i64 {
14861 <Arch as Syscalls>::syscall2(SYS_MSGGET, key as i64, msgflg as i64)
14862}
14863
14864#[inline]
14865unsafe fn sys_msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> i64 {
14866 <Arch as Syscalls>::syscall4(SYS_MSGSND, msqid as i64, msgp as i64, msgsz as i64, msgflg as i64)
14867}
14868
14869#[inline]
14870unsafe fn sys_msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> i64 {
14871 <Arch as Syscalls>::syscall5(SYS_MSGRCV, msqid as i64, msgp as i64, msgsz as i64, msgtyp as i64, msgflg as i64)
14872}
14873
14874#[inline]
14875unsafe fn sys_msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
14876 <Arch as Syscalls>::syscall3(SYS_MSGCTL, msqid as i64, cmd as i64, buf as i64)
14877}
14878
14879#[inline]
14880unsafe fn sys_semget(key: c_int, nsems: c_int, semflg: c_int) -> i64 {
14881 <Arch as Syscalls>::syscall3(SYS_SEMGET, key as i64, nsems as i64, semflg as i64)
14882}
14883
14884#[inline]
14885unsafe fn sys_semop(semid: c_int, sops: *const c_void, nsops: usize) -> i64 {
14886 <Arch as Syscalls>::syscall3(SYS_SEMOP, semid as i64, sops as i64, nsops as i64)
14887}
14888
14889#[inline]
14890unsafe fn sys_semctl(semid: c_int, semnum: c_int, cmd: c_int, arg: *mut c_void) -> i64 {
14891 <Arch as Syscalls>::syscall4(SYS_SEMCTL, semid as i64, semnum as i64, cmd as i64, arg as i64)
14892}
14893
14894#[inline]
14895unsafe fn sys_shmget(key: c_int, size: usize, shmflg: c_int) -> i64 {
14896 <Arch as Syscalls>::syscall3(SYS_SHMGET, key as i64, size as i64, shmflg as i64)
14897}
14898
14899#[inline]
14900unsafe fn sys_shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> i64 {
14901 <Arch as Syscalls>::syscall3(SYS_SHMAT, shmid as i64, shmaddr as i64, shmflg as i64)
14902}
14903
14904#[inline]
14905unsafe fn sys_shmdt(shmaddr: *const c_void) -> i64 {
14906 <Arch as Syscalls>::syscall1(SYS_SHMDT, shmaddr as i64)
14907}
14908
14909#[inline]
14910unsafe fn sys_shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
14911 <Arch as Syscalls>::syscall3(SYS_SHMCTL, shmid as i64, cmd as i64, buf as i64)
14912}
14913
14914#[no_mangle]
14916pub unsafe extern "C" fn ftok(path: *const c_char, id: c_int) -> c_int {
14917 let mut st: kernel_stat64 = core::mem::zeroed();
14918 let r = sys_stat(path as *const u8, &mut st);
14919 if r < 0 {
14920 ERRNO = (-r) as c_int;
14921 return -1;
14922 }
14923 ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) | (((id as u32 & 0xff) << 24)) as u64) as c_int
14924}
14925
14926#[no_mangle]
14928pub unsafe extern "C" fn msgget(key: c_int, msgflg: c_int) -> c_int {
14929 let r = sys_msgget(key, msgflg);
14930 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14931}
14932
14933#[no_mangle]
14935pub unsafe extern "C" fn msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> c_int {
14936 let r = sys_msgsnd(msqid, msgp, msgsz, 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 msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> isize {
14943 let r = sys_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
14944 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
14945}
14946
14947#[no_mangle]
14949pub unsafe extern "C" fn msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
14950 let r = sys_msgctl(msqid, cmd, buf);
14951 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14952}
14953
14954#[no_mangle]
14956pub unsafe extern "C" fn semget(key: c_int, nsems: c_int, semflg: c_int) -> c_int {
14957 if nsems > 65535 { ERRNO = 22; return -1; }
14958 let r = sys_semget(key, nsems, semflg);
14959 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14960}
14961
14962#[no_mangle]
14964pub unsafe extern "C" fn semop(semid: c_int, sops: *const c_void, nsops: usize) -> c_int {
14965 let r = sys_semop(semid, sops, nsops);
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 semctl(semid: c_int, semnum: c_int, cmd: c_int, mut args: ...) -> c_int {
14972 let mut arg: *mut c_void = core::ptr::null_mut();
14973 match cmd {
14975 16 | 13 | 17 | 1 | 3 | 2 | 0x102 | 0x104 | 0x106 => {
14976 arg = args.next_arg::<*mut c_void>();
14977 }
14978 _ => {}
14979 }
14980 let r = sys_semctl(semid, semnum, cmd, arg);
14981 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
14982}
14983
14984#[no_mangle]
14986pub unsafe extern "C" fn shmget(key: c_int, size: usize, shmflg: c_int) -> c_int {
14987 let r = sys_shmget(key, size, shmflg);
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 shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void {
14994 let r = sys_shmat(shmid, shmaddr, shmflg);
14995 if (r as usize) > (-(4096isize as isize)) as usize {
14996 ERRNO = (-r) as c_int;
14997 return core::ptr::null_mut();
14998 }
14999 r as *mut c_void
15000}
15001
15002#[no_mangle]
15004pub unsafe extern "C" fn shmdt(shmaddr: *const c_void) -> c_int {
15005 let r = sys_shmdt(shmaddr);
15006 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
15007}
15008
15009#[no_mangle]
15011pub unsafe extern "C" fn shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
15012 let r = sys_shmctl(shmid, cmd, buf);
15013 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
15014}
15015
15016#[no_mangle]
15026pub static mut __auxv: *const usize = core::ptr::null();
15027
15028#[no_mangle]
15029pub static mut __progname: *mut c_char = core::ptr::null_mut();
15030#[no_mangle]
15031pub static mut __progname_full: *mut c_char = core::ptr::null_mut();
15032#[no_mangle]
15033pub static mut program_invocation_name: *mut c_char = core::ptr::null_mut();
15034#[no_mangle]
15035pub static mut program_invocation_short_name: *mut c_char = core::ptr::null_mut();
15036
15037#[no_mangle]
15038pub static in6addr_any: [u8; 16] = [0; 16];
15039#[no_mangle]
15040pub static in6addr_loopback: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
15041
15042#[no_mangle]
15043pub static mut __daylight: c_int = 0;
15044#[no_mangle]
15045pub static mut __timezone: c_long = 0;
15046#[no_mangle]
15047pub static mut __tzname: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
15048
15049#[no_mangle]
15050pub unsafe extern "C" fn getauxval(type_: c_ulong) -> c_ulong {
15051 let mut p = __auxv;
15052 if p.is_null() {
15053 return 0;
15054 }
15055 loop {
15056 let tag = *p;
15057 if tag == 0 {
15058 return 0;
15059 }
15060 if tag == type_ as usize {
15061 return *p.add(1) as c_ulong;
15062 }
15063 p = p.add(2);
15064 }
15065}
15066
15067type MainFn = unsafe extern "C" fn(c_int, *const *const c_char, *const *const c_char) -> c_int;
15068type InitFn = unsafe extern "C" fn();
15069
15070#[no_mangle]
15071pub unsafe extern "C" fn __libc_start_main(
15072 main: MainFn,
15073 argc: c_int,
15074 argv: *const *const c_char,
15075 _init: *const c_void,
15076 _fini: *const c_void,
15077 _rtld_fini: *const c_void,
15078 _stack_end: *const c_void,
15079) -> ! {
15080 let envp = argv.add((argc + 1) as usize);
15081 __environ = envp as *mut *mut c_char;
15082 environ = __environ; ___environ = __environ;
15084 _environ = __environ;
15085
15086 if !argv.is_null() && argc > 0 {
15088 let argv0 = *argv;
15089 __progname_full = argv0 as *mut c_char;
15090 program_invocation_name = argv0 as *mut c_char;
15091 let mut base = argv0;
15092 let mut p = argv0;
15093 while *p != 0 {
15094 if *p == b'/' as c_char { base = p.add(1); }
15095 p = p.add(1);
15096 }
15097 __progname = base as *mut c_char;
15098 program_invocation_short_name = base as *mut c_char;
15099 }
15100
15101 __stdio_init();
15102
15103 let mut set: SigSetT = 0;
15104 sigemptyset(&mut set);
15105 sigaddset(&mut set, SIGCANCEL);
15106 sigprocmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
15107
15108 if !_init.is_null() {
15109 let init_fn: InitFn = core::mem::transmute(_init);
15110 init_fn();
15111 }
15112
15113 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
15117 {
15118 let random_ptr = getauxval(25) as *const u8; if !random_ptr.is_null() {
15120 let a = core::ptr::read_unaligned(random_ptr as *const u64);
15121 let b = core::ptr::read_unaligned(random_ptr.add(8) as *const u64);
15122 __stack_chk_guard = (a ^ b) as usize;
15123 } else {
15124 __stack_chk_guard = 0xdefaced_cafebeef;
15126 }
15127 }
15128
15129 let result = main(argc, argv, envp);
15130
15131 if !_fini.is_null() {
15132 let fini_fn: InitFn = core::mem::transmute(_fini);
15133 fini_fn();
15134 }
15135
15136 exit(result);
15137}
15138
15139type LdsoDlopenFn = unsafe extern "C" fn(*const c_char, c_int) -> *mut c_void;
15140type LdsoDlsymFn = unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void;
15141type LdsoDlcloseFn = unsafe extern "C" fn(*mut c_void) -> c_int;
15142type LdsoDlerrorFn = unsafe extern "C" fn() -> *const c_char;
15143
15144static mut LDSO_DLOPEN: Option<LdsoDlopenFn> = None;
15145static mut LDSO_DLSYM: Option<LdsoDlsymFn> = None;
15146static mut LDSO_DLCLOSE: Option<LdsoDlcloseFn> = None;
15147static mut LDSO_DLERROR: Option<LdsoDlerrorFn> = None;
15148
15149#[no_mangle]
15150pub unsafe extern "C" fn __ldso_register_dlopen(f: LdsoDlopenFn) {
15151 LDSO_DLOPEN = Some(f);
15152}
15153
15154#[no_mangle]
15155pub unsafe extern "C" fn __ldso_register_dlsym(f: LdsoDlsymFn) {
15156 LDSO_DLSYM = Some(f);
15157}
15158
15159#[no_mangle]
15160pub unsafe extern "C" fn __ldso_register_dlclose(f: LdsoDlcloseFn) {
15161 LDSO_DLCLOSE = Some(f);
15162}
15163
15164#[no_mangle]
15165pub unsafe extern "C" fn __ldso_register_dlerror(f: LdsoDlerrorFn) {
15166 LDSO_DLERROR = Some(f);
15167}
15168
15169#[no_mangle]
15170pub unsafe extern "C" fn dlopen(filename: *const c_char, flags: c_int) -> *mut c_void {
15171 if let Some(f) = LDSO_DLOPEN {
15172 f(filename, flags)
15173 } else {
15174 null_mut()
15175 }
15176}
15177
15178#[no_mangle]
15179pub unsafe extern "C" fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void {
15180 if let Some(f) = LDSO_DLSYM {
15181 f(handle, symbol)
15182 } else {
15183 null_mut()
15184 }
15185}
15186
15187#[no_mangle]
15188pub unsafe extern "C" fn dlclose(handle: *mut c_void) -> c_int {
15189 if let Some(f) = LDSO_DLCLOSE {
15190 f(handle)
15191 } else {
15192 0
15193 }
15194}
15195
15196#[no_mangle]
15197pub unsafe extern "C" fn dlerror() -> *const c_char {
15198 if let Some(f) = LDSO_DLERROR {
15199 f()
15200 } else {
15201 core::ptr::null()
15202 }
15203}
15204
15205include!("crypt_impl.rs");
15206include!("statvfs.rs");
15207include!("daemon.rs");
15208include!("dn_expand.rs");
15209include!("lrand48.rs");
15210include!("strverscmp.rs");
15211include!("syscall.rs");
15212include!("pthread_atfork.rs");
15213include!("fenv.rs");
15214include!("locale_ctype.rs");
15215include!("regression_stubs.rs");
15216include!("netdb_extra.rs");
15217include!("compat_extra.rs");
15218include!("stdio_extra.rs");
15219include!("ns_parse.rs");
15220include!("fts.rs");
15221include!("ifaddrs.rs");
15222include!("dl_extra.rs");
15223include!("des.rs");
15224include!("path_extra.rs");
15225include!("wordexp.rs");
15226include!("getopt_impl.rs");
15227
15228type regoff_t = c_int;
15233
15234#[repr(C)]
15235pub struct regex_t {
15236 pub re_nsub: usize,
15237 pub __opaque: *mut c_void,
15238 pub __padding: [*mut c_void; 4],
15239 pub __nsub2: usize,
15240 pub __padding2: c_char,
15241}
15242
15243#[repr(C)]
15244pub struct regmatch_t {
15245 pub rm_so: regoff_t,
15246 pub rm_eo: regoff_t,
15247}
15248
15249include!("regex.rs");
15250
15251#[cfg(test)]
15252mod libc_unit_stub {
15253 #[test]
15254 fn stub() {
15255 assert!(true);
15256 }
15257}
15258
15259#[inline]
15264pub(crate) fn fmax_impl(x: f64, y: f64) -> f64 {
15265 if x.is_nan() { return y; }
15266 if y.is_nan() { return x; }
15267 if x == 0.0 && y == 0.0 {
15268 return if x.is_sign_negative() && y.is_sign_negative() { -0.0 } else { 0.0 };
15269 }
15270 if x > y { x } else { y }
15271}
15272
15273#[inline]
15274pub(crate) fn fmin_impl(x: f64, y: f64) -> f64 {
15275 if x.is_nan() { return y; }
15276 if y.is_nan() { return x; }
15277 if x == 0.0 && y == 0.0 {
15278 return if x.is_sign_negative() || y.is_sign_negative() { -0.0 } else { 0.0 };
15279 }
15280 if x < y { x } else { y }
15281}
15282
15283#[inline]
15284pub(crate) fn fmaxf_impl(x: f32, y: f32) -> f32 {
15285 if x.is_nan() { return y; }
15286 if y.is_nan() { return x; }
15287 if x == 0.0 && y == 0.0 {
15288 return if x.is_sign_negative() && y.is_sign_negative() { -0.0 } else { 0.0 };
15289 }
15290 if x > y { x } else { y }
15291}
15292
15293#[inline]
15294pub(crate) fn fminf_impl(x: f32, y: f32) -> f32 {
15295 if x.is_nan() { return y; }
15296 if y.is_nan() { return x; }
15297 if x == 0.0 && y == 0.0 {
15298 return if x.is_sign_negative() || y.is_sign_negative() { -0.0 } else { 0.0 };
15299 }
15300 if x < y { x } else { y }
15301}
15302
15303#[inline(never)]
15304#[no_mangle]
15305pub unsafe extern "C" fn fmax(x: f64, y: f64) -> f64 {
15306 fmax_impl(x, y)
15307}
15308
15309#[inline(never)]
15310#[no_mangle]
15311pub unsafe extern "C" fn fmin(x: f64, y: f64) -> f64 {
15312 fmin_impl(x, y)
15313}
15314
15315#[no_mangle]
15316pub unsafe extern "C" fn fminf(x: f32, y: f32) -> f32 {
15317 fminf_impl(x, y)
15318}
15319
15320#[no_mangle]
15321pub unsafe extern "C" fn fdim(x: f64, y: f64) -> f64 {
15322 if x.is_nan() || y.is_nan() {
15323 return f64::NAN;
15324 }
15325 if x > y { x - y } else { 0.0 }
15326}
15327
15328#[no_mangle]
15329pub unsafe extern "C" fn fma(x: f64, y: f64, z: f64) -> f64 {
15330 if (x.is_infinite() && y == 0.0) || (y.is_infinite() && x == 0.0) {
15331 feraiseexcept(FE_INVALID);
15332 return f64::NAN;
15333 }
15334 if x.is_nan() || y.is_nan() || z.is_nan() {
15335 return f64::NAN;
15336 }
15337 let r = libm::fma(x, y, z);
15338 if r.is_nan() {
15340 feraiseexcept(FE_INVALID);
15341 }
15342 r
15343}
15344
15345#[no_mangle]
15346pub unsafe extern "C" fn ilogb(x: f64) -> i32 {
15347 if x.is_nan() {
15348 feraiseexcept(FE_INVALID);
15349 return -0x7fffffff - 1; }
15351 if x == 0.0 || x.is_infinite() {
15352 feraiseexcept(FE_INVALID);
15353 return if x == 0.0 { -0x7fffffff - 1 } else { 0x7fffffff };
15354 }
15355 let bits = x.to_bits();
15356 let exp = ((bits >> 52) & 0x7ff) as i32;
15357 if exp == 0 {
15358 let mut v = bits & 0xfffffffffffff;
15360 let mut e = -1022;
15361 while v < (1u64 << 52) { v <<= 1; e -= 1; }
15362 e
15363 } else {
15364 exp - 1023
15365 }
15366}
15367
15368#[no_mangle]
15369pub unsafe extern "C" fn logb(x: f64) -> f64 {
15370 if x.is_nan() { return x; }
15371 if x == 0.0 { return __math_divzero(1); }
15372 let bits = x.to_bits();
15373 let exp = ((bits >> 52) & 0x7ff) as i32;
15374 if exp == 0 {
15375 let mut v = bits & 0xfffffffffffff;
15377 let mut e = -1022i32;
15378 while v < (1u64 << 52) { v <<= 1; e -= 1; }
15379 e as f64
15380 } else if exp == 0x7ff {
15381 x * x } else {
15383 (exp - 1023) as f64
15384 }
15385}
15386
15387#[no_mangle]
15388pub unsafe extern "C" fn nearbyint(x: f64) -> f64 {
15389 let had_inexact = fetestexcept(FE_INEXACT) & FE_INEXACT != 0;
15390 let r = libm::rint(x);
15391 if !had_inexact {
15392 feclearexcept(FE_INEXACT);
15393 }
15394 r
15395}
15396
15397#[no_mangle]
15398pub unsafe extern "C" fn nextafter(x: f64, y: f64) -> f64 {
15399 if x.is_nan() || y.is_nan() { return x + y; }
15400 if x == 0.0 && y == 0.0 { return y; }
15401 if x == y { return x; }
15402 let r = libm::nextafter(x, y);
15403 if r.is_infinite() && x.is_finite() {
15404 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
15405 } else if r != x {
15406 let bits = r.to_bits();
15407 let is_subnormal = (bits & 0x7ff0000000000000) == 0 && (bits & 0xfffffffffffff) != 0;
15408 if r == 0.0 || is_subnormal {
15409 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
15410 }
15411 }
15412 r
15413}
15414
15415#[no_mangle]
15416pub unsafe extern "C" fn nexttoward(x: f64, y: f64) -> f64 {
15417 if x == 0.0 && y == 0.0 {
15419 return if y.is_sign_negative() { -0.0 } else { 0.0 };
15420 }
15421 nextafter(x, y)
15422}
15423
15424#[no_mangle]
15425pub unsafe extern "C" fn remainder(x: f64, y: f64) -> f64 {
15426 if x.is_nan() || y.is_nan() { return x + y; }
15427 if y == 0.0 || x.is_infinite() { return __math_invalid(x); }
15428 libm::remainder(x, y)
15429}
15430
15431#[no_mangle]
15432pub unsafe extern "C" fn remquo(x: f64, y: f64, quo: *mut i32) -> f64 {
15433 if x.is_nan() || y.is_nan() {
15434 if !quo.is_null() { *quo = 0; }
15435 return x + y;
15436 }
15437 if y == 0.0 || x.is_infinite() {
15438 if !quo.is_null() { *quo = 0; }
15439 return __math_invalid(x);
15440 }
15441 let (r, q) = libm::remquo(x, y);
15442 if !quo.is_null() { *quo = q; }
15443 r
15444}
15445
15446#[no_mangle]
15447pub unsafe extern "C" fn exp2(x: f64) -> f64 {
15448 exp2_impl(x)
15449}
15450
15451#[no_mangle]
15452pub unsafe extern "C" fn expm1(x: f64) -> f64 {
15453 let r = libm::expm1(x);
15454 if r != 0.0 && x != 0.0 && libm::fabs(x) < 1e-307 {
15456 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
15457 }
15458 r
15459}
15460
15461#[no_mangle]
15462pub unsafe extern "C" fn log1p(x: f64) -> f64 {
15463 if x == -1.0 {
15464 feraiseexcept(FE_DIVBYZERO);
15465 return f64::NEG_INFINITY;
15466 }
15467 libm::log1p(x)
15468}
15469
15470#[no_mangle]
15471pub unsafe extern "C" fn acosh(x: f64) -> f64 {
15472 if x < 1.0 {
15473 feraiseexcept(FE_INVALID);
15474 return f64::NAN;
15475 }
15476 libm::acosh(x)
15477}
15478
15479#[no_mangle]
15480pub unsafe extern "C" fn asinh(x: f64) -> f64 {
15481 if x == 0.0 { return x; }
15482 libm::asinh(x)
15483}
15484
15485#[no_mangle]
15486pub unsafe extern "C" fn atanh(x: f64) -> f64 {
15487 if x == 0.0 { return x; }
15488 let e = ((x.to_bits() >> 52) & 0x7ff) as i32;
15489 if e < 0x3ff - 32 {
15490 feraiseexcept(FE_INEXACT);
15491 if e == 0 { feraiseexcept(FE_UNDERFLOW); }
15492 return x;
15493 }
15494 if x == 1.0 {
15495 feraiseexcept(FE_DIVBYZERO);
15496 return f64::INFINITY;
15497 }
15498 if x == -1.0 {
15499 feraiseexcept(FE_DIVBYZERO);
15500 return f64::NEG_INFINITY;
15501 }
15502 if x.is_nan() { return x; }
15503 let ax = libm::fabs(x);
15504 if ax > 1.0 {
15505 feraiseexcept(FE_INVALID);
15506 return f64::NAN;
15507 }
15508 if ax < 0.5 {
15509 let r = libm::log1p(2.0 * (ax + ax * ax / (1.0 - ax))) / 2.0;
15511 if x < 0.0 { -r } else { r }
15512 } else {
15513 let r = 0.5 * libm::log((1.0 + ax) / (1.0 - ax));
15515 if x < 0.0 { -r } else { r }
15516 }
15517}
15518
15519#[no_mangle]
15520pub unsafe extern "C" fn cbrt(x: f64) -> f64 {
15521 libm::cbrt(x)
15522}
15523
15524#[no_mangle]
15525pub unsafe extern "C" fn erf(x: f64) -> f64 {
15526 erf_impl(x)
15527}
15528
15529#[no_mangle]
15530pub unsafe extern "C" fn erfc(x: f64) -> f64 {
15531 erfc_impl(x)
15532}
15533
15534#[no_mangle]
15535pub unsafe extern "C" fn lgamma(x: f64) -> f64 {
15536 lgamma_impl(x)
15537}
15538
15539#[no_mangle]
15540pub unsafe extern "C" fn tgamma(x: f64) -> f64 {
15541 tgamma_impl(x)
15542}
15543
15544#[no_mangle]
15545pub unsafe extern "C" fn lround(x: f64) -> core::ffi::c_long {
15546 libm::round(x) as core::ffi::c_long
15547}
15548
15549#[no_mangle]
15550pub unsafe extern "C" fn llround(x: f64) -> i64 {
15551 libm::round(x) as i64
15552}
15553
15554#[no_mangle]
15561pub unsafe extern "C" fn cabs(z: (f64, f64)) -> f64 {
15562 libm::sqrt(z.0 * z.0 + z.1 * z.1)
15563}
15564
15565#[no_mangle]
15566pub unsafe extern "C" fn cabsf(z: (f32, f32)) -> f32 {
15567 libm::sqrtf(z.0 * z.0 + z.1 * z.1)
15568}
15569
15570#[no_mangle]
15571pub unsafe extern "C" fn cabsl(z: (f64, f64)) -> f64 {
15572 cabs(z)
15573}
15574
15575#[no_mangle]
15576pub unsafe extern "C" fn carg(z: (f64, f64)) -> f64 {
15577 libm::atan2(z.1, z.0)
15578}
15579
15580#[no_mangle]
15581pub unsafe extern "C" fn cargf(z: (f32, f32)) -> f32 {
15582 libm::atan2f(z.1, z.0)
15583}
15584
15585#[no_mangle]
15586pub unsafe extern "C" fn cargl(z: (f64, f64)) -> f64 {
15587 carg(z)
15588}
15589
15590#[no_mangle]
15591pub unsafe extern "C" fn cimag(z: (f64, f64)) -> f64 {
15592 z.1
15593}
15594
15595#[no_mangle]
15596pub unsafe extern "C" fn cimagf(z: (f32, f32)) -> f32 {
15597 z.1
15598}
15599
15600#[no_mangle]
15601pub unsafe extern "C" fn cimagl(z: (f64, f64)) -> f64 {
15602 z.1
15603}
15604
15605#[no_mangle]
15606pub unsafe extern "C" fn creal(z: (f64, f64)) -> f64 {
15607 z.0
15608}
15609
15610#[no_mangle]
15611pub unsafe extern "C" fn crealf(z: (f32, f32)) -> f32 {
15612 z.0
15613}
15614
15615#[no_mangle]
15616pub unsafe extern "C" fn creall(z: (f64, f64)) -> f64 {
15617 z.0
15618}
15619
15620#[no_mangle]
15621pub unsafe extern "C" fn conj(z: (f64, f64)) -> (f64, f64) {
15622 (z.0, -z.1)
15623}
15624
15625#[no_mangle]
15626pub unsafe extern "C" fn conjf(z: (f32, f32)) -> (f32, f32) {
15627 (z.0, -z.1)
15628}
15629
15630#[no_mangle]
15631pub unsafe extern "C" fn conjl(z: (f64, f64)) -> (f64, f64) {
15632 conj(z)
15633}
15634
15635#[no_mangle]
15636pub unsafe extern "C" fn cproj(z: (f64, f64)) -> (f64, f64) {
15637 if z.0.is_infinite() || z.1.is_infinite() {
15638 (f64::INFINITY, if z.1.is_sign_positive() { 0.0 } else { -0.0 })
15639 } else {
15640 z
15641 }
15642}
15643
15644#[no_mangle]
15645pub unsafe extern "C" fn cprojf(z: (f32, f32)) -> (f32, f32) {
15646 if z.0.is_infinite() || z.1.is_infinite() {
15647 (f32::INFINITY, if z.1.is_sign_positive() { 0.0 } else { -0.0 })
15648 } else {
15649 z
15650 }
15651}
15652
15653#[no_mangle]
15654pub unsafe extern "C" fn cprojl(z: (f64, f64)) -> (f64, f64) {
15655 cproj(z)
15656}
15657
15658#[no_mangle]
15660pub unsafe extern "C" fn cexp(z: (f64, f64)) -> (f64, f64) {
15661 let r = libm::exp(z.0);
15662 (r * libm::cos(z.1), r * libm::sin(z.1))
15663}
15664
15665#[no_mangle]
15666pub unsafe extern "C" fn cexpf(z: (f32, f32)) -> (f32, f32) {
15667 let r = libm::expf(z.0);
15668 (r * libm::cosf(z.1), r * libm::sinf(z.1))
15669}
15670
15671#[no_mangle]
15672pub unsafe extern "C" fn cexpl(z: (f64, f64)) -> (f64, f64) {
15673 cexp(z)
15674}
15675
15676#[no_mangle]
15678pub unsafe extern "C" fn clog(z: (f64, f64)) -> (f64, f64) {
15679 (libm::log(cabs(z)), carg(z))
15680}
15681
15682#[no_mangle]
15683pub unsafe extern "C" fn clogf(z: (f32, f32)) -> (f32, f32) {
15684 (libm::logf(cabsf(z)), cargf(z))
15685}
15686
15687#[no_mangle]
15688pub unsafe extern "C" fn clogl(z: (f64, f64)) -> (f64, f64) {
15689 clog(z)
15690}
15691
15692#[no_mangle]
15694pub unsafe extern "C" fn csqrt(z: (f64, f64)) -> (f64, f64) {
15695 let r = cabs(z);
15696 let sign = if z.1 < 0.0 { -1.0 } else { 1.0 };
15697 (libm::sqrt((r + z.0) / 2.0), sign * libm::sqrt((r - z.0) / 2.0))
15698}
15699
15700#[no_mangle]
15701pub unsafe extern "C" fn csqrtf(z: (f32, f32)) -> (f32, f32) {
15702 let r = cabsf(z);
15703 let sign = if z.1 < 0.0 { -1.0f32 } else { 1.0f32 };
15704 (libm::sqrtf((r + z.0) / 2.0), sign * libm::sqrtf((r - z.0) / 2.0))
15705}
15706
15707#[no_mangle]
15708pub unsafe extern "C" fn csqrtl(z: (f64, f64)) -> (f64, f64) {
15709 csqrt(z)
15710}
15711
15712#[no_mangle]
15714pub unsafe extern "C" fn cpow(z: (f64, f64), w: (f64, f64)) -> (f64, f64) {
15715 let log_z = clog(z);
15716 let exp_arg = (w.0 * log_z.0 - w.1 * log_z.1, w.0 * log_z.1 + w.1 * log_z.0);
15717 cexp(exp_arg)
15718}
15719
15720#[no_mangle]
15721pub unsafe extern "C" fn cpowf(z: (f32, f32), w: (f32, f32)) -> (f32, f32) {
15722 let log_z = clogf(z);
15723 let exp_arg = (w.0 * log_z.0 - w.1 * log_z.1, w.0 * log_z.1 + w.1 * log_z.0);
15724 cexpf(exp_arg)
15725}
15726
15727#[no_mangle]
15728pub unsafe extern "C" fn cpowl(z: (f64, f64), w: (f64, f64)) -> (f64, f64) {
15729 cpow(z, w)
15730}
15731
15732#[no_mangle]
15734pub unsafe extern "C" fn ccos(z: (f64, f64)) -> (f64, f64) {
15735 (libm::cos(z.0) * libm::cosh(z.1), -libm::sin(z.0) * libm::sinh(z.1))
15736}
15737
15738#[no_mangle]
15739pub unsafe extern "C" fn ccosf(z: (f32, f32)) -> (f32, f32) {
15740 (libm::cosf(z.0) * libm::coshf(z.1), -libm::sinf(z.0) * libm::sinhf(z.1))
15741}
15742
15743#[no_mangle]
15744pub unsafe extern "C" fn ccosl(z: (f64, f64)) -> (f64, f64) {
15745 ccos(z)
15746}
15747
15748#[no_mangle]
15750pub unsafe extern "C" fn csin(z: (f64, f64)) -> (f64, f64) {
15751 (libm::sin(z.0) * libm::cosh(z.1), libm::cos(z.0) * libm::sinh(z.1))
15752}
15753
15754#[no_mangle]
15755pub unsafe extern "C" fn csinf(z: (f32, f32)) -> (f32, f32) {
15756 (libm::sinf(z.0) * libm::coshf(z.1), libm::cosf(z.0) * libm::sinhf(z.1))
15757}
15758
15759#[no_mangle]
15760pub unsafe extern "C" fn csinl(z: (f64, f64)) -> (f64, f64) {
15761 csin(z)
15762}
15763
15764#[no_mangle]
15766pub unsafe extern "C" fn ctan(z: (f64, f64)) -> (f64, f64) {
15767 let d = libm::cos(2.0 * z.0) + libm::cosh(2.0 * z.1);
15768 (libm::sin(2.0 * z.0) / d, libm::sinh(2.0 * z.1) / d)
15769}
15770
15771#[no_mangle]
15772pub unsafe extern "C" fn ctanf(z: (f32, f32)) -> (f32, f32) {
15773 let d = libm::cosf(2.0 * z.0) + libm::coshf(2.0 * z.1);
15774 (libm::sinf(2.0 * z.0) / d, libm::sinhf(2.0 * z.1) / d)
15775}
15776
15777#[no_mangle]
15778pub unsafe extern "C" fn ctanl(z: (f64, f64)) -> (f64, f64) {
15779 ctan(z)
15780}
15781
15782#[no_mangle]
15784pub unsafe extern "C" fn ccosh(z: (f64, f64)) -> (f64, f64) {
15785 (libm::cosh(z.0) * libm::cos(z.1), libm::sinh(z.0) * libm::sin(z.1))
15786}
15787
15788#[no_mangle]
15789pub unsafe extern "C" fn ccoshf(z: (f32, f32)) -> (f32, f32) {
15790 (libm::coshf(z.0) * libm::cosf(z.1), libm::sinhf(z.0) * libm::sinf(z.1))
15791}
15792
15793#[no_mangle]
15794pub unsafe extern "C" fn ccoshl(z: (f64, f64)) -> (f64, f64) {
15795 ccosh(z)
15796}
15797
15798#[no_mangle]
15800pub unsafe extern "C" fn csinh(z: (f64, f64)) -> (f64, f64) {
15801 (libm::sinh(z.0) * libm::cos(z.1), libm::cosh(z.0) * libm::sin(z.1))
15802}
15803
15804#[no_mangle]
15805pub unsafe extern "C" fn csinhf(z: (f32, f32)) -> (f32, f32) {
15806 (libm::sinhf(z.0) * libm::cosf(z.1), libm::coshf(z.0) * libm::sinf(z.1))
15807}
15808
15809#[no_mangle]
15810pub unsafe extern "C" fn csinhl(z: (f64, f64)) -> (f64, f64) {
15811 csinh(z)
15812}
15813
15814#[no_mangle]
15816pub unsafe extern "C" fn ctanh(z: (f64, f64)) -> (f64, f64) {
15817 let d = libm::cosh(2.0 * z.0) + libm::cos(2.0 * z.1);
15818 (libm::sinh(2.0 * z.0) / d, libm::sin(2.0 * z.1) / d)
15819}
15820
15821#[no_mangle]
15822pub unsafe extern "C" fn ctanhf(z: (f32, f32)) -> (f32, f32) {
15823 let d = libm::coshf(2.0 * z.0) + libm::cosf(2.0 * z.1);
15824 (libm::sinhf(2.0 * z.0) / d, libm::sinf(2.0 * z.1) / d)
15825}
15826
15827#[no_mangle]
15828pub unsafe extern "C" fn ctanhl(z: (f64, f64)) -> (f64, f64) {
15829 ctanh(z)
15830}
15831
15832#[no_mangle]
15835pub unsafe extern "C" fn cacos(z: (f64, f64)) -> (f64, f64) {
15836 let asin_z = casin(z);
15837 (3.14159265358979323846264338327950288419716939937510582097494459230781640 / 2.0 - asin_z.0, -asin_z.1)
15838}
15839
15840#[no_mangle]
15841pub unsafe extern "C" fn cacosf(z: (f32, f32)) -> (f32, f32) {
15842 let asin_z = casinf(z);
15843 (3.14159265358979323846264338327950288419716939937510582097494459230781640f32 / 2.0 - asin_z.0, -asin_z.1)
15844}
15845
15846#[no_mangle]
15847pub unsafe extern "C" fn cacosl(z: (f64, f64)) -> (f64, f64) {
15848 cacos(z)
15849}
15850
15851#[no_mangle]
15853pub unsafe extern "C" fn casin(z: (f64, f64)) -> (f64, f64) {
15854 let iz = (-z.1, z.0);
15856 let one_minus_z2 = (1.0 - z.0 * z.0 + z.1 * z.1, -2.0 * z.0 * z.1);
15858 let sqrt_val = csqrt(one_minus_z2);
15859 let arg = clog((iz.0 + sqrt_val.0, iz.1 + sqrt_val.1));
15860 (arg.1, -arg.0)
15862}
15863
15864#[no_mangle]
15865pub unsafe extern "C" fn casinf(z: (f32, f32)) -> (f32, f32) {
15866 let iz = (-z.1, z.0);
15867 let one_minus_z2 = (1.0 - z.0 * z.0 + z.1 * z.1, -2.0 * z.0 * z.1);
15868 let sqrt_val = csqrtf(one_minus_z2);
15869 let arg = clogf((iz.0 + sqrt_val.0, iz.1 + sqrt_val.1));
15870 (arg.1, -arg.0)
15871}
15872
15873#[no_mangle]
15874pub unsafe extern "C" fn casinl(z: (f64, f64)) -> (f64, f64) {
15875 casin(z)
15876}
15877
15878#[no_mangle]
15880pub unsafe extern "C" fn catan(z: (f64, f64)) -> (f64, f64) {
15881 let num = (1.0 + z.1, -z.0);
15885 let den = (1.0 - z.1, z.0);
15886 let ratio = cdiv(num, den);
15887 let log_ratio = clog(ratio);
15888 (-log_ratio.1 / 2.0, log_ratio.0 / 2.0)
15890}
15891
15892#[no_mangle]
15893pub unsafe extern "C" fn catanf(z: (f32, f32)) -> (f32, f32) {
15894 let num = (1.0 + z.1, -z.0);
15895 let den = (1.0 - z.1, z.0);
15896 let ratio = cdivf(num, den);
15897 let log_ratio = clogf(ratio);
15898 (-log_ratio.1 / 2.0, log_ratio.0 / 2.0)
15899}
15900
15901#[no_mangle]
15902pub unsafe extern "C" fn catanl(z: (f64, f64)) -> (f64, f64) {
15903 catan(z)
15904}
15905
15906fn cdiv(a: (f64, f64), b: (f64, f64)) -> (f64, f64) {
15908 let d = b.0 * b.0 + b.1 * b.1;
15909 ((a.0 * b.0 + a.1 * b.1) / d, (a.1 * b.0 - a.0 * b.1) / d)
15910}
15911
15912fn cdivf(a: (f32, f32), b: (f32, f32)) -> (f32, f32) {
15913 let d = b.0 * b.0 + b.1 * b.1;
15914 ((a.0 * b.0 + a.1 * b.1) / d, (a.1 * b.0 - a.0 * b.1) / d)
15915}
15916
15917#[no_mangle]
15919pub unsafe extern "C" fn cacosh(z: (f64, f64)) -> (f64, f64) {
15920 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
15921 let z2_minus_1 = (z2.0 - 1.0, z2.1);
15922 let sqrt_val = csqrt(z2_minus_1);
15923 clog((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
15924}
15925
15926#[no_mangle]
15927pub unsafe extern "C" fn cacoshf(z: (f32, f32)) -> (f32, f32) {
15928 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
15929 let z2_minus_1 = (z2.0 - 1.0, z2.1);
15930 let sqrt_val = csqrtf(z2_minus_1);
15931 clogf((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
15932}
15933
15934#[no_mangle]
15935pub unsafe extern "C" fn cacoshl(z: (f64, f64)) -> (f64, f64) {
15936 cacosh(z)
15937}
15938
15939#[no_mangle]
15941pub unsafe extern "C" fn casinh(z: (f64, f64)) -> (f64, f64) {
15942 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
15943 let z2_plus_1 = (z2.0 + 1.0, z2.1);
15944 let sqrt_val = csqrt(z2_plus_1);
15945 clog((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
15946}
15947
15948#[no_mangle]
15949pub unsafe extern "C" fn casinhf(z: (f32, f32)) -> (f32, f32) {
15950 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
15951 let z2_plus_1 = (z2.0 + 1.0, z2.1);
15952 let sqrt_val = csqrtf(z2_plus_1);
15953 clogf((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
15954}
15955
15956#[no_mangle]
15957pub unsafe extern "C" fn casinhl(z: (f64, f64)) -> (f64, f64) {
15958 casinh(z)
15959}
15960
15961#[no_mangle]
15963pub unsafe extern "C" fn catanh(z: (f64, f64)) -> (f64, f64) {
15964 let num = (1.0 + z.0, z.1);
15965 let den = (1.0 - z.0, -z.1);
15966 let ratio = cdiv(num, den);
15967 let log_ratio = clog(ratio);
15968 (log_ratio.0 / 2.0, log_ratio.1 / 2.0)
15969}
15970
15971#[no_mangle]
15972pub unsafe extern "C" fn catanhf(z: (f32, f32)) -> (f32, f32) {
15973 let num = (1.0 + z.0, z.1);
15974 let den = (1.0 - z.0, -z.1);
15975 let ratio = cdivf(num, den);
15976 let log_ratio = clogf(ratio);
15977 (log_ratio.0 / 2.0, log_ratio.1 / 2.0)
15978}
15979
15980#[no_mangle]
15981pub unsafe extern "C" fn catanhl(z: (f64, f64)) -> (f64, f64) {
15982 catanh(z)
15983}
15984
15985#[inline(never)]
15990#[no_mangle]
15991pub unsafe extern "C" fn fmaxf(x: f32, y: f32) -> f32 {
15992 fmaxf_impl(x, y)
15993}
15994
15995#[no_mangle]
15996pub unsafe extern "C" fn fdimf(x: f32, y: f32) -> f32 {
15997 if x.is_nan() || y.is_nan() {
15998 return f32::NAN;
15999 }
16000 if x > y { x - y } else { 0.0 }
16001}
16002
16003#[no_mangle]
16004pub unsafe extern "C" fn fmaf(x: f32, y: f32, z: f32) -> f32 {
16005 if (x.is_infinite() && y == 0.0) || (y.is_infinite() && x == 0.0) {
16006 feraiseexcept(FE_INVALID);
16007 return f32::NAN;
16008 }
16009 if x.is_nan() || y.is_nan() || z.is_nan() {
16010 return f32::NAN;
16011 }
16012 let r = libm::fmaf(x, y, z);
16013 if r.is_nan() {
16014 feraiseexcept(FE_INVALID);
16015 }
16016 r
16017}
16018
16019#[no_mangle]
16020pub unsafe extern "C" fn ilogbf(x: f32) -> i32 {
16021 if x.is_nan() {
16022 feraiseexcept(FE_INVALID);
16023 return -0x7fffffff - 1;
16024 }
16025 if x == 0.0 || x.is_infinite() {
16026 feraiseexcept(FE_INVALID);
16027 return if x == 0.0 { -0x7fffffff - 1 } else { 0x7fffffff };
16028 }
16029 let bits = x.to_bits();
16030 let exp = ((bits >> 23) & 0xff) as i32;
16031 if exp == 0 {
16032 let mut v = bits & 0x7fffff;
16033 let mut e = -126;
16034 while v < (1u32 << 23) { v <<= 1; e -= 1; }
16035 e
16036 } else {
16037 exp - 127
16038 }
16039}
16040
16041#[no_mangle]
16042pub unsafe extern "C" fn logbf(x: f32) -> f32 {
16043 if x.is_nan() { return x; }
16044 if x == 0.0 { return __math_divzerof(1); }
16045 let bits = x.to_bits();
16046 let exp = ((bits >> 23) & 0xff) as i32;
16047 if exp == 0 {
16048 let mut v = bits & 0x7fffff;
16049 let mut e = -126i32;
16050 while v < (1u32 << 23) { v <<= 1; e -= 1; }
16051 e as f32
16052 } else if exp == 0xff {
16053 x * x
16054 } else {
16055 (exp - 127) as f32
16056 }
16057}
16058
16059#[no_mangle]
16060pub unsafe extern "C" fn nearbyintf(x: f32) -> f32 {
16061 let had_inexact = fetestexcept(FE_INEXACT) & FE_INEXACT != 0;
16062 let r = libm::rintf(x);
16063 if !had_inexact {
16064 feclearexcept(FE_INEXACT);
16065 }
16066 r
16067}
16068
16069#[no_mangle]
16070pub unsafe extern "C" fn nextafterf(x: f32, y: f32) -> f32 {
16071 if x.is_nan() || y.is_nan() { return x + y; }
16072 if x == 0.0 && y == 0.0 { return y; }
16073 if x == y { return x; }
16074 let r = libm::nextafterf(x, y);
16075 if r.is_infinite() && x.is_finite() {
16076 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16077 } else if r != x {
16078 let bits = r.to_bits();
16079 let is_subnormal = (bits & 0x7f800000) == 0 && (bits & 0x7fffff) != 0;
16080 if r == 0.0 || is_subnormal {
16081 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16082 }
16083 }
16084 r
16085}
16086
16087#[no_mangle]
16088#[cfg(target_arch = "x86_64")]
16089pub unsafe extern "C" fn nexttowardf(x: f32, y: f64) -> f32 {
16090 if y.is_nan() { return (x as f64 + y) as f32; }
16091 if x == 0.0 && y == 0.0 {
16092 return if y.is_sign_negative() { -0.0 } else { 0.0 };
16093 }
16094 if (x as f64) == y { return x; }
16095 nextafterf(x, if y > x as f64 { f32::INFINITY } else { f32::NEG_INFINITY })
16096}
16097
16098#[no_mangle]
16099#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
16100pub unsafe extern "C" fn nexttowardf(x: f32, y: f128) -> f32 {
16101 if y.is_nan() { return (x as f128 + y) as f32; }
16102 if (x as f128) == y { return x; }
16103 nextafterf(x, if y > x as f128 { f32::INFINITY } else { f32::NEG_INFINITY })
16104}
16105
16106#[no_mangle]
16107pub unsafe extern "C" fn remainderf(x: f32, y: f32) -> f32 {
16108 if x.is_nan() || y.is_nan() { return x + y; }
16109 if y == 0.0 || x.is_infinite() { return __math_invalidf(x); }
16110 libm::remainderf(x, y)
16111}
16112
16113#[no_mangle]
16114pub unsafe extern "C" fn remquof(x: f32, y: f32, quo: *mut i32) -> f32 {
16115 if x.is_nan() || y.is_nan() {
16116 if !quo.is_null() { *quo = 0; }
16117 return x + y;
16118 }
16119 if y == 0.0 || x.is_infinite() {
16120 if !quo.is_null() { *quo = 0; }
16121 return __math_invalidf(x);
16122 }
16123 let (r, q) = libm::remquof(x, y);
16124 if !quo.is_null() { *quo = q; }
16125 r
16126}
16127
16128#[no_mangle]
16129pub unsafe extern "C" fn exp2f(x: f32) -> f32 {
16130 if x == f32::INFINITY { return f32::INFINITY; }
16131 if x == f32::NEG_INFINITY { return 0.0; }
16132 if x.is_nan() { return f32::NAN; }
16133 let r = libm::exp2f(x);
16134 if r.is_infinite() && x.is_finite() {
16135 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16136 } else if r == 0.0 && x < -149.0 {
16137 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16138 } else if r != 0.0 && x != libm::truncf(x) {
16139 let bits = r.to_bits();
16140 if (bits & 0x7f800000) == 0 {
16141 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16142 }
16143 }
16144 r
16145}
16146
16147#[no_mangle]
16148pub unsafe extern "C" fn expm1f(x: f32) -> f32 {
16149 libm::expm1f(x)
16150}
16151
16152#[no_mangle]
16153pub unsafe extern "C" fn log1pf(x: f32) -> f32 {
16154 if x == -1.0 {
16155 feraiseexcept(FE_DIVBYZERO);
16156 return f32::NEG_INFINITY;
16157 }
16158 libm::log1pf(x)
16159}
16160
16161#[no_mangle]
16162pub unsafe extern "C" fn acoshf(x: f32) -> f32 {
16163 if x < 1.0 {
16164 feraiseexcept(FE_INVALID);
16165 return f32::NAN;
16166 }
16167 libm::acoshf(x)
16168}
16169
16170#[no_mangle]
16171pub unsafe extern "C" fn asinhf(x: f32) -> f32 {
16172 if x == 0.0 { return x; }
16173 libm::asinhf(x)
16174}
16175
16176#[no_mangle]
16177pub unsafe extern "C" fn atanhf(x: f32) -> f32 {
16178 if x == 0.0 { return x; }
16179 let e = ((x.to_bits() >> 23) & 0xff) as i32;
16180 if e < 0x7f - 32 {
16181 feraiseexcept(FE_INEXACT);
16182 if e == 0 { feraiseexcept(FE_UNDERFLOW); }
16183 return x;
16184 }
16185 if x == 1.0 {
16186 feraiseexcept(FE_DIVBYZERO);
16187 return f32::INFINITY;
16188 }
16189 if x == -1.0 {
16190 feraiseexcept(FE_DIVBYZERO);
16191 return f32::NEG_INFINITY;
16192 }
16193 if x.is_nan() { return x; }
16194 let ax = libm::fabsf(x);
16195 if ax > 1.0 {
16196 feraiseexcept(FE_INVALID);
16197 return f32::NAN;
16198 }
16199 if ax < 0.5 {
16200 let r = libm::log1pf(2.0 * (ax + ax * ax / (1.0 - ax))) / 2.0;
16201 if x < 0.0 { -r } else { r }
16202 } else {
16203 let r = 0.5 * libm::logf((1.0 + ax) / (1.0 - ax));
16204 if x < 0.0 { -r } else { r }
16205 }
16206}
16207
16208#[no_mangle]
16209pub unsafe extern "C" fn cbrtf(x: f32) -> f32 {
16210 libm::cbrtf(x)
16211}
16212
16213#[no_mangle]
16214pub unsafe extern "C" fn erff(x: f32) -> f32 {
16215 libm::erff(x)
16216}
16217
16218#[no_mangle]
16219pub unsafe extern "C" fn erfcf(x: f32) -> f32 {
16220 libm::erfcf(x)
16221}
16222
16223#[no_mangle]
16224pub unsafe extern "C" fn lgammaf(x: f32) -> f32 {
16225 if x.is_nan() {
16226 crate::signgam = 1;
16227 return x;
16228 }
16229 if x == 0.0 {
16230 crate::signgam = if x.is_sign_negative() { -1 } else { 1 };
16231 feraiseexcept(FE_DIVBYZERO);
16232 return f32::INFINITY;
16233 }
16234 let (r, sign) = libm::lgammaf_r(x);
16235 crate::signgam = sign;
16236 r
16237}
16238
16239#[no_mangle]
16240pub unsafe extern "C" fn tgammaf(x: f32) -> f32 {
16241 if x.is_nan() { return x; }
16242 if x == 0.0 {
16243 feraiseexcept(FE_DIVBYZERO);
16244 return if x.is_sign_negative() { f32::NEG_INFINITY } else { f32::INFINITY };
16245 }
16246 if x.is_infinite() {
16247 return if x.is_sign_negative() { __math_invalidf(x) } else { f32::INFINITY };
16248 }
16249 if x < 0.0 && x == libm::floorf(x) {
16250 feraiseexcept(FE_INVALID);
16251 return f32::NAN;
16252 }
16253 libm::tgammaf(x)
16254}
16255
16256#[no_mangle]
16257pub unsafe extern "C" fn lroundf(x: f32) -> core::ffi::c_long {
16258 libm::roundf(x) as core::ffi::c_long
16259}
16260
16261#[no_mangle]
16262pub unsafe extern "C" fn llroundf(x: f32) -> i64 {
16263 libm::roundf(x) as i64
16264}
16265
16266#[no_mangle]
16271pub unsafe extern "C" fn wcscasecmp(s1: *const u32, s2: *const u32) -> i32 {
16272 let mut i = 0;
16273 loop {
16274 let c1 = *s1.add(i);
16275 let c2 = *s2.add(i);
16276 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16277 let l1 = if c1 >= 'A' as u32 && c1 <= 'Z' as u32 { c1 + 32 } else { c1 };
16278 let l2 = if c2 >= 'A' as u32 && c2 <= 'Z' as u32 { c2 + 32 } else { c2 };
16279 if l1 != l2 { return (l1 as i32) - (l2 as i32); }
16280 i += 1;
16281 }
16282}
16283
16284#[no_mangle]
16285pub unsafe extern "C" fn wcscasecmp_l(s1: *const u32, s2: *const u32, _loc: *mut core::ffi::c_void) -> i32 {
16286 wcscasecmp(s1, s2)
16287}
16288
16289#[no_mangle]
16290pub unsafe extern "C" fn wcsncasecmp(s1: *const u32, s2: *const u32, n: usize) -> i32 {
16291 let mut i = 0;
16292 while i < n {
16293 let c1 = *s1.add(i);
16294 let c2 = *s2.add(i);
16295 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16296 let l1 = if c1 >= 'A' as u32 && c1 <= 'Z' as u32 { c1 + 32 } else { c1 };
16297 let l2 = if c2 >= 'A' as u32 && c2 <= 'Z' as u32 { c2 + 32 } else { c2 };
16298 if l1 != l2 { return (l1 as i32) - (l2 as i32); }
16299 i += 1;
16300 }
16301 0
16302}
16303
16304#[no_mangle]
16305pub unsafe extern "C" fn wcsncasecmp_l(s1: *const u32, s2: *const u32, n: usize, _loc: *mut core::ffi::c_void) -> i32 {
16306 wcsncasecmp(s1, s2, n)
16307}
16308
16309#[no_mangle]
16310pub unsafe extern "C" fn wcscoll(s1: *const u32, s2: *const u32) -> i32 {
16311 let mut i = 0;
16313 loop {
16314 let c1 = *s1.add(i);
16315 let c2 = *s2.add(i);
16316 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16317 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
16318 i += 1;
16319 }
16320}
16321
16322#[no_mangle]
16323pub unsafe extern "C" fn wcstok(s: *mut u32, sep: *const u32, p: *mut *mut u32) -> *mut u32 {
16324 let mut src = if s.is_null() { *p } else { s };
16325 while *src != 0 && *sep.add(0) == *src { src = src.add(1); }
16327 if *src == 0 { return core::ptr::null_mut(); }
16328 let start = src;
16329 while *src != 0 && *sep.add(0) != *src { src = src.add(1); }
16331 if *src != 0 {
16332 *src = 0;
16333 *p = src.add(1);
16334 } else {
16335 *p = src;
16336 }
16337 start
16338}
16339
16340#[no_mangle]
16341pub unsafe extern "C" fn wcswcs(haystack: *const u32, needle: *const u32) -> *mut u32 {
16342 if *needle == 0 { return haystack as *mut u32; }
16343 let mut i = 0;
16344 while *haystack.add(i) != 0 {
16345 let mut j = 0;
16346 while *needle.add(j) != 0 && *haystack.add(i + j) == *needle.add(j) {
16347 j += 1;
16348 }
16349 if *needle.add(j) == 0 { return haystack.add(i) as *mut u32; }
16350 i += 1;
16351 }
16352 core::ptr::null_mut()
16353}
16354
16355#[no_mangle]
16356pub unsafe extern "C" fn wcswidth(s: *const u32, n: usize) -> i32 {
16357 let mut width = 0i32;
16358 let mut i = 0;
16359 while i < n {
16360 let c = *s.add(i);
16361 if c == 0 { break; }
16362 width += 1;
16364 i += 1;
16365 }
16366 width
16367}
16368
16369#[no_mangle]
16370pub unsafe extern "C" fn wcsftime(s: *mut u32, maxsize: usize, fmt: *const u32, tm: *const c_void) -> usize {
16371 if s.is_null() || fmt.is_null() || maxsize == 0 { return 0; }
16372 let mut cfmt = [0u8; 1024];
16375 let mut o = 0usize;
16376 let mut i = 0usize;
16377 let mut st: c_uint = 0;
16378 while *fmt.add(i) != 0 && o + 8 < cfmt.len() {
16379 let n = wcrtomb(
16380 cfmt.as_mut_ptr().add(o) as *mut c_char,
16381 *fmt.add(i) as c_int,
16382 &mut st as *mut c_uint,
16383 );
16384 if n == !0usize { return 0; }
16385 o += n;
16386 i += 1;
16387 }
16388 cfmt[o] = 0;
16389 let mut out = [0u8; 4096];
16390 let mut lim = maxsize.saturating_mul(4);
16391 if lim > out.len() { lim = out.len(); }
16392 let n = strftime(out.as_mut_ptr() as *mut c_char, lim, cfmt.as_ptr() as *const c_char, tm as *const tm);
16393 if n == 0 { return 0; }
16394 let mut ws = 0usize;
16395 let mut p = 0usize;
16396 while p < n && ws + 1 < maxsize {
16397 let mut wc: c_int = 0;
16398 let mut st2: c_uint = 0;
16399 let r = mbrtowc(&mut wc, out.as_ptr().add(p) as *const c_char, n - p, &mut st2);
16400 if r == !0usize { return 0; }
16401 if r == 0 || r == !1usize { break; }
16402 *s.add(ws) = wc as u32;
16403 ws += 1;
16404 p += r;
16405 }
16406 *s.add(ws) = 0;
16407 ws
16408}
16409
16410#[no_mangle]
16411pub unsafe extern "C" fn mbsnrtowcs(
16412 dst: *mut u32,
16413 src: *mut *const u8,
16414 nms: usize,
16415 len: usize,
16416 st: *mut core::ffi::c_void,
16417) -> usize {
16418 if src.is_null() { return 0; }
16419 let mut s = *src;
16420 if s.is_null() { return 0; }
16421 let state = st as *mut c_uint;
16422 let limit = if dst.is_null() { usize::MAX } else { len };
16423 let mut count = 0usize;
16424 let mut n = nms;
16425 while count < limit && n > 0 {
16426 let c = *s;
16427 if c == 0 {
16428 if !dst.is_null() {
16429 if count < len { *dst.add(count) = 0; }
16430 *src = core::ptr::null();
16431 }
16432 return count;
16433 }
16434 let mut wc: c_int = 0;
16435 let r = mbrtowc(&mut wc, s as *const c_char, n, state);
16436 if r == !0usize {
16437 *src = s;
16438 return !0usize;
16439 }
16440 if r == !1usize { break; }
16441 if !dst.is_null() { *dst.add(count) = wc as u32; }
16442 count += 1;
16443 s = s.add(r);
16444 n -= r;
16445 }
16446 *src = s;
16447 count
16448}
16449
16450#[no_mangle]
16451pub unsafe extern "C" fn wcsnrtombs(dst: *mut u8, src: *mut *const u32, nwc: usize, len: usize, _st: *mut core::ffi::c_void) -> usize {
16452 let mut count = 0;
16453 let mut s = *src;
16454 let mut d = dst;
16455 while count < len && count < nwc {
16456 let c = *s;
16457 if c == 0 { break; }
16458 if !d.is_null() {
16459 if c < 0x80 {
16460 *d = c as u8;
16461 d = d.add(1);
16462 count += 1;
16463 } else if c < 0x800 {
16464 if count + 2 > len { break; }
16465 *d = 0xc0 | (c >> 6) as u8;
16466 *d.add(1) = 0x80 | (c & 0x3f) as u8;
16467 d = d.add(2);
16468 count += 2;
16469 } else if c < 0x10000 {
16470 if count + 3 > len { break; }
16471 *d = 0xe0 | (c >> 12) as u8;
16472 *d.add(1) = 0x80 | ((c >> 6) & 0x3f) as u8;
16473 *d.add(2) = 0x80 | (c & 0x3f) as u8;
16474 d = d.add(3);
16475 count += 3;
16476 } else {
16477 if count + 4 > len { break; }
16478 *d = 0xf0 | (c >> 18) as u8;
16479 *d.add(1) = 0x80 | ((c >> 12) & 0x3f) as u8;
16480 *d.add(2) = 0x80 | ((c >> 6) & 0x3f) as u8;
16481 *d.add(3) = 0x80 | (c & 0x3f) as u8;
16482 d = d.add(4);
16483 count += 4;
16484 }
16485 }
16486 s = s.add(1);
16487 }
16488 if !dst.is_null() { *src = s; }
16489 count
16490}
16491
16492pub type thrd_start_t = Option<unsafe extern "C" fn(arg: *mut core::ffi::c_void) -> i32>;
16499
16500#[no_mangle]
16502pub unsafe extern "C" fn thrd_create(thr: *mut usize, func: thrd_start_t, arg: *mut core::ffi::c_void) -> i32 {
16503 let mut thread: u64 = 0;
16504 let r = pthread_create(&mut thread, core::ptr::null(), core::mem::transmute(func), arg);
16505 if r == 0 {
16506 *thr = thread as usize;
16507 0 } else {
16509 -1 }
16511}
16512
16513#[no_mangle]
16514pub unsafe extern "C" fn thrd_join(thr: usize, res: *mut i32) -> i32 {
16515 let mut retval: *mut core::ffi::c_void = core::ptr::null_mut();
16516 let r = pthread_join(thr as u64, &mut retval);
16517 if r == 0 {
16518 if !res.is_null() { *res = retval as i32; }
16519 0
16520 } else {
16521 -1
16522 }
16523}
16524
16525#[no_mangle]
16526pub unsafe extern "C" fn thrd_exit(res: i32) {
16527 pthread_exit(res as *mut core::ffi::c_void);
16528}
16529
16530#[no_mangle]
16531pub unsafe extern "C" fn thrd_detach(thr: usize) -> i32 {
16532 let r = pthread_detach(thr as u64);
16533 if r == 0 { 0 } else { -1 }
16534}
16535
16536#[no_mangle]
16537pub unsafe extern "C" fn thrd_current() -> usize {
16538 pthread_self() as usize
16539}
16540
16541#[no_mangle]
16542pub unsafe extern "C" fn thrd_equal(thr1: usize, thr2: usize) -> i32 {
16543 (thr1 == thr2) as i32
16544}
16545
16546#[no_mangle]
16547pub unsafe extern "C" fn thrd_sleep(duration: *const core::ffi::c_void, remaining: *mut core::ffi::c_void) -> i32 {
16548 nanosleep(duration as *const timespec, remaining as *mut timespec)
16549}
16550
16551#[no_mangle]
16552pub unsafe extern "C" fn thrd_yield() {
16553 sched_yield();
16554}
16555
16556#[no_mangle]
16558pub unsafe extern "C" fn mtx_init(mtx: *mut usize, _mtx_type: i32) -> i32 {
16559 let r = pthread_mutex_init(mtx as *mut pthread_mutex_t, core::ptr::null());
16560 if r == 0 { 0 } else { -1 }
16561}
16562
16563#[no_mangle]
16564pub unsafe extern "C" fn mtx_lock(mtx: *mut usize) -> i32 {
16565 let r = pthread_mutex_lock(mtx as *mut pthread_mutex_t);
16566 if r == 0 { 0 } else { -1 }
16567}
16568
16569#[no_mangle]
16570pub unsafe extern "C" fn mtx_trylock(mtx: *mut usize) -> i32 {
16571 let r = pthread_mutex_trylock(mtx as *mut pthread_mutex_t);
16572 if r == 0 { 0 } else { -1 }
16573}
16574
16575#[no_mangle]
16576pub unsafe extern "C" fn mtx_unlock(mtx: *mut usize) -> i32 {
16577 let r = pthread_mutex_unlock(mtx as *mut pthread_mutex_t);
16578 if r == 0 { 0 } else { -1 }
16579}
16580
16581#[no_mangle]
16582pub unsafe extern "C" fn mtx_destroy(mtx: *mut usize) {
16583 pthread_mutex_destroy(mtx as *mut pthread_mutex_t);
16584}
16585
16586#[no_mangle]
16587pub unsafe extern "C" fn mtx_timedlock(mtx: *mut usize, ts: *const core::ffi::c_void) -> i32 {
16588 let r = pthread_mutex_timedlock(mtx as *mut pthread_mutex_t, ts as *const timespec);
16589 if r == 0 { 0 } else { -1 }
16590}
16591
16592#[no_mangle]
16594pub unsafe extern "C" fn cnd_init(cnd: *mut usize) -> i32 {
16595 let r = pthread_cond_init(cnd as *mut pthread_cond_t, core::ptr::null());
16596 if r == 0 { 0 } else { -1 }
16597}
16598
16599#[no_mangle]
16600pub unsafe extern "C" fn cnd_signal(cnd: *mut usize) -> i32 {
16601 let r = pthread_cond_signal(cnd as *mut pthread_cond_t);
16602 if r == 0 { 0 } else { -1 }
16603}
16604
16605#[no_mangle]
16606pub unsafe extern "C" fn cnd_broadcast(cnd: *mut usize) -> i32 {
16607 let r = pthread_cond_broadcast(cnd as *mut pthread_cond_t);
16608 if r == 0 { 0 } else { -1 }
16609}
16610
16611#[no_mangle]
16612pub unsafe extern "C" fn cnd_wait(cnd: *mut usize, mtx: *mut usize) -> i32 {
16613 let r = pthread_cond_wait(cnd as *mut pthread_cond_t, mtx as *mut pthread_mutex_t);
16614 if r == 0 { 0 } else { -1 }
16615}
16616
16617#[no_mangle]
16618pub unsafe extern "C" fn cnd_timedwait(cnd: *mut usize, mtx: *mut usize, ts: *const core::ffi::c_void) -> i32 {
16619 let r = pthread_cond_timedwait(cnd as *mut pthread_cond_t, mtx as *mut pthread_mutex_t, ts as *const timespec);
16620 if r == 0 { 0 } else { -1 }
16621}
16622
16623#[no_mangle]
16624pub unsafe extern "C" fn cnd_destroy(cnd: *mut usize) {
16625 pthread_cond_destroy(cnd as *mut pthread_cond_t);
16626}
16627
16628#[no_mangle]
16630pub unsafe extern "C" fn tss_create(key: *mut u32, dtor: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>) -> i32 {
16631 let r = pthread_key_create(key, dtor);
16632 if r == 0 { 0 } else { -1 }
16633}
16634
16635#[no_mangle]
16636pub unsafe extern "C" fn tss_delete(key: u32) {
16637 pthread_key_delete(key);
16638}
16639
16640#[no_mangle]
16641pub unsafe extern "C" fn tss_set(key: u32, val: *mut core::ffi::c_void) -> i32 {
16642 let r = pthread_setspecific(key, val);
16643 if r == 0 { 0 } else { -1 }
16644}
16645
16646#[no_mangle]
16647pub unsafe extern "C" fn tss_get(key: u32) -> *mut core::ffi::c_void {
16648 pthread_getspecific(key)
16649}
16650
16651#[no_mangle]
16653pub unsafe extern "C" fn call_once(flag: *mut u32, func: Option<unsafe extern "C" fn()>) {
16654 if *flag == 0 {
16655 if let Some(f) = func { f(); }
16656 *flag = 1;
16657 }
16658}
16659
16660#[no_mangle]
16666pub unsafe extern "C" fn accept4(fd: i32, addr: *mut core::ffi::c_void, addrlen: *mut u32, flags: i32) -> i32 {
16667 <Arch as Syscalls>::syscall4(SYS_ACCEPT4, fd as i64, addr as i64, addrlen as i64, flags as i64) as i32
16668}
16669
16670#[no_mangle]
16676pub unsafe extern "C" fn epoll_create(size: i32) -> i32 {
16677 #[cfg(target_arch = "x86_64")]
16678 { <Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE, size as i64) as i32 }
16679 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
16680 {
16681 if size < 1 {
16682 ERRNO = EINVAL;
16683 return -1;
16684 }
16685 <Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE1, 0) as i32
16686 }
16687}
16688
16689#[no_mangle]
16690pub unsafe extern "C" fn epoll_create1(flags: i32) -> i32 {
16691 <Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE1, flags as i64) as i32
16692}
16693
16694#[no_mangle]
16695pub unsafe extern "C" fn epoll_ctl(epfd: i32, op: i32, fd: i32, event: *mut core::ffi::c_void) -> i32 {
16696 <Arch as Syscalls>::syscall4(SYS_EPOLL_CTL, epfd as i64, op as i64, fd as i64, event as i64) as i32
16697}
16698
16699#[no_mangle]
16700pub unsafe extern "C" fn epoll_wait(epfd: i32, events: *mut core::ffi::c_void, maxevents: i32, timeout: i32) -> i32 {
16701 <Arch as Syscalls>::syscall4(SYS_EPOLL_WAIT, epfd as i64, events as i64, maxevents as i64, timeout as i64) as i32
16702}
16703
16704#[no_mangle]
16705pub unsafe extern "C" fn epoll_pwait(epfd: i32, events: *mut core::ffi::c_void, maxevents: i32, timeout: i32, sigmask: *const u64) -> i32 {
16706 <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
16707}
16708
16709#[no_mangle]
16710pub unsafe extern "C" fn eventfd(initval: u32, flags: i32) -> i32 {
16711 <Arch as Syscalls>::syscall2(SYS_EVENTFD2, initval as i64, flags as i64) as i32
16712}
16713
16714#[no_mangle]
16715pub unsafe extern "C" fn eventfd_read(fd: i32, value: *mut u64) -> i32 {
16716 let n = crate::read(fd, value as *mut core::ffi::c_void, 8);
16717 if n == 8 { 0 } else { -1 }
16718}
16719
16720#[no_mangle]
16721pub unsafe extern "C" fn eventfd_write(fd: i32, value: u64) -> i32 {
16722 let n = crate::write(fd, &value as *const u64 as *const core::ffi::c_void, 8);
16723 if n == 8 { 0 } else { -1 }
16724}
16725
16726#[no_mangle]
16727pub unsafe extern "C" fn signalfd(fd: i32, mask: *const u64, flags: i32) -> i32 {
16728 <Arch as Syscalls>::syscall4(SYS_SIGNALFD4, fd as i64, mask as i64, 8, flags as i64) as i32
16729}
16730
16731#[no_mangle]
16732pub unsafe extern "C" fn timerfd_create(clockid: i32, flags: i32) -> i32 {
16733 <Arch as Syscalls>::syscall2(SYS_TIMERFD_CREATE, clockid as i64, flags as i64) as i32
16734}
16735
16736#[no_mangle]
16737pub 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 {
16738 <Arch as Syscalls>::syscall4(SYS_TIMERFD_SETTIME, fd as i64, flags as i64, new_value as i64, old_value as i64) as i32
16739}
16740
16741#[no_mangle]
16742pub unsafe extern "C" fn timerfd_gettime(fd: i32, curr_value: *mut core::ffi::c_void) -> i32 {
16743 <Arch as Syscalls>::syscall2(SYS_TIMERFD_GETTIME, fd as i64, curr_value as i64) as i32
16744}
16745
16746#[no_mangle]
16751pub unsafe extern "C" fn prctl(option: i32, mut args: ...) -> i32 {
16752 let a1 = args.next_arg::<i64>();
16753 let a2 = args.next_arg::<i64>();
16754 let a3 = args.next_arg::<i64>();
16755 let a4 = args.next_arg::<i64>();
16756 <Arch as Syscalls>::syscall5(SYS_PRCTL, option as i64, a1, a2, a3, a4) as i32
16757}
16758
16759#[no_mangle]
16760pub unsafe extern "C" fn quotactl(cmd: i32, special: *const core::ffi::c_char, id: i32, addr: *mut core::ffi::c_char) -> i32 {
16761 <Arch as Syscalls>::syscall4(sysno(179, 60), cmd as i64, special as i64, id as i64, addr as i64) as i32
16762}
16763
16764#[no_mangle]
16765pub unsafe extern "C" fn klogctl(type_: i32, bufp: *mut core::ffi::c_char, len: i32) -> i32 {
16766 <Arch as Syscalls>::syscall3(sysno(103, 116), type_ as i64, bufp as i64, len as i64) as i32
16767}
16768
16769static mut SYSLOG_IDENT: [core::ffi::c_char; 64] = [0; 64];
16770static mut SYSLOG_OPTIONS: i32 = 0;
16771static mut SYSLOG_FACILITY: i32 = 1;
16772
16773#[no_mangle]
16774pub unsafe extern "C" fn openlog(ident: *const core::ffi::c_char, option: i32, facility: i32) {
16775 SYSLOG_OPTIONS = option;
16776 SYSLOG_FACILITY = facility & 0x3f8;
16777 SYSLOG_IDENT[0] = 0;
16778 if !ident.is_null() {
16779 let mut i = 0;
16780 while i < 63 && *ident.add(i) != 0 {
16781 SYSLOG_IDENT[i] = *ident.add(i);
16782 i += 1;
16783 }
16784 SYSLOG_IDENT[i] = 0;
16785 }
16786}
16787
16788#[repr(C)]
16789struct SockAddrUn {
16790 sun_family: u16,
16791 sun_path: [core::ffi::c_char; 108],
16792}
16793
16794unsafe fn syslog_emit(priority: i32, msg: *const core::ffi::c_char, len: usize) {
16795 let mut out = [0u8; 1200];
16796 let mut o = 0usize;
16797 let pri = (SYSLOG_FACILITY | (priority & 7)) as u32;
16798 out[o] = b'<'; o += 1;
16799 if pri >= 100 { out[o] = b'0' + (pri / 100) as u8; o += 1; }
16800 if pri >= 10 { out[o] = b'0' + ((pri / 10) % 10) as u8; o += 1; }
16801 out[o] = b'0' + (pri % 10) as u8; o += 1;
16802 out[o] = b'>'; o += 1;
16803 let mut i = 0;
16804 while i < 63 && SYSLOG_IDENT[i] != 0 && o + 1 < out.len() {
16805 out[o] = SYSLOG_IDENT[i] as u8; o += 1; i += 1;
16806 }
16807 if SYSLOG_OPTIONS & 1 != 0 {
16808 out[o] = b'['; o += 1;
16809 let mut pid = crate::getpid() as u32;
16810 let mut digits = [0u8; 10];
16811 let mut d = 0;
16812 if pid == 0 { digits[0] = b'0'; d = 1; }
16813 while pid > 0 { digits[d] = b'0' + (pid % 10) as u8; pid /= 10; d += 1; }
16814 while d > 0 { d -= 1; out[o] = digits[d]; o += 1; }
16815 out[o] = b']'; o += 1;
16816 }
16817 out[o] = b':'; o += 1; out[o] = b' '; o += 1;
16818 let copy = core::cmp::min(len, out.len() - o - 1);
16819 core::ptr::copy_nonoverlapping(msg as *const u8, out.as_mut_ptr().add(o), copy);
16820 o += copy;
16821 let fd = crate::socket(AF_UNIX, SOCK_DGRAM, 0);
16822 if fd >= 0 {
16823 let mut sa: SockAddrUn = core::mem::zeroed();
16824 sa.sun_family = AF_UNIX as u16;
16825 let path = b"/dev/log";
16826 for i in 0..path.len() { sa.sun_path[i] = path[i] as core::ffi::c_char; }
16827 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);
16828 crate::close(fd);
16829 if r >= 0 { return; }
16830 }
16831 crate::write(2, out.as_ptr() as *const core::ffi::c_void, o);
16832 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
16833}
16834
16835#[no_mangle]
16836pub unsafe extern "C" fn vsyslog(priority: c_int, fmt: *const c_char, ap: VaList) {
16837 let mut msg = [0 as c_char; 1024];
16838 let n = vsnprintf(msg.as_mut_ptr(), msg.len(), fmt, ap);
16839 if n > 0 { syslog_emit(priority, msg.as_ptr(), core::cmp::min(n as usize, msg.len() - 1)); }
16840}
16841
16842#[no_mangle]
16843pub unsafe extern "C" fn syslog(priority: c_int, fmt: *const c_char, args: ...) {
16844 vsyslog(priority, fmt, args);
16845}
16846
16847#[no_mangle]
16848pub unsafe extern "C" fn closelog() {
16849 }
16851
16852#[no_mangle]
16853pub unsafe extern "C" fn setlogmask(mask: i32) -> i32 {
16854 static mut LOG_MASK: i32 = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80;
16855 let old = LOG_MASK;
16856 if mask != 0 { LOG_MASK = mask; }
16857 old
16858}
16859
16860#[no_mangle]
16861pub unsafe extern "C" fn acct(filename: *const core::ffi::c_char) -> i32 {
16862 <Arch as Syscalls>::syscall1(SYS_ACCT, filename as i64) as i32
16863}
16864
16865#[no_mangle]
16866pub unsafe extern "C" fn swapon(path: *const core::ffi::c_char, flags: i32) -> i32 {
16867 <Arch as Syscalls>::syscall2(SYS_SWAPON, path as i64, flags as i64) as i32
16868}
16869
16870#[no_mangle]
16871pub unsafe extern "C" fn swapoff(path: *const core::ffi::c_char) -> i32 {
16872 <Arch as Syscalls>::syscall1(SYS_SWAPOFF, path as i64) as i32
16873}
16874
16875#[no_mangle]
16876pub unsafe extern "C" fn syncfs(fd: i32) -> i32 {
16877 <Arch as Syscalls>::syscall1(SYS_SYNCFS, fd as i64) as i32
16878}
16879
16880#[no_mangle]
16881pub unsafe extern "C" fn sync_file_range(fd: i32, offset: i64, nbytes: u64, flags: u32) -> i32 {
16882 <Arch as Syscalls>::syscall4(sysno(277, 84), fd as i64, offset, nbytes as i64, flags as i64) as i32
16883}
16884
16885#[no_mangle]
16886pub unsafe extern "C" fn posix_fadvise(fd: i32, offset: i64, len: u64, advice: i32) -> i32 {
16887 <Arch as Syscalls>::syscall4(sysno(221, 223), fd as i64, offset, len as i64, advice as i64) as i32
16888}
16889
16890#[no_mangle]
16891pub unsafe extern "C" fn posix_fallocate(fd: i32, offset: i64, len: u64) -> i32 {
16892 <Arch as Syscalls>::syscall3(SYS_FALLOCATE, fd as i64, offset, len as i64) as i32
16893}
16894
16895#[no_mangle]
16896pub unsafe extern "C" fn readahead(fd: i32, offset: i64, count: usize) -> i32 {
16897 <Arch as Syscalls>::syscall3(sysno(187, 213), fd as i64, offset, count as i64) as i32
16898}
16899
16900#[no_mangle]
16901pub unsafe extern "C" fn fallocate(fd: i32, mode: i32, offset: i64, len: u64) -> i32 {
16902 <Arch as Syscalls>::syscall4(SYS_FALLOCATE, fd as i64, mode as i64, offset, len as i64) as i32
16903}
16904
16905#[no_mangle]
16910pub unsafe extern "C" fn tcgetattr(fd: i32, termios_p: *mut core::ffi::c_void) -> i32 {
16911 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5401, termios_p as i64) as i32
16912}
16913
16914#[no_mangle]
16915pub unsafe extern "C" fn tcsetattr(fd: i32, optional_actions: i32, termios_p: *const core::ffi::c_void) -> i32 {
16916 let cmd = match optional_actions {
16917 0 => 0x5402,
16918 1 => 0x5403,
16919 2 => 0x5404,
16920 _ => 0x5402,
16921 };
16922 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, cmd, termios_p as i64) as i32
16923}
16924
16925#[no_mangle]
16926pub unsafe extern "C" fn tcdrain(fd: i32) -> i32 {
16927 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5409, 1) as i32
16928}
16929
16930#[no_mangle]
16931pub unsafe extern "C" fn tcflush(fd: i32, queue_selector: i32) -> i32 {
16932 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540B, queue_selector as i64) as i32
16933}
16934
16935#[no_mangle]
16936pub unsafe extern "C" fn tcflow(fd: i32, action: i32) -> i32 {
16937 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540A, action as i64) as i32
16938}
16939
16940#[no_mangle]
16941pub unsafe extern "C" fn tcsendbreak(fd: i32, duration: i32) -> i32 {
16942 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5425, duration as i64) as i32
16943}
16944
16945#[no_mangle]
16946pub unsafe extern "C" fn tcgetsid(fd: i32) -> i32 {
16947 let mut sid: i32 = 0;
16948 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5429, &mut sid as *mut i32 as i64);
16949 if r < 0 { -1 } else { sid }
16950}
16951
16952#[no_mangle]
16953pub unsafe extern "C" fn tcgetpgrp(fd: i32) -> i32 {
16954 let mut pgrp: i32 = 0;
16955 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540F, &mut pgrp as *mut i32 as i64);
16956 if r < 0 { -1 } else { pgrp }
16957}
16958
16959#[no_mangle]
16960pub unsafe extern "C" fn tcsetpgrp(fd: i32, pgrp: i32) -> i32 {
16961 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5410, &pgrp as *const i32 as i64) as i32
16962}
16963
16964#[no_mangle]
16975pub unsafe extern "C" fn mq_open(name: *const core::ffi::c_char, oflag: i32, _args: ...) -> i64 {
16976 crate::open(name, oflag, 0) as i64
16977}
16978
16979#[no_mangle]
16980pub unsafe extern "C" fn mq_close(mqdes: i64) -> i32 {
16981 crate::close(mqdes as i32)
16982}
16983
16984#[no_mangle]
16985pub unsafe extern "C" fn mq_unlink(name: *const core::ffi::c_char) -> i32 {
16986 crate::unlink(name)
16987}
16988
16989#[no_mangle]
16990pub unsafe extern "C" fn mq_send(mqdes: i64, msg_ptr: *const core::ffi::c_char, msg_len: usize, _msg_prio: u32) -> i32 {
16991 let r = crate::write(mqdes as i32, msg_ptr as *const core::ffi::c_void, msg_len) as i32;
16992 if r >= 0 { mq_notify_fire(mqdes); }
16993 r
16994}
16995
16996#[no_mangle]
16997pub unsafe extern "C" fn mq_receive(mqdes: i64, msg_ptr: *mut core::ffi::c_char, msg_len: usize, _msg_prio: *mut u32) -> isize {
16998 crate::read(mqdes as i32, msg_ptr as *mut core::ffi::c_void, msg_len)
16999}
17000
17001#[no_mangle]
17002pub 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 {
17003 mq_send(mqdes, msg_ptr, msg_len, msg_prio)
17004}
17005
17006#[no_mangle]
17007pub 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 {
17008 mq_receive(mqdes, msg_ptr, msg_len, msg_prio)
17009}
17010
17011#[no_mangle]
17016pub unsafe extern "C" fn pthread_getaffinity_np(thread: usize, cpusetsize: usize, cpuset: *mut u8) -> i32 {
17017 sched_getaffinity(thread as i32, cpusetsize, cpuset)
17018}
17019
17020#[no_mangle]
17021pub unsafe extern "C" fn pthread_setaffinity_np(thread: usize, cpusetsize: usize, cpuset: *const u8) -> i32 {
17022 sched_setaffinity(thread as i32, cpusetsize, cpuset)
17023}
17024
17025#[no_mangle]
17030pub unsafe extern "C" fn sched_yield() -> i32 {
17031 <Arch as Syscalls>::syscall0(sysno(24, 124)) as i32
17032}
17033
17034#[no_mangle]
17035pub unsafe extern "C" fn sched_get_priority_max(policy: i32) -> i32 {
17036 <Arch as Syscalls>::syscall1(sysno(146, 125), policy as i64) as i32
17037}
17038
17039#[no_mangle]
17040pub unsafe extern "C" fn sched_get_priority_min(policy: i32) -> i32 {
17041 <Arch as Syscalls>::syscall1(sysno(147, 126), policy as i64) as i32
17042}
17043
17044#[no_mangle]
17045pub unsafe extern "C" fn sched_getparam(pid: i32, param: *mut core::ffi::c_void) -> i32 {
17046 <Arch as Syscalls>::syscall2(sysno(143, 121), pid as i64, param as i64) as i32
17047}
17048
17049#[no_mangle]
17050pub unsafe extern "C" fn sched_setparam(pid: i32, param: *const core::ffi::c_void) -> i32 {
17051 <Arch as Syscalls>::syscall2(sysno(142, 118), pid as i64, param as i64) as i32
17052}
17053
17054#[no_mangle]
17055pub unsafe extern "C" fn sched_getscheduler(pid: i32) -> i32 {
17056 <Arch as Syscalls>::syscall1(sysno(145, 120), pid as i64) as i32
17057}
17058
17059#[no_mangle]
17060pub unsafe extern "C" fn sched_setscheduler(pid: i32, policy: i32, param: *const core::ffi::c_void) -> i32 {
17061 <Arch as Syscalls>::syscall3(sysno(144, 119), pid as i64, policy as i64, param as i64) as i32
17062}
17063
17064#[no_mangle]
17065pub unsafe extern "C" fn sched_setaffinity(pid: i32, cpusetsize: usize, cpuset: *const u8) -> i32 {
17066 <Arch as Syscalls>::syscall3(sysno(203, 122), pid as i64, cpusetsize as i64, cpuset as i64) as i32
17067}
17068
17069#[no_mangle]
17070pub unsafe extern "C" fn sched_getaffinity(pid: i32, cpusetsize: usize, cpuset: *mut u8) -> i32 {
17071 <Arch as Syscalls>::syscall3(sysno(204, 123), pid as i64, cpusetsize as i64, cpuset as i64) as i32
17072}
17073
17074#[no_mangle]
17075pub unsafe extern "C" fn sched_getcpu() -> i32 {
17076 let mut cpu: i32 = 0;
17077 <Arch as Syscalls>::syscall3(sysno(309, 168), &mut cpu as *mut i32 as i64, 0, 0);
17078 cpu
17079}
17080
17081#[no_mangle]
17082pub unsafe extern "C" fn sched_rr_get_interval(pid: i32, tp: *mut core::ffi::c_void) -> i32 {
17083 <Arch as Syscalls>::syscall2(sysno(148, 127), pid as i64, tp as i64) as i32
17084}
17085
17086#[no_mangle]
17091pub unsafe extern "C" fn timer_create(clockid: i32, sevp: *mut core::ffi::c_void, timerid: *mut i32) -> i32 {
17092 <Arch as Syscalls>::syscall3(sysno(222, 107), clockid as i64, sevp as i64, timerid as i64) as i32
17093}
17094
17095#[no_mangle]
17096pub unsafe extern "C" fn timer_delete(timerid: i32) -> i32 {
17097 <Arch as Syscalls>::syscall1(sysno(226, 111), timerid as i64) as i32
17098}
17099
17100#[no_mangle]
17101pub 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 {
17102 <Arch as Syscalls>::syscall4(sysno(223, 110), timerid as i64, flags as i64, new_value as i64, old_value as i64) as i32
17103}
17104
17105#[no_mangle]
17106pub unsafe extern "C" fn timer_gettime(timerid: i32, curr_value: *mut core::ffi::c_void) -> i32 {
17107 <Arch as Syscalls>::syscall2(sysno(224, 108), timerid as i64, curr_value as i64) as i32
17108}
17109
17110#[no_mangle]
17111pub unsafe extern "C" fn timer_getoverrun(timerid: i32) -> i32 {
17112 <Arch as Syscalls>::syscall1(sysno(225, 109), timerid as i64) as i32
17113}
17114
17115#[no_mangle]
17116pub unsafe extern "C" fn clock_adjtime(_clockid: i32, buf: *mut core::ffi::c_void) -> i32 {
17117 <Arch as Syscalls>::syscall2(SYS_ADJTIMEX, buf as i64, 0) as i32
17118}
17119
17120#[no_mangle]
17121pub unsafe extern "C" fn clock_getcpuclockid(pid: i32, clockid: *mut i32) -> i32 {
17122 if clockid.is_null() { return EINVAL; }
17123 let id: i32 = ((-(pid as i64) - 1) * 8 + 2) as i32;
17124 let mut ts: timespec = core::mem::zeroed();
17125 let r = <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, id as i64, &mut ts as *mut timespec as i64);
17126 if r < 0 {
17127 let e = (-r) as c_int;
17128 return if e == EINVAL { 3 } else { e };
17129 }
17130 *clockid = id;
17131 0
17132}
17133
17134#[no_mangle]
17139pub unsafe extern "C" fn strcoll(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char) -> i32 {
17140 let mut i = 0;
17142 loop {
17143 let c1 = *s1.add(i) as u8;
17144 let c2 = *s2.add(i) as u8;
17145 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
17146 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
17147 i += 1;
17148 }
17149}
17150
17151#[no_mangle]
17152pub unsafe extern "C" fn strxfrm(dest: *mut core::ffi::c_char, src: *const core::ffi::c_char, n: usize) -> usize {
17153 let mut i = 0;
17154 while i < n {
17155 let c = *src.add(i);
17156 *dest.add(i) = c;
17157 if c == 0 { break; }
17158 i += 1;
17159 }
17160 i
17161}
17162
17163#[no_mangle]
17168pub 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 {
17169 let dir = opendir(dirp);
17170 if dir.is_null() { return -1; }
17171 let mut count = 0;
17172 loop {
17173 let ent = readdir(dir);
17174 if ent.is_null() { break; }
17175 count += 1;
17176 }
17177 closedir(dir);
17178 count
17179}
17180
17181#[no_mangle]
17182pub unsafe extern "C" fn alphasort(a: *const *const core::ffi::c_void, b: *const *const core::ffi::c_void) -> i32 {
17183 let s1 = *a as *const core::ffi::c_char;
17184 let s2 = *b as *const core::ffi::c_char;
17185 crate::strcmp(s1 as *const u8, s2 as *const u8)
17186}
17187
17188#[no_mangle]
17189pub unsafe extern "C" fn versionsort(a: *const *const core::ffi::c_void, b: *const *const core::ffi::c_void) -> i32 {
17190 let s1 = *a as *const core::ffi::c_char;
17191 let s2 = *b as *const core::ffi::c_char;
17192 crate::strcmp(s1 as *const u8, s2 as *const u8)
17193}
17194
17195unsafe fn vwarn_impl(fmt: *const c_char, ap: VaList, with_errno: bool) {
17203 let mut buf = [0 as c_char; 1024];
17204 let n = vsnprintf(buf.as_mut_ptr(), buf.len(), fmt, ap);
17205 if n > 0 {
17206 let l = core::cmp::min(n as usize, buf.len() - 1);
17207 crate::write(2, buf.as_ptr() as *const c_void, l);
17208 }
17209 if with_errno {
17210 let e = ERRNO;
17211 crate::write(2, b": ".as_ptr() as *const c_void, 2);
17212 let msg = strerror(e);
17213 crate::write(2, msg as *const c_void, crate::strlen(msg));
17214 }
17215 crate::write(2, b"\n".as_ptr() as *const c_void, 1);
17216}
17217
17218#[no_mangle]
17219pub unsafe extern "C" fn verr(eval: c_int, fmt: *const c_char, ap: VaList) {
17220 vwarn_impl(fmt, ap, true);
17221 crate::exit(eval);
17222}
17223
17224#[no_mangle]
17225pub unsafe extern "C" fn verrx(eval: c_int, fmt: *const c_char, ap: VaList) {
17226 vwarn_impl(fmt, ap, false);
17227 crate::exit(eval);
17228}
17229
17230#[no_mangle]
17231pub unsafe extern "C" fn vwarn(fmt: *const c_char, ap: VaList) {
17232 vwarn_impl(fmt, ap, true);
17233}
17234
17235#[no_mangle]
17236pub unsafe extern "C" fn vwarnx(fmt: *const c_char, ap: VaList) {
17237 vwarn_impl(fmt, ap, false);
17238}
17239
17240#[no_mangle]
17241pub unsafe extern "C" fn err(eval: c_int, fmt: *const c_char, args: ...) {
17242 verr(eval, fmt, args);
17243}
17244
17245#[no_mangle]
17246pub unsafe extern "C" fn errx(eval: c_int, fmt: *const c_char, args: ...) {
17247 verrx(eval, fmt, args);
17248}
17249
17250#[no_mangle]
17251pub unsafe extern "C" fn warn(fmt: *const c_char, args: ...) {
17252 vwarn(fmt, args);
17253}
17254
17255#[no_mangle]
17256pub unsafe extern "C" fn warnx(fmt: *const c_char, args: ...) {
17257 vwarnx(fmt, args);
17258}
17259
17260#[no_mangle]
17265pub unsafe extern "C" fn ecvt(value: f64, ndigit: i32, decpt: *mut i32, sign: *mut i32) -> *mut core::ffi::c_char {
17266 static mut BUF: [core::ffi::c_char; 80] = [0; 80];
17267 if value < 0.0 { *sign = 1; } else { *sign = 0; }
17268 let v = if value < 0.0 { -value } else { value };
17269 if v == 0.0 { *decpt = 0; BUF[0] = 0; return BUF.as_mut_ptr(); }
17270 let mut d = 0i32;
17271 let mut tmp = v;
17272 while tmp >= 10.0 { tmp /= 10.0; d += 1; }
17273 while tmp < 1.0 { tmp *= 10.0; d -= 1; }
17274 *decpt = d + 1;
17275 let mut i = 0;
17276 let mut val = tmp;
17277 while i < ndigit as usize && i < 79 {
17278 let digit = val as i32;
17279 BUF[i] = (b'0' + digit as u8) as c_char;
17280 val = (val - digit as f64) * 10.0;
17281 i += 1;
17282 }
17283 BUF[i] = 0;
17284 BUF.as_mut_ptr()
17285}
17286
17287#[no_mangle]
17288pub unsafe extern "C" fn fcvt(value: f64, ndigit: i32, decpt: *mut i32, sign: *mut i32) -> *mut core::ffi::c_char {
17289 static mut BUF: [core::ffi::c_char; 80] = [0; 80];
17290 if value < 0.0 { *sign = 1; } else { *sign = 0; }
17291 let v = if value < 0.0 { -value } else { value };
17292 if v == 0.0 { *decpt = 0; BUF[0] = 0; return BUF.as_mut_ptr(); }
17293 let mut d = 0i32;
17294 let mut tmp = v;
17295 while tmp >= 10.0 { tmp /= 10.0; d += 1; }
17296 while tmp < 1.0 { tmp *= 10.0; d -= 1; }
17297 *decpt = d + 1;
17298 let mut val = tmp;
17299 let mut i = 0;
17300 while i < (*decpt) as usize && i < 79 {
17301 let digit = val as i32;
17302 BUF[i] = (b'0' + digit as u8) as c_char;
17303 val = (val - digit as f64) * 10.0;
17304 i += 1;
17305 }
17306 if ndigit > 0 && i < 79 {
17307 BUF[i] = '.' as c_char;
17308 i += 1;
17309 let mut frac = val;
17310 let mut j = 0;
17311 while j < ndigit as usize && i < 79 {
17312 let digit = frac as i32;
17313 BUF[i] = (b'0' + digit as u8) as c_char;
17314 frac = (frac - digit as f64) * 10.0;
17315 i += 1;
17316 j += 1;
17317 }
17318 }
17319 BUF[i] = 0;
17320 BUF.as_mut_ptr()
17321}
17322
17323#[no_mangle]
17324pub unsafe extern "C" fn gcvt(value: f64, _ndigit: i32, buf: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
17325 if value == 0.0 {
17327 *buf = '0' as c_char;
17328 *buf.add(1) = 0;
17329 return buf;
17330 }
17331 let mut i = 0;
17332 let v = if value < 0.0 { *buf = '-' as c_char; i = 1; -value } else { value };
17333 let mut int_part = v as i64;
17335 let mut digits = [0u8; 32];
17336 let mut di = 0;
17337 if int_part == 0 {
17338 digits[0] = 0;
17339 di = 1;
17340 } else {
17341 while int_part > 0 && di < 32 {
17342 digits[di] = (int_part % 10) as u8;
17343 int_part /= 10;
17344 di += 1;
17345 }
17346 }
17347 while di > 0 && i < 79 {
17348 di -= 1;
17349 *buf.add(i) = (b'0' + digits[di]) as c_char;
17350 i += 1;
17351 }
17352 *buf.add(i) = 0;
17353 buf
17354}
17355
17356static mut SHELLS: [*const core::ffi::c_char; 3] = [
17361 b"/bin/sh\0".as_ptr() as *const core::ffi::c_char,
17362 b"/bin/bash\0".as_ptr() as *const core::ffi::c_char,
17363 core::ptr::null(),
17364];
17365static mut SHELL_IDX: usize = 0;
17366
17367#[no_mangle]
17368pub unsafe extern "C" fn getusershell() -> *mut core::ffi::c_char {
17369 let s = SHELLS[SHELL_IDX];
17370 if s.is_null() {
17371 SHELL_IDX = 0;
17372 return core::ptr::null_mut();
17373 }
17374 SHELL_IDX += 1;
17375 s as *mut core::ffi::c_char
17376}
17377
17378#[no_mangle]
17379pub unsafe extern "C" fn setusershell() {
17380 SHELL_IDX = 0;
17381}
17382
17383#[no_mangle]
17384pub unsafe extern "C" fn endusershell() {
17385 SHELL_IDX = 0;
17386}
17387
17388#[no_mangle]
17393pub unsafe extern "C" fn ether_aton(s: *const core::ffi::c_char) -> *mut u8 {
17394 static mut EA: [u8; 6] = [0; 6];
17395 if ether_aton_r(s, EA.as_mut_ptr()).is_null() { core::ptr::null_mut() } else { EA.as_mut_ptr() }
17396}
17397
17398#[no_mangle]
17399pub unsafe extern "C" fn ether_aton_r(s: *const core::ffi::c_char, ea: *mut u8) -> *mut u8 {
17400 if ea.is_null() { return core::ptr::null_mut(); }
17401 let mut i = 0;
17402 let mut j = 0;
17403 let mut val: u32 = 0;
17404 let mut digits = 0;
17405 while *s.add(i) != 0 && j < 6 {
17406 let c = *s.add(i);
17407 if c == ':' as c_char {
17408 if digits == 0 { return core::ptr::null_mut(); }
17409 *ea.add(j) = val as u8;
17410 j += 1;
17411 val = 0;
17412 digits = 0;
17413 } 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) {
17414 let d = if c >= '0' as c_char && c <= '9' as c_char { (c - '0' as c_char) as u32 }
17415 else if c >= 'a' as c_char { (c - 'a' as c_char + 10) as u32 }
17416 else { (c - 'A' as c_char + 10) as u32 };
17417 val = val * 16 + d;
17418 if val > 255 { return core::ptr::null_mut(); }
17419 digits += 1;
17420 if digits > 2 { return core::ptr::null_mut(); }
17421 } else {
17422 return core::ptr::null_mut();
17423 }
17424 i += 1;
17425 }
17426 if digits == 0 || j != 5 { return core::ptr::null_mut(); }
17427 *ea.add(j) = val as u8;
17428 ea
17429}
17430
17431#[no_mangle]
17432pub unsafe extern "C" fn ether_ntoa(ea: *const u8) -> *mut core::ffi::c_char {
17433 static mut BUF: [core::ffi::c_char; 18] = [0; 18];
17434 ether_ntoa_r(ea, BUF.as_mut_ptr());
17435 BUF.as_mut_ptr()
17436}
17437
17438#[no_mangle]
17439pub unsafe extern "C" fn ether_ntoa_r(ea: *const u8, buf: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
17440 let a = *ea.add(0); let b = *ea.add(1); let c = *ea.add(2);
17441 let d = *ea.add(3); let e = *ea.add(4); let f = *ea.add(5);
17442 let hex = b"0123456789abcdef\0".as_ptr() as *const u8;
17443 let mut i = 0;
17444 *buf.add(i) = *hex.add((a >> 4) as usize) as c_char; i += 1;
17445 *buf.add(i) = *hex.add((a & 0xf) as usize) as c_char; i += 1;
17446 *buf.add(i) = ':' as c_char; i += 1;
17447 *buf.add(i) = *hex.add((b >> 4) as usize) as c_char; i += 1;
17448 *buf.add(i) = *hex.add((b & 0xf) as usize) as c_char; i += 1;
17449 *buf.add(i) = ':' as c_char; i += 1;
17450 *buf.add(i) = *hex.add((c >> 4) as usize) as c_char; i += 1;
17451 *buf.add(i) = *hex.add((c & 0xf) as usize) as c_char; i += 1;
17452 *buf.add(i) = ':' as c_char; i += 1;
17453 *buf.add(i) = *hex.add((d >> 4) as usize) as c_char; i += 1;
17454 *buf.add(i) = *hex.add((d & 0xf) as usize) as c_char; i += 1;
17455 *buf.add(i) = ':' as c_char; i += 1;
17456 *buf.add(i) = *hex.add((e >> 4) as usize) as c_char; i += 1;
17457 *buf.add(i) = *hex.add((e & 0xf) as usize) as c_char; i += 1;
17458 *buf.add(i) = ':' as c_char; i += 1;
17459 *buf.add(i) = *hex.add((f >> 4) as usize) as c_char; i += 1;
17460 *buf.add(i) = *hex.add((f & 0xf) as usize) as c_char; i += 1;
17461 *buf.add(i) = 0;
17462 buf
17463}
17464
17465#[no_mangle]
17470pub unsafe extern "C" fn getutxent() -> *mut core::ffi::c_void {
17471 getutent()
17472}
17473
17474#[no_mangle]
17475pub unsafe extern "C" fn getutxid(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
17476 getutid(ut)
17477}
17478
17479#[no_mangle]
17480pub unsafe extern "C" fn getutxline(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
17481 getutline(ut)
17482}
17483
17484#[no_mangle]
17485pub unsafe extern "C" fn pututxline(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
17486 pututline(ut)
17487}
17488
17489#[no_mangle]
17490pub unsafe extern "C" fn setutxent() {
17491 setutent()
17492}
17493
17494#[no_mangle]
17495pub unsafe extern "C" fn endutxent() {
17496 endutent()
17497}
17498
17499#[no_mangle]
17504pub unsafe extern "C" fn execv(path: *const core::ffi::c_char, argv: *const *const core::ffi::c_char) -> i32 {
17505 crate::execve(path, argv, core::ptr::null())
17506}
17507
17508#[no_mangle]
17509pub unsafe extern "C" fn execlp(file: *const core::ffi::c_char, _args: ...) -> i32 {
17510 let mut argv: [*const core::ffi::c_char; 64] = [core::ptr::null(); 64];
17512 let mut i = 0;
17513 let mut args = _args;
17514 loop {
17515 let arg = args.next_arg::<*const core::ffi::c_char>();
17516 if arg.is_null() { break; }
17517 argv[i] = arg;
17518 i += 1;
17519 if i >= 63 { break; }
17520 }
17521 argv[i] = core::ptr::null();
17522 execvp(file, argv.as_ptr())
17523}
17524
17525#[no_mangle]
17526pub unsafe extern "C" fn execvp(file: *const core::ffi::c_char, argv: *const *const core::ffi::c_char) -> i32 {
17527 let path = crate::getenv(b"PATH\0".as_ptr() as *const core::ffi::c_char);
17529 if path.is_null() { return -1; }
17530 crate::execve(file, argv, core::ptr::null())
17532}
17533
17534#[no_mangle]
17535pub unsafe extern "C" fn fexecve(fd: i32, argv: *const *const core::ffi::c_char, envp: *const *const core::ffi::c_char) -> i32 {
17536 let mut path: [core::ffi::c_char; 64] = [0; 64];
17538 let mut i = 0;
17539 let src = b"/proc/self/fd/\0".as_ptr() as *const core::ffi::c_char;
17540 while i < 63 && *src.add(i) != 0 { path[i] = *src.add(i); i += 1; }
17541 let mut n = fd as usize;
17542 if n == 0 { path[i] = '0' as c_char; i += 1; }
17543 while n > 0 && i < 63 {
17544 path[i] = (b'0' + (n % 10) as u8) as c_char;
17545 n /= 10;
17546 i += 1;
17547 }
17548 path[i] = 0;
17549 crate::execve(path.as_ptr(), argv, envp)
17550}
17551
17552#[no_mangle]
17557pub unsafe extern "C" fn confstr(name: i32, buf: *mut core::ffi::c_char, len: usize) -> usize {
17558 match name {
17559 0 => { let s = b"/bin:/usr/bin\0".as_ptr() as *const core::ffi::c_char;
17561 let mut i = 0;
17562 while i < len - 1 && *s.add(i) != 0 { *buf.add(i) = *s.add(i); i += 1; }
17563 *buf.add(i) = 0;
17564 i + 1
17565 }
17566 1 => { let s = b"\0".as_ptr() as *const core::ffi::c_char;
17568 let mut i = 0;
17569 while i < len - 1 && *s.add(i) != 0 { *buf.add(i) = *s.add(i); i += 1; }
17570 *buf.add(i) = 0;
17571 i + 1
17572 }
17573 _ => 0,
17574 }
17575}
17576
17577#[no_mangle]
17578pub unsafe extern "C" fn pathconf(_path: *const core::ffi::c_char, name: i32) -> i64 {
17579 match name {
17581 0 => 4096, 1 => 255, 2 => 255, 3 => 255, 4 => 4096, 5 => 4096, 6 => 1, 7 => 0, 8 => 0, _ => -1,
17591 }
17592}
17593
17594#[no_mangle]
17595pub unsafe extern "C" fn fpathconf(_fd: i32, name: i32) -> i64 {
17596 match name {
17598 0 => 4096, 1 => 255, 2 => 255, 3 => 255, 4 => 4096, 5 => 4096, 6 => 1, 7 => 0, 8 => 0, _ => -1,
17608 }
17609}
17610
17611#[no_mangle]
17616pub unsafe extern "C" fn exp10(x: f64) -> f64 {
17617 libm::pow(10.0, x)
17618}
17619
17620#[no_mangle]
17621pub unsafe extern "C" fn exp10f(x: f32) -> f32 {
17622 libm::powf(10.0, x)
17623}
17624
17625#[no_mangle]
17630pub unsafe extern "C" fn explicit_bzero(s: *mut u8, n: usize) {
17631 core::ptr::write_bytes(s, 0, n);
17632 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
17633}
17634
17635#[no_mangle]
17636pub unsafe extern "C" fn memccpy(dest: *mut u8, src: *const u8, c: i32, n: usize) -> *mut u8 {
17637 let mut i = 0;
17638 while i < n {
17639 let byte = *src.add(i);
17640 *dest.add(i) = byte;
17641 if byte == c as u8 {
17642 return dest.add(i + 1);
17643 }
17644 i += 1;
17645 }
17646 core::ptr::null_mut()
17647}
17648
17649#[no_mangle]
17654pub unsafe extern "C" fn faccessat(dirfd: i32, pathname: *const core::ffi::c_char, mode: i32, flags: i32) -> i32 {
17655 <Arch as Syscalls>::syscall4(SYS_FACCESSAT, dirfd as i64, pathname as i64, mode as i64, flags as i64) as i32
17656}
17657
17658#[no_mangle]
17659pub unsafe extern "C" fn fchmodat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32, flags: i32) -> i32 {
17660 <Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, pathname as i64, mode as i64, flags as i64) as i32
17661}
17662
17663#[no_mangle]
17664pub unsafe extern "C" fn fchownat(dirfd: i32, pathname: *const core::ffi::c_char, uid: u32, gid: u32, flags: i32) -> i32 {
17665 <Arch as Syscalls>::syscall5(sysno(260, 54), dirfd as i64, pathname as i64, uid as i64, gid as i64, flags as i64) as i32
17666}
17667
17668#[no_mangle]
17669pub unsafe extern "C" fn linkat(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char, flags: i32) -> i32 {
17670 <Arch as Syscalls>::syscall5(SYS_LINKAT, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64) as i32
17671}
17672
17673#[no_mangle]
17674pub unsafe extern "C" fn mkdirat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32) -> i32 {
17675 <Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, pathname as i64, mode as i64) as i32
17676}
17677
17678#[no_mangle]
17679pub unsafe extern "C" fn mkfifoat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32) -> i32 {
17680 mknodat(dirfd, pathname, mode | 0o010000, 0)
17681}
17682
17683#[no_mangle]
17684pub unsafe extern "C" fn mknodat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32, dev: u64) -> i32 {
17685 <Arch as Syscalls>::syscall4(sysno(259, 33), dirfd as i64, pathname as i64, mode as i64, dev as i64) as i32
17686}
17687
17688#[no_mangle]
17689pub unsafe extern "C" fn readlinkat(dirfd: i32, pathname: *const core::ffi::c_char, buf: *mut core::ffi::c_char, bufsiz: usize) -> isize {
17690 <Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, pathname as i64, buf as i64, bufsiz as i64) as isize
17691}
17692
17693#[no_mangle]
17694pub unsafe extern "C" fn renameat(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char) -> i32 {
17695 <Arch as Syscalls>::syscall4(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64) as i32
17696}
17697
17698#[no_mangle]
17699pub unsafe extern "C" fn renameat2(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char, flags: u32) -> i32 {
17700 <Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64) as i32
17701}
17702
17703#[no_mangle]
17704pub unsafe extern "C" fn symlinkat(target: *const core::ffi::c_char, newdirfd: i32, linkpath: *const core::ffi::c_char) -> i32 {
17705 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64) as i32
17706}
17707
17708#[no_mangle]
17709pub unsafe extern "C" fn unlinkat(dirfd: i32, pathname: *const core::ffi::c_char, flags: i32) -> i32 {
17710 <Arch as Syscalls>::syscall3(SYS_UNLINKAT, dirfd as i64, pathname as i64, flags as i64) as i32
17711}
17712
17713#[no_mangle]
17714pub unsafe extern "C" fn utimes(filename: *const core::ffi::c_char, times: *const core::ffi::c_void) -> i32 {
17715 utimensat(AT_FDCWD, filename, times as *const timespec, 0)
17716}
17717
17718#[no_mangle]
17719pub unsafe extern "C" fn futimes(fd: i32, times: *const core::ffi::c_void) -> i32 {
17720 utimensat(fd, core::ptr::null(), times as *const timespec, 0)
17721}
17722
17723#[no_mangle]
17728pub unsafe extern "C" fn inotify_init() -> i32 {
17729 <Arch as Syscalls>::syscall1(sysno(253, 26), 0) as i32
17730}
17731
17732#[no_mangle]
17733pub unsafe extern "C" fn inotify_init1(flags: i32) -> i32 {
17734 <Arch as Syscalls>::syscall1(sysno(294, 26), flags as i64) as i32
17735}
17736
17737#[no_mangle]
17738pub unsafe extern "C" fn inotify_add_watch(fd: i32, pathname: *const core::ffi::c_char, mask: u32) -> i32 {
17739 <Arch as Syscalls>::syscall3(sysno(254, 27), fd as i64, pathname as i64, mask as i64) as i32
17740}
17741
17742#[no_mangle]
17743pub unsafe extern "C" fn inotify_rm_watch(fd: i32, wd: i32) -> i32 {
17744 <Arch as Syscalls>::syscall2(sysno(255, 28), fd as i64, wd as i64) as i32
17745}
17746
17747#[no_mangle]
17748pub unsafe extern "C" fn fanotify_init(flags: i32, event_f_flags: i32) -> i32 {
17749 <Arch as Syscalls>::syscall2(sysno(300, 262), flags as i64, event_f_flags as i64) as i32
17750}
17751
17752#[no_mangle]
17753pub unsafe extern "C" fn fanotify_mark(fd: i32, flags: i32, mask: u64, dirfd: i32, pathname: *const core::ffi::c_char) -> i32 {
17754 <Arch as Syscalls>::syscall5(sysno(301, 263), fd as i64, flags as i64, mask as i64, dirfd as i64, pathname as i64) as i32
17755}
17756
17757#[no_mangle]
17762pub unsafe extern "C" fn ffs(x: i32) -> i32 {
17763 if x == 0 { return 0; }
17764 x.trailing_zeros() as i32 + 1
17765}
17766
17767#[no_mangle]
17768pub unsafe extern "C" fn ffsl(x: i64) -> i32 {
17769 if x == 0 { return 0; }
17770 x.trailing_zeros() as i32 + 1
17771}
17772
17773#[no_mangle]
17774pub unsafe extern "C" fn ffsll(x: i64) -> i32 {
17775 if x == 0 { return 0; }
17776 x.trailing_zeros() as i32 + 1
17777}
17778
17779#[no_mangle]
17784pub unsafe extern "C" fn fchdir(fd: i32) -> i32 {
17785 <Arch as Syscalls>::syscall1(SYS_FCHDIR, fd as i64) as i32
17786}
17787
17788#[no_mangle]
17789pub unsafe extern "C" fn fchown(fd: i32, uid: u32, gid: u32) -> i32 {
17790 <Arch as Syscalls>::syscall3(SYS_FCHOWN, fd as i64, uid as i64, gid as i64) as i32
17791}
17792
17793#[no_mangle]
17794pub unsafe extern "C" fn fdopendir(fd: i32) -> *mut core::ffi::c_void {
17795 if fd < 0 { return core::ptr::null_mut(); }
17797 DIR_FD = fd;
17798 DIR_POS = 0;
17799 DIR_LEN = 0;
17800 &DIR_FD as *const i32 as *mut core::ffi::c_void
17801}
17802
17803#[no_mangle]
17804pub unsafe extern "C" fn getdtablesize() -> i32 {
17805 let mut rlim: Rlimit = core::mem::zeroed();
17806 if getrlimit(RLIMIT_NOFILE, &mut rlim) == 0 {
17807 rlim.rlim_cur as i32
17808 } else {
17809 1024
17810 }
17811}
17812
17813#[no_mangle]
17814pub unsafe extern "C" fn getentropy(buf: *mut u8, buflen: usize) -> i32 {
17815 getrandom(buf, buflen, 0) as i32
17816}
17817
17818#[no_mangle]
17819pub unsafe extern "C" fn getrandom(buf: *mut u8, buflen: usize, flags: u32) -> isize {
17820 <Arch as Syscalls>::syscall3(sysno(318, 278), buf as i64, buflen as i64, flags as i64) as isize
17821}
17822
17823#[no_mangle]
17824pub unsafe extern "C" fn killpg(pgrp: i32, sig: i32) -> i32 {
17825 <Arch as Syscalls>::syscall2(SYS_KILL, -pgrp as i64, sig as i64) as i32
17826}
17827
17828#[no_mangle]
17829pub unsafe extern "C" fn mkfifo(pathname: *const core::ffi::c_char, mode: u32) -> i32 {
17830 mknod(pathname, 0o010000 | mode, 0)
17831}
17832
17833#[no_mangle]
17838pub unsafe extern "C" fn aligned_alloc(alignment: usize, size: usize) -> *mut core::ffi::c_void {
17839 alloc_aligned_impl(alignment, size) as *mut core::ffi::c_void
17840}
17841
17842#[no_mangle]
17843pub unsafe extern "C" fn memalign(alignment: usize, size: usize) -> *mut core::ffi::c_void {
17844 alloc_aligned_impl(alignment, size) as *mut core::ffi::c_void
17845}
17846
17847#[no_mangle]
17848pub unsafe extern "C" fn posix_memalign(memptr: *mut *mut core::ffi::c_void, alignment: usize, size: usize) -> i32 {
17849 if memptr.is_null() { return EINVAL; }
17850 if alignment < core::mem::size_of::<*mut core::ffi::c_void>() || !alignment.is_power_of_two() {
17851 return EINVAL;
17852 }
17853 let p = alloc_aligned_impl(alignment, size);
17854 if p.is_null() { return ENOMEM; }
17855 *memptr = p as *mut core::ffi::c_void;
17856 0
17857}
17858
17859#[no_mangle]
17860pub unsafe extern "C" fn valloc(size: usize) -> *mut core::ffi::c_void {
17861 alloc_aligned_impl(PAGE, size) as *mut core::ffi::c_void
17862}
17863
17864#[no_mangle]
17877pub unsafe extern "C" fn gettext(msgid: *const core::ffi::c_char) -> *const core::ffi::c_char {
17878 msgid
17879}
17880
17881#[no_mangle]
17882pub unsafe extern "C" fn dgettext(_domainname: *const core::ffi::c_char, msgid: *const core::ffi::c_char) -> *const core::ffi::c_char {
17883 msgid
17884}
17885
17886#[no_mangle]
17887pub unsafe extern "C" fn dcgettext(_domainname: *const core::ffi::c_char, msgid: *const core::ffi::c_char, _category: i32) -> *const core::ffi::c_char {
17888 msgid
17889}
17890
17891#[no_mangle]
17892pub unsafe extern "C" fn ngettext(msgid1: *const core::ffi::c_char, msgid2: *const core::ffi::c_char, n: u64) -> *const core::ffi::c_char {
17893 if n == 1 { msgid1 } else { msgid2 }
17894}
17895
17896#[no_mangle]
17897pub 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 {
17898 if n == 1 { msgid1 } else { msgid2 }
17899}
17900
17901#[no_mangle]
17902pub 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 {
17903 if n == 1 { msgid1 } else { msgid2 }
17904}
17905
17906#[no_mangle]
17907pub unsafe extern "C" fn textdomain(domainname: *const core::ffi::c_char) -> *mut core::ffi::c_char {
17908 static mut DOMAIN: [core::ffi::c_char; 256] = [0; 256];
17909 if domainname.is_null() { return DOMAIN.as_mut_ptr(); }
17910 let mut i = 0;
17911 while i < 255 && *domainname.add(i) != 0 {
17912 DOMAIN[i] = *domainname.add(i);
17913 i += 1;
17914 }
17915 DOMAIN[i] = 0;
17916 DOMAIN.as_mut_ptr()
17917}
17918
17919#[no_mangle]
17920pub unsafe extern "C" fn bindtextdomain(_domainname: *const core::ffi::c_char, dirname: *const core::ffi::c_char) -> *mut core::ffi::c_char {
17921 dirname as *mut core::ffi::c_char
17922}
17923
17924#[no_mangle]
17925pub unsafe extern "C" fn bind_textdomain_codeset(_domainname: *const core::ffi::c_char, codeset: *const core::ffi::c_char) -> *mut core::ffi::c_char {
17926 codeset as *mut core::ffi::c_char
17927}
17928
17929#[no_mangle]
17934pub unsafe extern "C" fn wmemcpy(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
17935 let mut i = 0;
17936 while i < n {
17937 *dest.add(i) = *src.add(i);
17938 i += 1;
17939 }
17940 dest
17941}
17942
17943#[no_mangle]
17944pub unsafe extern "C" fn wmemmove(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
17945 if dest as usize <= src as usize {
17946 let mut i = 0;
17947 while i < n {
17948 *dest.add(i) = *src.add(i);
17949 i += 1;
17950 }
17951 } else {
17952 let mut i = n;
17953 while i > 0 {
17954 i -= 1;
17955 *dest.add(i) = *src.add(i);
17956 }
17957 }
17958 dest
17959}
17960
17961#[no_mangle]
17962pub unsafe extern "C" fn wmemset(dest: *mut u32, c: u32, n: usize) -> *mut u32 {
17963 let mut i = 0;
17964 while i < n {
17965 *dest.add(i) = c;
17966 i += 1;
17967 }
17968 dest
17969}
17970
17971#[no_mangle]
17972pub unsafe extern "C" fn wmemcmp(s1: *const u32, s2: *const u32, n: usize) -> i32 {
17973 let mut i = 0;
17974 while i < n {
17975 let c1 = *s1.add(i);
17976 let c2 = *s2.add(i);
17977 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
17978 i += 1;
17979 }
17980 0
17981}
17982
17983#[no_mangle]
17984pub unsafe extern "C" fn wmemchr(s: *const u32, c: u32, n: usize) -> *mut u32 {
17985 let mut i = 0;
17986 while i < n {
17987 if *s.add(i) == c { return s.add(i) as *mut u32; }
17988 i += 1;
17989 }
17990 core::ptr::null_mut()
17991}
17992
17993#[no_mangle]
17994pub unsafe extern "C" fn wcpcpy(dest: *mut u32, src: *const u32) -> *mut u32 {
17995 let mut i = 0;
17996 loop {
17997 let c = *src.add(i);
17998 *dest.add(i) = c;
17999 if c == 0 { return dest.add(i); }
18000 i += 1;
18001 }
18002}
18003
18004#[no_mangle]
18005pub unsafe extern "C" fn wcpncpy(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18006 let mut i = 0;
18007 while i < n {
18008 let c = *src.add(i);
18009 *dest.add(i) = c;
18010 if c == 0 { return dest.add(i); }
18011 i += 1;
18012 }
18013 dest.add(n)
18014}
18015
18016#[no_mangle]
18017pub unsafe extern "C" fn wprintf(fmt: *const wchar_t, args: ...) -> c_int {
18018 vfwprintf(stdout, fmt, args)
18019}
18020
18021#[no_mangle]
18022pub unsafe extern "C" fn vwprintf(fmt: *const wchar_t, ap: core::ffi::VaList) -> c_int {
18023 vfwprintf(stdout, fmt, ap)
18024}
18025
18026#[no_mangle]
18031pub unsafe extern "C" fn c16rtomb(s: *mut u8, c16: u16, ps: *mut core::ffi::c_void) -> usize {
18032 let state = ps as *mut u32;
18034 let saved: u32 = if state.is_null() { 0 } else { *state };
18035 if s.is_null() {
18036 if !state.is_null() { *state = 0; }
18037 return 1;
18038 }
18039 let cp: u32;
18040 if saved != 0 {
18041 if c16 < 0xdc00 || c16 > 0xdfff {
18042 if !state.is_null() { *state = 0; }
18043 ERRNO = EILSEQ;
18044 return !0usize;
18045 }
18046 cp = 0x10000 + (((saved - 0xd800) << 10) | ((c16 as u32) - 0xdc00));
18047 if !state.is_null() { *state = 0; }
18048 } else if c16 >= 0xd800 && c16 <= 0xdbff {
18049 if !state.is_null() { *state = c16 as u32; }
18050 return 0;
18051 } else if c16 >= 0xdc00 && c16 <= 0xdfff {
18052 ERRNO = EILSEQ;
18053 return !0usize;
18054 } else {
18055 cp = c16 as u32;
18056 }
18057 if cp < 0x80 {
18058 *s = cp as u8;
18059 1
18060 } else if cp < 0x800 {
18061 *s = (0xc0 | (cp >> 6)) as u8;
18062 *s.add(1) = (0x80 | (cp & 0x3f)) as u8;
18063 2
18064 } else if cp < 0x10000 {
18065 *s = (0xe0 | (cp >> 12)) as u8;
18066 *s.add(1) = (0x80 | ((cp >> 6) & 0x3f)) as u8;
18067 *s.add(2) = (0x80 | (cp & 0x3f)) as u8;
18068 3
18069 } else {
18070 *s = (0xf0 | (cp >> 18)) as u8;
18071 *s.add(1) = (0x80 | ((cp >> 12) & 0x3f)) as u8;
18072 *s.add(2) = (0x80 | ((cp >> 6) & 0x3f)) as u8;
18073 *s.add(3) = (0x80 | (cp & 0x3f)) as u8;
18074 4
18075 }
18076}
18077
18078#[no_mangle]
18079pub unsafe extern "C" fn c32rtomb(s: *mut u8, c32: u32, _ps: *mut core::ffi::c_void) -> usize {
18080 if s.is_null() { return 1; }
18081 if c32 > 0x10ffff || (c32 >= 0xd800 && c32 <= 0xdfff) {
18082 ERRNO = EILSEQ;
18083 return !0usize;
18084 }
18085 if c32 < 0x80 {
18086 *s = c32 as u8;
18087 1
18088 } else if c32 < 0x800 {
18089 *s = (0xc0 | (c32 >> 6)) as u8;
18090 *s.add(1) = (0x80 | (c32 & 0x3f)) as u8;
18091 2
18092 } else if c32 < 0x10000 {
18093 *s = (0xe0 | (c32 >> 12)) as u8;
18094 *s.add(1) = (0x80 | ((c32 >> 6) & 0x3f)) as u8;
18095 *s.add(2) = (0x80 | (c32 & 0x3f)) as u8;
18096 3
18097 } else {
18098 *s = (0xf0 | (c32 >> 18)) as u8;
18099 *s.add(1) = (0x80 | ((c32 >> 12) & 0x3f)) as u8;
18100 *s.add(2) = (0x80 | ((c32 >> 6) & 0x3f)) as u8;
18101 *s.add(3) = (0x80 | (c32 & 0x3f)) as u8;
18102 4
18103 }
18104}
18105
18106#[no_mangle]
18107pub unsafe extern "C" fn mbrtoc16(pc16: *mut u16, s: *const u8, n: usize, _ps: *mut core::ffi::c_void) -> usize {
18108 if s.is_null() { return 0; }
18109 if n == 0 { return 1; }
18110 let c = *s;
18111 if c == 0 { return 0; }
18112 if c < 0x80 {
18113 if !pc16.is_null() { *pc16 = c as u16; }
18114 return 1;
18115 }
18116 if c < 0xC2 { return 1; } if c < 0xE0 {
18118 if n < 2 { return 1; }
18119 let c2 = *s.add(1);
18120 if (c2 & 0xC0) != 0x80 { return 1; }
18121 if !pc16.is_null() { *pc16 = ((((c & 0x1F) as u32) << 6) | ((c2 & 0x3F) as u32)) as u16; }
18122 return 2;
18123 }
18124 if c < 0xF0 {
18125 if n < 3 { return 1; }
18126 let c2 = *s.add(1);
18127 let c3 = *s.add(2);
18128 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 { return 1; }
18129 if !pc16.is_null() { *pc16 = ((((c & 0x0F) as u32) << 12) | (((c2 & 0x3F) as u32) << 6) | ((c3 & 0x3F) as u32)) as u16; }
18130 return 3;
18131 }
18132 1
18133}
18134
18135#[no_mangle]
18136pub unsafe extern "C" fn mbrtoc32(pc32: *mut u32, s: *const u8, n: usize, _ps: *mut core::ffi::c_void) -> usize {
18137 if s.is_null() { return 0; }
18138 if n == 0 { return 1; }
18139 let c = *s;
18140 if c == 0 { return 0; }
18141 if c < 0x80 {
18142 if !pc32.is_null() { *pc32 = c as u32; }
18143 return 1;
18144 }
18145 if c < 0xC2 { return 1; } if c < 0xE0 {
18147 if n < 2 { return 1; }
18148 let c2 = *s.add(1);
18149 if (c2 & 0xC0) != 0x80 { return 1; }
18150 if !pc32.is_null() { *pc32 = (((c & 0x1F) as u32) << 6) | ((c2 & 0x3F) as u32); }
18151 return 2;
18152 }
18153 if c < 0xF0 {
18154 if n < 3 { return 1; }
18155 let c2 = *s.add(1);
18156 let c3 = *s.add(2);
18157 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 { return 1; }
18158 if !pc32.is_null() { *pc32 = (((c & 0x0F) as u32) << 12) | (((c2 & 0x3F) as u32) << 6) | ((c3 & 0x3F) as u32); }
18159 return 3;
18160 }
18161 if c < 0xF5 {
18162 if n < 4 { return 1; }
18163 let c2 = *s.add(1);
18164 let c3 = *s.add(2);
18165 let c4 = *s.add(3);
18166 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80 { return 1; }
18167 if !pc32.is_null() { *pc32 = (((c & 0x07) as u32) << 18) | (((c2 & 0x3F) as u32) << 12) | (((c3 & 0x3F) as u32) << 6) | ((c4 & 0x3F) as u32); }
18168 return 4;
18169 }
18170 1
18171}
18172
18173#[no_mangle]
18185pub unsafe extern "C" fn chown(path: *const core::ffi::c_char, uid: u32, gid: u32) -> i32 {
18186 <Arch as Syscalls>::syscall3(SYS_FCHOWNAT, AT_FDCWD as i64, path as i64, ((uid as u64) << 32 | gid as u64) as i64) as i32
18187}
18188
18189#[no_mangle]
18190pub unsafe extern "C" fn lchown(path: *const core::ffi::c_char, uid: u32, gid: u32) -> i32 {
18191 <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
18192}
18193
18194#[no_mangle]
18199pub unsafe extern "C" fn chroot(path: *const core::ffi::c_char) -> i32 {
18200 <Arch as Syscalls>::syscall1(SYS_CHROOT, path as i64) as i32
18201}
18202
18203#[no_mangle]
18204pub unsafe extern "C" fn get_current_dir_name() -> *mut core::ffi::c_char {
18205 static mut BUF: [core::ffi::c_char; 4096] = [0; 4096];
18206 let r = getcwd(BUF.as_mut_ptr(), 4096);
18207 if r.is_null() { core::ptr::null_mut() } else { BUF.as_mut_ptr() }
18208}
18209
18210#[no_mangle]
18215pub unsafe extern "C" fn creat(pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18216 open(pathname, 0o100 | 0o200 | 0o1000, mode as i32)
18217}
18218
18219#[no_mangle]
18220pub unsafe extern "C" fn openat(dirfd: i32, pathname: *const core::ffi::c_char, flags: i32, mode: u32) -> i32 {
18221 <Arch as Syscalls>::syscall4(SYS_OPENAT, dirfd as i64, pathname as i64, flags as i64, mode as i64) as i32
18222}
18223
18224#[no_mangle]
18225pub unsafe extern "C" fn pwrite(fd: i32, buf: *const u8, count: usize, offset: i64) -> isize {
18226 <Arch as Syscalls>::syscall4(sysno(18, 68), fd as i64, buf as i64, count as i64, offset) as isize
18227}
18228
18229#[no_mangle]
18230pub unsafe extern "C" fn readv(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32) -> isize {
18231 <Arch as Syscalls>::syscall3(sysno(19, 65), fd as i64, iov as i64, iovcnt as i64) as isize
18232}
18233
18234#[no_mangle]
18235pub unsafe extern "C" fn writev(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32) -> isize {
18236 <Arch as Syscalls>::syscall3(sysno(20, 66), fd as i64, iov as i64, iovcnt as i64) as isize
18237}
18238
18239#[no_mangle]
18244pub unsafe extern "C" fn flock(fd: i32, operation: i32) -> i32 {
18245 <Arch as Syscalls>::syscall2(SYS_FLOCK, fd as i64, operation as i64) as i32
18246}
18247
18248#[no_mangle]
18249pub unsafe extern "C" fn lockf(fd: i32, cmd: i32, len: i64) -> i32 {
18250 let r = <Arch as Syscalls>::syscall3(SYS_FCNTL, fd as i64, if cmd == 0 { 7 } else if cmd == 1 { 6 } else { 5 } , len);
18251 if r < 0 { return -1; }
18252 0
18253}
18254
18255#[no_mangle]
18260pub unsafe extern "C" fn getdomainname(name: *mut core::ffi::c_char, len: usize) -> i32 {
18261 if cfg!(target_arch = "x86_64") { <Arch as Syscalls>::syscall2(156, name as i64, len as i64) as i32 } else { ERRNO = 38; -1 }
18262}
18263
18264#[no_mangle]
18265pub unsafe extern "C" fn setdomainname(name: *const core::ffi::c_char, len: usize) -> i32 {
18266 <Arch as Syscalls>::syscall2(sysno(171, 162), name as i64, len as i64) as i32
18267}
18268
18269#[no_mangle]
18270pub unsafe extern "C" fn sethostname(name: *const core::ffi::c_char, len: usize) -> i32 {
18271 <Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64) as i32
18272}
18273
18274#[no_mangle]
18275pub unsafe extern "C" fn getlogin_r(name: *mut core::ffi::c_char, bufsize: usize) -> i32 {
18276 let user = crate::getenv(b"USER\0".as_ptr() as *const core::ffi::c_char);
18278 if user.is_null() { return 2; }
18279 let mut i = 0;
18280 while i < bufsize - 1 && *user.add(i) != 0 {
18281 *name.add(i) = *user.add(i);
18282 i += 1;
18283 }
18284 *name.add(i) = 0;
18285 0
18286}
18287
18288#[no_mangle]
18289pub unsafe extern "C" fn cuserid(s: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
18290 let user = crate::getenv(b"USER\0".as_ptr() as *const core::ffi::c_char);
18291 if user.is_null() { return core::ptr::null_mut(); }
18292 if s.is_null() {
18293 static mut BUF: [core::ffi::c_char; 32] = [0; 32];
18294 let mut i = 0;
18295 while i < 31 && *user.add(i) != 0 { BUF[i] = *user.add(i); i += 1; }
18296 BUF[i] = 0;
18297 BUF.as_mut_ptr()
18298 } else {
18299 let mut i = 0;
18300 while i < 31 && *user.add(i) != 0 { *s.add(i) = *user.add(i); i += 1; }
18301 *s.add(i) = 0;
18302 s
18303 }
18304}
18305
18306#[repr(C)]
18311#[derive(Copy, Clone)]
18312pub struct Passwd {
18313 pub pw_name: *mut c_char,
18314 pub pw_passwd: *mut c_char,
18315 pub pw_uid: u32,
18316 pub pw_gid: u32,
18317 pub pw_gecos: *mut c_char,
18318 pub pw_dir: *mut c_char,
18319 pub pw_shell: *mut c_char,
18320}
18321
18322#[repr(C)]
18323#[derive(Copy, Clone)]
18324pub struct Group {
18325 pub gr_name: *mut c_char,
18326 pub gr_passwd: *mut c_char,
18327 pub gr_gid: u32,
18328 pub gr_mem: *mut *mut c_char,
18329}
18330
18331static mut PWD_ENT: Passwd = Passwd {
18332 pw_name: core::ptr::null_mut(), pw_passwd: core::ptr::null_mut(),
18333 pw_uid: 0, pw_gid: 0, pw_gecos: core::ptr::null_mut(),
18334 pw_dir: core::ptr::null_mut(), pw_shell: core::ptr::null_mut(),
18335};
18336static mut PWD_BUF: [c_char; 1024] = [0; 1024];
18337static mut PWD_FILE: *mut FILE = core::ptr::null_mut();
18338
18339static mut GRP_ENT: Group = Group {
18340 gr_name: core::ptr::null_mut(), gr_passwd: core::ptr::null_mut(),
18341 gr_gid: 0, gr_mem: core::ptr::null_mut(),
18342};
18343static mut GRP_BUF: [c_char; 2048] = [0; 2048];
18344static mut GRP_MEM: [*mut c_char; 32] = [core::ptr::null_mut(); 32];
18345static mut GRP_FILE: *mut FILE = core::ptr::null_mut();
18346
18347unsafe fn parse_passwd(line: *const c_char, ent: *mut Passwd, buf: *mut c_char, buflen: usize) -> bool {
18348 let mut src = line;
18349 let mut o = 0usize;
18350 let mut fields: [*mut c_char; 7] = [core::ptr::null_mut(); 7];
18351 let mut n = 0usize;
18352 while n < 7 {
18353 let start = o;
18354 while *src != 0 && *src != b':' as c_char {
18355 if o + 1 >= buflen { return false; }
18356 *buf.add(o) = *src;
18357 o += 1;
18358 src = src.add(1);
18359 }
18360 *buf.add(o) = 0;
18361 o += 1;
18362 fields[n] = buf.add(start);
18363 n += 1;
18364 if *src == 0 { break; }
18365 src = src.add(1);
18366 }
18367 if n < 7 { return false; }
18368 (*ent).pw_name = fields[0];
18369 (*ent).pw_passwd = fields[1];
18370 (*ent).pw_uid = crate::strtol(fields[2], core::ptr::null_mut(), 10) as u32;
18371 (*ent).pw_gid = crate::strtol(fields[3], core::ptr::null_mut(), 10) as u32;
18372 (*ent).pw_gecos = fields[4];
18373 (*ent).pw_dir = fields[5];
18374 (*ent).pw_shell = fields[6];
18375 true
18376}
18377
18378unsafe fn parse_group(line: *const c_char, ent: *mut Group, buf: *mut c_char, buflen: usize) -> bool {
18379 let mut src = line;
18380 let mut o = 0usize;
18381 let mut fields: [*mut c_char; 4] = [core::ptr::null_mut(); 4];
18382 let mut n = 0usize;
18383 while n < 4 {
18384 let start = o;
18385 while *src != 0 && *src != b':' as c_char {
18386 if o + 1 >= buflen { return false; }
18387 *buf.add(o) = *src;
18388 o += 1;
18389 src = src.add(1);
18390 }
18391 *buf.add(o) = 0;
18392 o += 1;
18393 fields[n] = buf.add(start);
18394 n += 1;
18395 if *src == 0 { break; }
18396 src = src.add(1);
18397 }
18398 if n < 4 { return false; }
18399 (*ent).gr_name = fields[0];
18400 (*ent).gr_passwd = fields[1];
18401 (*ent).gr_gid = crate::strtol(fields[2], core::ptr::null_mut(), 10) as u32;
18402 let mut mi = 0usize;
18403 let mut m = fields[3];
18404 if *m != 0 {
18405 loop {
18406 if mi + 1 >= GRP_MEM.len() { break; }
18407 GRP_MEM[mi] = m;
18408 mi += 1;
18409 while *m != 0 && *m != b',' as c_char { m = m.add(1); }
18410 if *m == 0 { break; }
18411 *m = 0;
18412 m = m.add(1);
18413 }
18414 }
18415 GRP_MEM[mi] = core::ptr::null_mut();
18416 (*ent).gr_mem = GRP_MEM.as_mut_ptr();
18417 true
18418}
18419
18420#[no_mangle]
18421pub unsafe extern "C" fn getpwnam(name: *const c_char) -> *mut Passwd {
18422 if name.is_null() { return core::ptr::null_mut(); }
18423 setpwent();
18424 loop {
18425 let p = getpwent();
18426 if p.is_null() { break; }
18427 if crate::strcmp((*p).pw_name as *const u8, name as *const u8) == 0 { endpwent(); return p; }
18428 }
18429 endpwent();
18430 core::ptr::null_mut()
18431}
18432
18433#[no_mangle]
18434pub unsafe extern "C" fn getpwuid(uid: u32) -> *mut Passwd {
18435 setpwent();
18436 loop {
18437 let p = getpwent();
18438 if p.is_null() { break; }
18439 if (*p).pw_uid == uid { endpwent(); return p; }
18440 }
18441 endpwent();
18442 core::ptr::null_mut()
18443}
18444
18445#[no_mangle]
18446pub unsafe extern "C" fn setpwent() {
18447 endpwent();
18448 PWD_FILE = crate::fopen(b"/etc/passwd\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
18449}
18450
18451#[no_mangle]
18452pub unsafe extern "C" fn getpwent() -> *mut Passwd {
18453 if PWD_FILE.is_null() { setpwent(); if PWD_FILE.is_null() { return core::ptr::null_mut(); } }
18454 let mut line = [0 as c_char; 1024];
18455 loop {
18456 if crate::fgets(line.as_mut_ptr(), 1024, PWD_FILE).is_null() { return core::ptr::null_mut(); }
18457 if parse_passwd(line.as_ptr(), &raw mut PWD_ENT, PWD_BUF.as_mut_ptr(), PWD_BUF.len()) {
18458 return &raw mut PWD_ENT;
18459 }
18460 }
18461}
18462
18463#[no_mangle]
18464pub unsafe extern "C" fn endpwent() {
18465 if !PWD_FILE.is_null() { crate::fclose(PWD_FILE); PWD_FILE = core::ptr::null_mut(); }
18466}
18467
18468#[no_mangle]
18469pub 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 {
18470 if result.is_null() { return EINVAL; }
18471 let p = getpwnam(name);
18472 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *pwd = *p; *result = pwd; 0 }
18473}
18474
18475#[no_mangle]
18476pub unsafe extern "C" fn getpwuid_r(uid: u32, pwd: *mut Passwd, _buf: *mut c_char, _buflen: usize, result: *mut *mut Passwd) -> c_int {
18477 if result.is_null() { return EINVAL; }
18478 let p = getpwuid(uid);
18479 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *pwd = *p; *result = pwd; 0 }
18480}
18481
18482#[no_mangle]
18483pub unsafe extern "C" fn fgetpwent(f: *mut FILE) -> *mut Passwd {
18484 if f.is_null() { return core::ptr::null_mut(); }
18485 let mut line = [0 as c_char; 1024];
18486 loop {
18487 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
18488 if parse_passwd(line.as_ptr(), &raw mut PWD_ENT, PWD_BUF.as_mut_ptr(), PWD_BUF.len()) {
18489 return &raw mut PWD_ENT;
18490 }
18491 }
18492}
18493
18494#[no_mangle]
18495pub unsafe extern "C" fn putpwent(f: *mut FILE, p: *const Passwd) -> c_int {
18496 if f.is_null() || p.is_null() { return -1; }
18497 crate::fprintf(f, b"%s:%s:%u:%u:%s:%s:%s\n\0".as_ptr() as *const c_char,
18498 (*p).pw_name, (*p).pw_passwd, (*p).pw_uid, (*p).pw_gid,
18499 (*p).pw_gecos, (*p).pw_dir, (*p).pw_shell)
18500}
18501
18502#[no_mangle]
18503pub unsafe extern "C" fn getgrnam(name: *const c_char) -> *mut Group {
18504 if name.is_null() { return core::ptr::null_mut(); }
18505 setgrent();
18506 loop {
18507 let g = getgrent();
18508 if g.is_null() { break; }
18509 if crate::strcmp((*g).gr_name as *const u8, name as *const u8) == 0 { endgrent(); return g; }
18510 }
18511 endgrent();
18512 core::ptr::null_mut()
18513}
18514
18515#[no_mangle]
18516pub unsafe extern "C" fn getgrgid(gid: u32) -> *mut Group {
18517 setgrent();
18518 loop {
18519 let g = getgrent();
18520 if g.is_null() { break; }
18521 if (*g).gr_gid == gid { endgrent(); return g; }
18522 }
18523 endgrent();
18524 core::ptr::null_mut()
18525}
18526
18527#[no_mangle]
18528pub unsafe extern "C" fn setgrent() {
18529 endgrent();
18530 GRP_FILE = crate::fopen(b"/etc/group\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
18531}
18532
18533#[no_mangle]
18534pub unsafe extern "C" fn getgrent() -> *mut Group {
18535 if GRP_FILE.is_null() { setgrent(); if GRP_FILE.is_null() { return core::ptr::null_mut(); } }
18536 let mut line = [0 as c_char; 1024];
18537 loop {
18538 if crate::fgets(line.as_mut_ptr(), 1024, GRP_FILE).is_null() { return core::ptr::null_mut(); }
18539 if parse_group(line.as_ptr(), &raw mut GRP_ENT, GRP_BUF.as_mut_ptr(), GRP_BUF.len()) {
18540 return &raw mut GRP_ENT;
18541 }
18542 }
18543}
18544
18545#[no_mangle]
18546pub unsafe extern "C" fn endgrent() {
18547 if !GRP_FILE.is_null() { crate::fclose(GRP_FILE); GRP_FILE = core::ptr::null_mut(); }
18548}
18549
18550#[no_mangle]
18551pub 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 {
18552 if result.is_null() { return EINVAL; }
18553 let g = getgrnam(name);
18554 if g.is_null() { *result = core::ptr::null_mut(); 0 } else { *grp = *g; *result = grp; 0 }
18555}
18556
18557#[no_mangle]
18558pub unsafe extern "C" fn getgrgid_r(gid: u32, grp: *mut Group, _buf: *mut c_char, _buflen: usize, result: *mut *mut Group) -> c_int {
18559 if result.is_null() { return EINVAL; }
18560 let g = getgrgid(gid);
18561 if g.is_null() { *result = core::ptr::null_mut(); 0 } else { *grp = *g; *result = grp; 0 }
18562}
18563
18564#[no_mangle]
18565pub unsafe extern "C" fn fgetgrent(f: *mut FILE) -> *mut Group {
18566 if f.is_null() { return core::ptr::null_mut(); }
18567 let mut line = [0 as c_char; 1024];
18568 loop {
18569 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
18570 if parse_group(line.as_ptr(), &raw mut GRP_ENT, GRP_BUF.as_mut_ptr(), GRP_BUF.len()) {
18571 return &raw mut GRP_ENT;
18572 }
18573 }
18574}
18575
18576#[no_mangle]
18577pub unsafe extern "C" fn putgrent(f: *mut FILE, g: *const Group) -> c_int {
18578 if f.is_null() || g.is_null() { return -1; }
18579 crate::fprintf(f, b"%s:%s:%u:\0".as_ptr() as *const c_char, (*g).gr_name, (*g).gr_passwd, (*g).gr_gid);
18580 if !(*g).gr_mem.is_null() {
18581 let mut i = 0;
18582 while !(*(*g).gr_mem.add(i)).is_null() {
18583 if i > 0 { crate::fputc(b',' as c_int, f); }
18584 crate::fputs(*(*g).gr_mem.add(i), f);
18585 i += 1;
18586 }
18587 }
18588 crate::fputc(b'\n' as c_int, f);
18589 0
18590}
18591
18592#[no_mangle]
18597pub unsafe extern "C" fn setgroups(ngroups: usize, gidset: *const u32) -> i32 {
18598 <Arch as Syscalls>::syscall2(SYS_SETGROUPS, ngroups as i64, gidset as i64) as i32
18599}
18600
18601#[no_mangle]
18602pub unsafe extern "C" fn setresuid(ruid: u32, euid: u32, suid: u32) -> i32 {
18603 <Arch as Syscalls>::syscall3(SYS_SETRESUID, ruid as i64, euid as i64, suid as i64) as i32
18604}
18605
18606#[no_mangle]
18607pub unsafe extern "C" fn setresgid(rgid: u32, egid: u32, sgid: u32) -> i32 {
18608 <Arch as Syscalls>::syscall3(SYS_SETRESGID, rgid as i64, egid as i64, sgid as i64) as i32
18609}
18610
18611#[no_mangle]
18612pub unsafe extern "C" fn getresuid(ruid: *mut u32, euid: *mut u32, suid: *mut u32) -> i32 {
18613 <Arch as Syscalls>::syscall3(SYS_GETRESUID, ruid as i64, euid as i64, suid as i64) as i32
18614}
18615
18616#[no_mangle]
18617pub unsafe extern "C" fn getresgid(rgid: *mut u32, egid: *mut u32, sgid: *mut u32) -> i32 {
18618 <Arch as Syscalls>::syscall3(SYS_GETRESGID, rgid as i64, egid as i64, sgid as i64) as i32
18619}
18620
18621#[no_mangle]
18626pub unsafe extern "C" fn sendmsg(fd: i32, msg: *const core::ffi::c_void, flags: i32) -> isize {
18627 <Arch as Syscalls>::syscall3(SYS_SENDMSG, fd as i64, msg as i64, flags as i64) as isize
18628}
18629
18630#[no_mangle]
18631pub unsafe extern "C" fn recvmsg(fd: i32, msg: *mut core::ffi::c_void, flags: i32) -> isize {
18632 <Arch as Syscalls>::syscall3(SYS_RECVMSG, fd as i64, msg as i64, flags as i64) as isize
18633}
18634
18635#[no_mangle]
18636pub unsafe extern "C" fn sendmmsg(fd: i32, msgvec: *mut core::ffi::c_void, vlen: u32, flags: i32) -> i32 {
18637 <Arch as Syscalls>::syscall4(sysno(307, 269), fd as i64, msgvec as i64, vlen as i64, flags as i64) as i32
18638}
18639
18640#[no_mangle]
18641pub unsafe extern "C" fn recvmmsg(fd: i32, msgvec: *mut core::ffi::c_void, vlen: u32, flags: i32, timeout: *mut core::ffi::c_void) -> i32 {
18642 <Arch as Syscalls>::syscall5(sysno(299, 243), fd as i64, msgvec as i64, vlen as i64, flags as i64, timeout as i64) as i32
18643}
18644
18645#[no_mangle]
18646pub unsafe extern "C" fn getpeername(fd: i32, addr: *mut core::ffi::c_void, addrlen: *mut u32) -> i32 {
18647 <Arch as Syscalls>::syscall3(sysno(52, 205), fd as i64, addr as i64, addrlen as i64) as i32
18648}
18649
18650#[no_mangle]
18651pub unsafe extern "C" fn getsockopt(fd: i32, level: i32, optname: i32, optval: *mut core::ffi::c_void, optlen: *mut u32) -> i32 {
18652 <Arch as Syscalls>::syscall5(sysno(55, 209), fd as i64, level as i64, optname as i64, optval as i64, optlen as i64) as i32
18653}
18654
18655#[no_mangle]
18660pub unsafe extern "C" fn ftrylockfile(file: *mut FILE) -> i32 {
18661 if file.is_null() { return EINVAL; }
18662 if (*file).lock < 0 { return 0; }
18663 let tid = sys_gettid() as c_int;
18664 let v = a_load(&raw const (*file).lock);
18665 if v == tid {
18666 (*file).lockcount += 1;
18667 return 0;
18668 }
18669 if v == 0 && a_cas(&raw mut (*file).lock, 0, tid) == 0 {
18670 (*file).lockcount = 1;
18671 return 0;
18672 }
18673 EBUSY
18674}
18675
18676#[no_mangle]
18677pub unsafe extern "C" fn getc_unlocked(file: *mut core::ffi::c_char) -> i32 {
18678 getc(file as *mut FILE)
18679}
18680
18681#[no_mangle]
18682pub unsafe extern "C" fn getchar_unlocked() -> i32 {
18683 getchar()
18684}
18685
18686#[no_mangle]
18687pub unsafe extern "C" fn putc_unlocked(c: i32, file: *mut core::ffi::c_char) -> i32 {
18688 putc(c, file as *mut FILE)
18689}
18690
18691#[no_mangle]
18692pub unsafe extern "C" fn putchar_unlocked(c: i32) -> i32 {
18693 putchar(c)
18694}
18695
18696#[no_mangle] pub static mut optarg: *mut core::ffi::c_char = core::ptr::null_mut();
18701#[no_mangle] pub static mut optind: i32 = 1;
18702#[no_mangle] pub static mut opterr: i32 = 1;
18703#[no_mangle] pub static mut optopt: i32 = '?' as i32;
18704#[no_mangle] pub static mut optreset: i32 = 0;
18705
18706#[no_mangle]
18711pub unsafe extern "C" fn getitimer(which: i32, curr_value: *mut core::ffi::c_void) -> i32 {
18712 <Arch as Syscalls>::syscall2(sysno(36, 102), which as i64, curr_value as i64) as i32
18713}
18714
18715#[no_mangle]
18716pub unsafe extern "C" fn setitimer(which: i32, new_value: *const core::ffi::c_void, old_value: *mut core::ffi::c_void) -> i32 {
18717 <Arch as Syscalls>::syscall3(sysno(38, 103), which as i64, new_value as i64, old_value as i64) as i32
18718}
18719
18720#[no_mangle]
18725pub unsafe extern "C" fn getloadavg(loadavg: *mut f64, nelem: i32) -> i32 {
18726 let fd = crate::open(b"/proc/loadavg\0".as_ptr() as *const core::ffi::c_char, 0, 0);
18727 if fd < 0 { return -1; }
18728 let mut buf: [u8; 64] = [0; 64];
18729 let n = crate::read(fd, buf.as_mut_ptr() as *mut core::ffi::c_void, 63);
18730 crate::close(fd);
18731 if n <= 0 { return -1; }
18732 buf[n as usize] = 0;
18733 let mut i = 0;
18734 while i < nelem as usize && i < 3 {
18735 let val = crate::strtod((buf.as_ptr() as *const core::ffi::c_char).add(i * 5), core::ptr::null_mut());
18736 *loadavg.add(i) = val;
18737 i += 1;
18738 }
18739 i as i32
18740}
18741
18742#[no_mangle]
18743pub unsafe extern "C" fn get_nprocs() -> i32 {
18744 sysconf(84) as i32 }
18746
18747#[no_mangle]
18748pub unsafe extern "C" fn get_nprocs_conf() -> i32 {
18749 sysconf(83) as i32 }
18751
18752#[no_mangle]
18753pub unsafe extern "C" fn get_avphys_pages() -> i64 {
18754 sysconf(86) }
18756
18757#[no_mangle]
18758pub unsafe extern "C" fn get_phys_pages() -> i64 {
18759 sysconf(85) }
18761
18762#[no_mangle]
18767pub unsafe extern "C" fn capget(header: *mut core::ffi::c_void, data: *mut core::ffi::c_void) -> i32 {
18768 <Arch as Syscalls>::syscall2(SYS_CAPGET, header as i64, data as i64) as i32
18769}
18770
18771#[no_mangle]
18772pub unsafe extern "C" fn capset(header: *const core::ffi::c_void, data: *const core::ffi::c_void) -> i32 {
18773 <Arch as Syscalls>::syscall2(SYS_CAPSET, header as i64, data as i64) as i32
18774}
18775
18776#[no_mangle]
18777pub unsafe extern "C" fn arch_prctl(code: i32, addr: u64) -> i32 {
18778 if cfg!(target_arch = "x86_64") { <Arch as Syscalls>::syscall2(158, code as i64, addr as i64) as i32 } else { ERRNO = 38; -1 }
18779}
18780
18781#[no_mangle]
18786pub unsafe extern "C" fn cfgetospeed(termios_p: *const core::ffi::c_void) -> u32 {
18787 unsafe { *(termios_p as *const u32).add(1) }
18788}
18789
18790#[no_mangle]
18791pub unsafe extern "C" fn cfgetispeed(termios_p: *const core::ffi::c_void) -> u32 {
18792 unsafe { *(termios_p as *const u32).add(2) }
18793}
18794
18795#[no_mangle]
18796pub unsafe extern "C" fn cfsetospeed(termios_p: *mut core::ffi::c_void, speed: u32) -> i32 {
18797 unsafe { *(termios_p as *mut u32).add(1) = speed; }
18798 0
18799}
18800
18801#[no_mangle]
18802pub unsafe extern "C" fn cfsetispeed(termios_p: *mut core::ffi::c_void, speed: u32) -> i32 {
18803 unsafe { *(termios_p as *mut u32).add(2) = speed; }
18804 0
18805}
18806
18807#[no_mangle]
18808pub unsafe extern "C" fn cfmakeraw(termios_p: *mut core::ffi::c_void) {
18809 unsafe {
18810 let p = termios_p as *mut u32;
18811 *p.add(0) &= !0o37;
18812 *p.add(0) &= !(0o4000 | 0o2000 | 0o10000 | 0o20);
18813 *p.add(0) |= 0o60;
18814 *p.add(3) &= !0o17;
18815 *p.add(3) &= !(0o1000 | 0o40000000);
18816 *p.add(1) = 1;
18817 *p.add(2) = 0;
18818 }
18819}
18820
18821#[no_mangle]
18826pub unsafe extern "C" fn getrusage(who: i32, usage: *mut core::ffi::c_void) -> i32 {
18827 <Arch as Syscalls>::syscall2(sysno(98, 165), who as i64, usage as i64) as i32
18828}
18829
18830#[no_mangle]
18831pub unsafe extern "C" fn getpriority(which: i32, who: u32) -> i32 {
18832 <Arch as Syscalls>::syscall2(SYS_GETPRIORITY, which as i64, who as i64) as i32
18833}
18834
18835#[no_mangle]
18836pub unsafe extern "C" fn setpriority(which: i32, who: u32, prio: i32) -> i32 {
18837 <Arch as Syscalls>::syscall3(SYS_SETPRIORITY, which as i64, who as i64, prio as i64) as i32
18838}
18839
18840#[no_mangle]
18841pub unsafe extern "C" fn prlimit(pid: u32, resource: i32, new_limit: *const core::ffi::c_void, old_limit: *mut core::ffi::c_void) -> i32 {
18842 <Arch as Syscalls>::syscall4(sysno(302, 261), pid as i64, resource as i64, new_limit as i64, old_limit as i64) as i32
18843}
18844
18845#[no_mangle]
18850pub unsafe extern "C" fn clone(flags: u32, child_stack: *mut u8, _args: ...) -> i32 {
18851 <Arch as Syscalls>::syscall5(SYS_CLONE, flags as i64, child_stack as i64, 0, 0, 0) as i32
18852}
18853
18854#[no_mangle]
18855pub unsafe extern "C" fn _Fork() -> i32 {
18856 crate::fork()
18857}
18858
18859#[no_mangle]
18860pub 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 {
18861 let mut master: i32 = 0;
18862 let mut slave: i32 = 0;
18863 if openpty(&mut master, &mut slave, name, termp, winp) < 0 { return -1; }
18864 let pid = crate::fork();
18865 if pid < 0 { crate::close(master); crate::close(slave); return -1; }
18866 if pid == 0 {
18867 crate::close(master);
18868 crate::setsid();
18869 crate::dup2(slave, 0);
18870 crate::dup2(slave, 1);
18871 crate::dup2(slave, 2);
18872 } else {
18873 crate::close(slave);
18874 if !amaster.is_null() { *amaster = master; }
18875 }
18876 pid
18877}
18878
18879#[no_mangle]
18880pub 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 {
18881 let master = crate::open(b"/dev/ptmx\0".as_ptr() as *const core::ffi::c_char, 0o2000, 0);
18882 if master < 0 { return -1; }
18883 grantpt(master);
18884 unlockpt(master);
18885 let slave_name = ptsname(master);
18886 if slave_name.is_null() { crate::close(master); return -1; }
18887 let slave = crate::open(slave_name, 0o2000, 0);
18888 if slave < 0 { crate::close(master); return -1; }
18889 if !amaster.is_null() { *amaster = master; }
18890 if !aslave.is_null() { *aslave = slave; }
18891 if !name.is_null() { crate::strcpy(name as *mut u8, slave_name as *const u8); }
18892 0
18893}
18894
18895#[no_mangle]
18896pub unsafe extern "C" fn login_tty(fd: i32) -> i32 {
18897 crate::setsid();
18898 crate::dup2(fd, 0);
18899 crate::dup2(fd, 1);
18900 crate::dup2(fd, 2);
18901 0
18902}
18903
18904#[no_mangle]
18909pub unsafe extern "C" fn __dls2b() {}
18910#[no_mangle]
18911pub unsafe extern "C" fn __dls3() {}
18912#[no_mangle]
18913pub unsafe extern "C" fn _dlstart() {}
18914
18915#[no_mangle]
18920pub unsafe extern "C" fn index(s: *const core::ffi::c_char, c: i32) -> *mut core::ffi::c_char {
18921 let mut i = 0;
18922 loop {
18923 let ch = *s.add(i);
18924 if ch == c as core::ffi::c_char { return s.add(i) as *mut core::ffi::c_char; }
18925 if ch == 0 { return core::ptr::null_mut(); }
18926 i += 1;
18927 }
18928}
18929
18930#[no_mangle]
18931pub unsafe extern "C" fn rindex(s: *const core::ffi::c_char, c: i32) -> *mut core::ffi::c_char {
18932 let mut last = core::ptr::null_mut();
18933 let mut i = 0;
18934 loop {
18935 let ch = *s.add(i);
18936 if ch == 0 { return last; }
18937 if ch == c as core::ffi::c_char { last = s.add(i) as *mut core::ffi::c_char; }
18938 i += 1;
18939 }
18940}
18941
18942#[no_mangle]
18947pub unsafe extern "C" fn imaxabs(j: i64) -> i64 {
18948 j.abs()
18949}
18950
18951#[no_mangle]
18952pub unsafe extern "C" fn imaxdiv(numer: i64, denom: i64) -> (i64, i64) {
18953 (numer / denom, numer % denom)
18954}
18955
18956#[no_mangle]
18961pub static mut h_errno: i32 = 0;
18962
18963#[no_mangle]
18964pub unsafe extern "C" fn __h_errno_location() -> *mut i32 {
18965 &mut h_errno
18966}
18967
18968#[no_mangle]
18969pub unsafe extern "C" fn herror(s: *const core::ffi::c_char) {
18970 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
18971 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
18972 crate::write(2, hstrerror(*__h_errno_location()) as *const core::ffi::c_void, crate::strlen(hstrerror(*__h_errno_location())));
18973 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
18974}
18975
18976#[no_mangle]
18977pub unsafe extern "C" fn hstrerror(_err: i32) -> *const core::ffi::c_char {
18978 b"Unknown error\0".as_ptr() as *const core::ffi::c_char
18979}
18980
18981#[no_mangle]
18986pub unsafe extern "C" fn gettid() -> i32 {
18987 <Arch as Syscalls>::syscall0(SYS_GETTID) as i32
18988}
18989
18990#[no_mangle]
18995pub unsafe extern "C" fn ioctl(fd: i32, request: u32, mut args: ...) -> i32 {
18996 let arg = args.next_arg::<i64>();
18997 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, request as i64, arg) as i32
18998}
18999
19000#[no_mangle]
19001pub unsafe extern "C" fn ioperm(from: u64, num: u64, turn_on: i32) -> i32 {
19002 #[cfg(target_arch = "x86_64")]
19003 { <Arch as Syscalls>::syscall3(SYS_IOPERM, from as i64, num as i64, turn_on as i64) as i32 }
19004 #[cfg(not(target_arch = "x86_64"))]
19005 {
19006 let _ = (from, num, turn_on);
19007 ERRNO = ENOSYS_VAL;
19008 -1
19009 }
19010}
19011
19012#[no_mangle]
19013pub unsafe extern "C" fn iopl(level: i32) -> i32 {
19014 #[cfg(target_arch = "x86_64")]
19015 { <Arch as Syscalls>::syscall1(SYS_IOPL, level as i64) as i32 }
19016 #[cfg(not(target_arch = "x86_64"))]
19017 {
19018 let _ = level;
19019 ERRNO = ENOSYS_VAL;
19020 -1
19021 }
19022}
19023
19024#[no_mangle]
19029pub unsafe extern "C" fn getxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19030 <Arch as Syscalls>::syscall4(sysno(191, 8), path as i64, name as i64, value as i64, size as i64) as isize
19031}
19032
19033#[no_mangle]
19034pub unsafe extern "C" fn lgetxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19035 <Arch as Syscalls>::syscall4(sysno(192, 9), path as i64, name as i64, value as i64, size as i64) as isize
19036}
19037
19038#[no_mangle]
19039pub unsafe extern "C" fn fgetxattr(fd: i32, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19040 <Arch as Syscalls>::syscall4(sysno(193, 10), fd as i64, name as i64, value as i64, size as i64) as isize
19041}
19042
19043#[no_mangle]
19044pub unsafe extern "C" fn listxattr(path: *const core::ffi::c_char, list: *mut u8, size: usize) -> isize {
19045 <Arch as Syscalls>::syscall3(sysno(194, 11), path as i64, list as i64, size as i64) as isize
19046}
19047
19048#[no_mangle]
19049pub unsafe extern "C" fn llistxattr(path: *const core::ffi::c_char, list: *mut u8, size: usize) -> isize {
19050 <Arch as Syscalls>::syscall3(sysno(195, 12), path as i64, list as i64, size as i64) as isize
19051}
19052
19053#[no_mangle]
19054pub unsafe extern "C" fn flistxattr(fd: i32, list: *mut u8, size: usize) -> isize {
19055 <Arch as Syscalls>::syscall3(sysno(196, 13), fd as i64, list as i64, size as i64) as isize
19056}
19057
19058#[no_mangle]
19059pub 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 {
19060 <Arch as Syscalls>::syscall5(sysno(188, 5), path as i64, name as i64, value as i64, size as i64, flags as i64) as i32
19061}
19062
19063#[no_mangle]
19064pub 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 {
19065 <Arch as Syscalls>::syscall5(sysno(189, 6), path as i64, name as i64, value as i64, size as i64, flags as i64) as i32
19066}
19067
19068#[no_mangle]
19069pub unsafe extern "C" fn fsetxattr(fd: i32, name: *const core::ffi::c_char, value: *const u8, size: usize, flags: i32) -> i32 {
19070 <Arch as Syscalls>::syscall5(sysno(190, 7), fd as i64, name as i64, value as i64, size as i64, flags as i64) as i32
19071}
19072
19073#[no_mangle]
19074pub unsafe extern "C" fn removexattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char) -> i32 {
19075 <Arch as Syscalls>::syscall2(sysno(197, 14), path as i64, name as i64) as i32
19076}
19077
19078#[no_mangle]
19079pub unsafe extern "C" fn lremovexattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char) -> i32 {
19080 <Arch as Syscalls>::syscall2(sysno(198, 15), path as i64, name as i64) as i32
19081}
19082
19083#[no_mangle]
19084pub unsafe extern "C" fn fremovexattr(fd: i32, name: *const core::ffi::c_char) -> i32 {
19085 <Arch as Syscalls>::syscall2(sysno(199, 16), fd as i64, name as i64) as i32
19086}
19087
19088#[no_mangle]
19093pub unsafe extern "C" fn adjtime(_delta: *const core::ffi::c_void, olddelta: *mut core::ffi::c_void) -> i32 {
19094 <Arch as Syscalls>::syscall1(SYS_ADJTIMEX, olddelta as i64) as i32
19095}
19096
19097#[no_mangle]
19098pub unsafe extern "C" fn adjtimex(buf: *mut core::ffi::c_void) -> i32 {
19099 <Arch as Syscalls>::syscall1(SYS_ADJTIMEX, buf as i64) as i32
19100}
19101
19102#[no_mangle]
19107pub unsafe extern "C" fn grantpt(fd: i32) -> i32 {
19108 let mut s: u32 = 0;
19110 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5410, &mut s as *mut u32 as i64);
19111 0
19112}
19113
19114#[no_mangle]
19115pub unsafe extern "C" fn unlockpt(fd: i32) -> i32 {
19116 let mut unlock: i32 = 0;
19117 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5411, &mut unlock as *mut i32 as i64);
19118 0
19119}
19120
19121#[no_mangle]
19122pub unsafe extern "C" fn ptsname(fd: i32) -> *mut core::ffi::c_char {
19123 static mut BUF: [core::ffi::c_char; 32] = [0; 32];
19124 let mut pty_nr: i32 = 0;
19125 if <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5413, &mut pty_nr as *mut i32 as i64) < 0 {
19126 return core::ptr::null_mut();
19127 }
19128 BUF[0] = '/' as c_char; BUF[1] = 'd' as c_char; BUF[2] = 'e' as c_char; BUF[3] = 'v' as c_char;
19130 BUF[4] = '/' as c_char; BUF[5] = 'p' as c_char; BUF[6] = 't' as c_char; BUF[7] = 's' as c_char;
19131 BUF[8] = '/' as c_char;
19132 let mut n = pty_nr as usize;
19133 let mut i = 9;
19134 if n == 0 { BUF[i] = '0' as c_char; i += 1; }
19135 while n > 0 && i < 31 {
19136 BUF[i] = (b'0' + (n % 10) as u8) as c_char;
19137 n /= 10;
19138 i += 1;
19139 }
19140 BUF[i] = 0;
19141 BUF.as_mut_ptr()
19142}
19143
19144#[no_mangle]
19149pub unsafe extern "C" fn finite(x: f64) -> i32 {
19150 (!x.is_nan() && !x.is_infinite()) as i32
19151}
19152
19153#[no_mangle]
19154pub unsafe extern "C" fn finitef(x: f32) -> i32 {
19155 (!x.is_nan() && !x.is_infinite()) as i32
19156}
19157
19158#[no_mangle]
19159pub unsafe extern "C" fn __fpclassifyl(x: f64) -> i32 {
19160 __fpclassify(x)
19161}
19162
19163#[no_mangle]
19164pub unsafe extern "C" fn __signbitl(x: f64) -> i32 {
19165 __signbit(x)
19166}
19167
19168#[no_mangle]
19177pub unsafe extern "C" fn j0(x: f64) -> f64 {
19178 j0_impl(x)
19179}
19180
19181#[no_mangle]
19182pub unsafe extern "C" fn j0f(x: f32) -> f32 {
19183 libm::j0f(x)
19184}
19185
19186#[no_mangle]
19187pub unsafe extern "C" fn j1(x: f64) -> f64 {
19188 libm::j1(x)
19189}
19190
19191#[no_mangle]
19192pub unsafe extern "C" fn j1f(x: f32) -> f32 {
19193 libm::j1f(x)
19194}
19195
19196#[no_mangle]
19197pub unsafe extern "C" fn jn(n: i32, x: f64) -> f64 {
19198 libm::jn(n, x)
19199}
19200
19201#[no_mangle]
19202pub unsafe extern "C" fn jnf(n: i32, x: f32) -> f32 {
19203 libm::jnf(n, x)
19204}
19205
19206#[no_mangle]
19207pub unsafe extern "C" fn y0(x: f64) -> f64 {
19208 y0_impl(x)
19209}
19210
19211#[no_mangle]
19212pub unsafe extern "C" fn y0f(x: f32) -> f32 {
19213 if x.is_nan() { return x; }
19214 if x < 0.0 { return __math_invalidf(x); }
19215 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f32::NEG_INFINITY; }
19216 libm::y0f(x)
19217}
19218
19219#[no_mangle]
19220pub unsafe extern "C" fn y1(x: f64) -> f64 {
19221 if x.is_nan() { return x; }
19222 if x < 0.0 { return __math_invalid(x); }
19223 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f64::NEG_INFINITY; }
19224 libm::y1(x)
19225}
19226
19227#[no_mangle]
19228pub unsafe extern "C" fn y1f(x: f32) -> f32 {
19229 if x.is_nan() { return x; }
19230 if x < 0.0 { return __math_invalidf(x); }
19231 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f32::NEG_INFINITY; }
19232 libm::y1f(x)
19233}
19234
19235#[no_mangle]
19236pub unsafe extern "C" fn yn(n: i32, x: f64) -> f64 {
19237 if x.is_nan() { return x; }
19238 if x < 0.0 { return __math_invalid(x); }
19239 if x == 0.0 {
19240 feraiseexcept(FE_DIVBYZERO);
19241 if n >= 0 { return f64::NEG_INFINITY; }
19242 }
19243 libm::yn(n, x)
19244}
19245
19246#[no_mangle]
19247pub unsafe extern "C" fn ynf(n: i32, x: f32) -> f32 {
19248 if x.is_nan() { return x; }
19249 if x < 0.0 { return __math_invalidf(x); }
19250 if x == 0.0 {
19251 feraiseexcept(FE_DIVBYZERO);
19252 if n >= 0 { return f32::NEG_INFINITY; }
19253 }
19254 libm::ynf(n, x)
19255}
19256
19257#[no_mangle]
19262pub unsafe extern "C" fn __ctype_b_loc() -> *mut *const u16 {
19263 static mut TABLE: *const u16 = core::ptr::null();
19264 &mut TABLE
19265}
19266
19267#[no_mangle]
19268pub unsafe extern "C" fn __ctype_tolower_loc() -> *mut *const i32 {
19269 static mut TABLE: *const i32 = core::ptr::null();
19270 &mut TABLE
19271}
19272
19273#[no_mangle]
19274pub unsafe extern "C" fn __ctype_toupper_loc() -> *mut *const i32 {
19275 static mut TABLE: *const i32 = core::ptr::null();
19276 &mut TABLE
19277}
19278
19279#[no_mangle]
19280pub unsafe extern "C" fn __isalnum_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19281 (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
19282}
19283
19284#[no_mangle]
19285pub unsafe extern "C" fn __isalpha_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19286 (c >= 'A' as i32 && c <= 'Z' as i32 || c >= 'a' as i32 && c <= 'z' as i32) as i32
19287}
19288
19289#[no_mangle]
19290pub unsafe extern "C" fn __isblank_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19291 (c == ' ' as i32 || c == '\t' as i32) as i32
19292}
19293
19294#[no_mangle]
19295pub unsafe extern "C" fn __iscntrl_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19296 (c < 0x20 || c == 0x7f) as i32
19297}
19298
19299#[no_mangle]
19300pub unsafe extern "C" fn __isdigit_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19301 (c >= '0' as i32 && c <= '9' as i32) as i32
19302}
19303
19304#[no_mangle]
19305pub unsafe extern "C" fn __isgraph_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19306 (c > 0x20 && c < 0x7f) as i32
19307}
19308
19309#[no_mangle]
19310pub unsafe extern "C" fn __islower_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19311 (c >= 'a' as i32 && c <= 'z' as i32) as i32
19312}
19313
19314#[no_mangle]
19315pub unsafe extern "C" fn __isprint_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19316 (c >= 0x20 && c < 0x7f) as i32
19317}
19318
19319#[no_mangle]
19320pub unsafe extern "C" fn __ispunct_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19321 (c >= 0x21 && c <= 0x2f || c >= 0x3a && c <= 0x40 || c >= 0x5b && c <= 0x60 || c >= 0x7b && c <= 0x7e) as i32
19322}
19323
19324#[no_mangle]
19325pub unsafe extern "C" fn __isspace_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19326 (c == ' ' as i32 || c >= 0x09 && c <= 0x0d) as i32
19327}
19328
19329#[no_mangle]
19330pub unsafe extern "C" fn __isupper_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19331 (c >= 'A' as i32 && c <= 'Z' as i32) as i32
19332}
19333
19334#[no_mangle]
19335pub unsafe extern "C" fn __isxdigit_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19336 (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
19337}
19338
19339#[no_mangle]
19344pub unsafe extern "C" fn __iswalnum_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19345 (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
19346}
19347
19348#[no_mangle]
19349pub unsafe extern "C" fn __iswalpha_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19350 (c >= 'A' as u32 && c <= 'Z' as u32 || c >= 'a' as u32 && c <= 'z' as u32) as i32
19351}
19352
19353#[no_mangle]
19354pub unsafe extern "C" fn __iswblank_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19355 (c == ' ' as u32 || c == '\t' as u32) as i32
19356}
19357
19358#[no_mangle]
19359pub unsafe extern "C" fn __iswcntrl_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19360 (c < 0x20 || c == 0x7f) as i32
19361}
19362
19363#[no_mangle]
19364pub unsafe extern "C" fn __iswdigit_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19365 (c >= '0' as u32 && c <= '9' as u32) as i32
19366}
19367
19368#[no_mangle]
19369pub unsafe extern "C" fn __iswgraph_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19370 (c > 0x20 && c < 0x7f) as i32
19371}
19372
19373#[no_mangle]
19374pub unsafe extern "C" fn __iswlower_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19375 (c >= 'a' as u32 && c <= 'z' as u32) as i32
19376}
19377
19378#[no_mangle]
19379pub unsafe extern "C" fn __iswprint_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19380 (c >= 0x20 && c < 0x7f) as i32
19381}
19382
19383#[no_mangle]
19384pub unsafe extern "C" fn __iswpunct_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19385 (c >= 0x21 && c <= 0x2f || c >= 0x3a && c <= 0x40 || c >= 0x5b && c <= 0x60 || c >= 0x7b && c <= 0x7e) as i32
19386}
19387
19388#[no_mangle]
19389pub unsafe extern "C" fn __iswspace_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19390 (c == ' ' as u32 || c >= 0x09 && c <= 0x0d) as i32
19391}
19392
19393#[no_mangle]
19394pub unsafe extern "C" fn __iswupper_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19395 (c >= 'A' as u32 && c <= 'Z' as u32) as i32
19396}
19397
19398#[no_mangle]
19399pub unsafe extern "C" fn __iswxdigit_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19400 (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
19401}
19402
19403#[no_mangle]
19404pub unsafe extern "C" fn __iswctype_l(c: u32, ctype: u32, _loc: *mut core::ffi::c_void) -> i32 {
19405 crate::iswctype(c as wint_t, ctype as wctype_t)
19406}
19407
19408#[no_mangle]
19409pub unsafe extern "C" fn __towlower_l(c: u32, _loc: *mut core::ffi::c_void) -> u32 {
19410 crate::towlower(c)
19411}
19412
19413#[no_mangle]
19414pub unsafe extern "C" fn __towupper_l(c: u32, _loc: *mut core::ffi::c_void) -> u32 {
19415 crate::towupper(c)
19416}
19417
19418#[no_mangle]
19419pub unsafe extern "C" fn __towctrans_l(c: u32, _trans: u32, _loc: *mut core::ffi::c_void) -> u32 {
19420 c
19421}
19422
19423#[no_mangle]
19436pub 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) {
19437 crate::write(2, b"Assertion failed: ".as_ptr() as *const core::ffi::c_void, 18);
19438 if !expr.is_null() { crate::write(2, expr as *const core::ffi::c_void, crate::strlen(expr)); }
19439 crate::write(2, b" (".as_ptr() as *const core::ffi::c_void, 2);
19440 if !file.is_null() { crate::write(2, file as *const core::ffi::c_void, crate::strlen(file)); }
19441 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
19442 let mut n = line as usize;
19443 let mut digits: [u8; 32] = [0; 32];
19444 let mut di = 0;
19445 if n == 0 { digits[0] = 0; di = 1; }
19446 while n > 0 && di < 32 { digits[di] = (n % 10) as u8; n /= 10; di += 1; }
19447 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); }
19448 crate::write(2, b")".as_ptr() as *const core::ffi::c_void, 1);
19449 if !func.is_null() { crate::write(2, func as *const core::ffi::c_void, crate::strlen(func)); }
19450 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
19451 crate::abort()
19452}
19453
19454#[no_mangle]
19455pub unsafe extern "C" fn at_quick_exit(_func: Option<unsafe extern "C" fn()>) -> i32 {
19456 0
19458}
19459
19460#[no_mangle]
19461pub unsafe extern "C" fn brk(addr: *mut u8) -> i32 {
19462 <Arch as Syscalls>::syscall1(sysno(12, 214), addr as i64) as i32
19463}
19464
19465#[no_mangle]
19466pub 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 {
19467 <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
19468}
19469
19470#[no_mangle]
19471pub unsafe extern "C" fn ctermid(s: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
19472 static mut BUF: [core::ffi::c_char; 20] = [0; 20];
19473 let dst = if s.is_null() { BUF.as_mut_ptr() } else { s };
19474 let src = b"/dev/tty\0".as_ptr() as *const core::ffi::c_char;
19475 let mut i = 0;
19476 while i < 9 { *dst.add(i) = *src.add(i); i += 1; }
19477 dst
19478}
19479
19480#[no_mangle]
19481pub unsafe extern "C" fn delete_module(name: *const core::ffi::c_char, flags: u32) -> i32 {
19482 <Arch as Syscalls>::syscall2(SYS_DELETE_MODULE, name as i64, flags as i64) as i32
19483}
19484
19485
19486
19487
19488
19489#[no_mangle]
19490pub unsafe extern "C" fn __duplocale(loc: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
19491 loc
19492}
19493
19494#[no_mangle]
19495pub unsafe extern "C" fn euidaccess(pathname: *const core::ffi::c_char, mode: i32) -> i32 {
19496 faccessat(AT_FDCWD, pathname, mode, 0x200)
19497}
19498
19499#[no_mangle]
19500pub unsafe extern "C" fn fgetln(f: *mut core::ffi::c_void, lenp: *mut usize) -> *mut core::ffi::c_char {
19501 static mut BUF: [core::ffi::c_char; 4096] = [0; 4096];
19502 let mut i = 0;
19503 while i < 4095 {
19504 let c = getc(f as *mut FILE);
19505 if c < 0 { break; }
19506 BUF[i] = c as c_char;
19507 i += 1;
19508 if c == '\n' as i32 { break; }
19509 }
19510 BUF[i] = 0;
19511 if !lenp.is_null() { *lenp = i; }
19512 if i == 0 { core::ptr::null_mut() } else { BUF.as_mut_ptr() }
19513}
19514
19515#[no_mangle]
19516pub unsafe extern "C" fn fgetws(ws: *mut u32, n: i32, f: *mut core::ffi::c_void) -> *mut u32 {
19517 let mut i = 0;
19518 while i < n - 1 {
19519 let c = getwc(f as *mut core::ffi::c_void);
19520 if c == 0 { break; }
19521 *ws.add(i as usize) = c;
19522 i += 1;
19523 if c == '\n' as u32 { break; }
19524 }
19525 *ws.add(i as usize) = 0;
19526 if i == 0 { core::ptr::null_mut() } else { ws }
19527}
19528
19529#[no_mangle]
19530pub 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 {
19531 if !label.is_null() { crate::write(2, label as *const core::ffi::c_void, crate::strlen(label)); }
19532 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
19533 if !text.is_null() { crate::write(2, text as *const core::ffi::c_void, crate::strlen(text)); }
19534 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
19535 0
19536}
19537
19538#[no_mangle]
19539pub unsafe extern "C" fn ftime(tp: *mut core::ffi::c_void) -> i32 {
19540 let mut tv: timeval = core::mem::zeroed();
19541 if gettimeofday(&mut tv, core::ptr::null_mut()) == 0 {
19542 let tb = tp as *mut Timeb;
19543 (*tb).time = tv.tv_sec;
19544 (*tb).millitm = (tv.tv_usec / 1000) as u16;
19545 (*tb).timezone = 0;
19546 (*tb).dstflag = 0;
19547 0
19548 } else {
19549 -1
19550 }
19551}
19552
19553#[no_mangle]
19554pub unsafe extern "C" fn getdents(fd: i32, dirp: *mut u8, count: usize) -> isize {
19555 <Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, dirp as i64, count as i64) as isize
19556}
19557
19558#[no_mangle]
19559pub unsafe extern "C" fn gethostid() -> i64 {
19560 let fd = crate::open(b"/proc/sys/kernel/random/boot_id\0".as_ptr() as *const core::ffi::c_char, 0, 0);
19562 if fd < 0 { return 0; }
19563 let mut buf: [u8; 64] = [0; 64];
19564 let n = crate::read(fd, buf.as_mut_ptr() as *mut core::ffi::c_void, 63);
19565 crate::close(fd);
19566 if n <= 0 { return 0; }
19567 buf[n as usize] = 0;
19568 crate::strtol(buf.as_ptr() as *const core::ffi::c_char, core::ptr::null_mut(), 16)
19569}
19570
19571#[no_mangle]
19572pub unsafe extern "C" fn getpass(prompt: *const core::ffi::c_char) -> *mut core::ffi::c_char {
19573 static mut BUF: [core::ffi::c_char; 128] = [0; 128];
19574 crate::write(2, prompt as *const core::ffi::c_void, crate::strlen(prompt));
19576 let n = crate::read(0, BUF.as_mut_ptr() as *mut core::ffi::c_void, 127);
19578 if n > 0 {
19579 let end = if BUF[(n - 1) as usize] == '\n' as c_char { n - 1 } else { n };
19580 BUF[end as usize] = 0;
19581 } else {
19582 BUF[0] = 0;
19583 }
19584 BUF.as_mut_ptr()
19585}
19586
19587#[no_mangle]
19588pub 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 {
19589 let s = *optionp;
19590 if s.is_null() { return -1; }
19591 let mut end = s;
19593 while *end != 0 && *end != ',' as c_char && *end != '=' as c_char { end = end.add(1); }
19594 let eq = *end == '=' as c_char;
19595 if eq { *end = 0; *valuep = end.add(1); }
19596 let mut i = 0;
19598 loop {
19599 let tok = *tokens.add(i);
19600 if tok.is_null() { break; }
19601 if crate::strcmp(s as *const u8, tok as *const u8) == 0 {
19602 while *end != 0 && *end != ',' as c_char { end = end.add(1); }
19604 if *end == ',' as c_char { end = end.add(1); }
19605 *optionp = end;
19606 return i as i32;
19607 }
19608 i += 1;
19609 }
19610 -1
19611}
19612
19613#[no_mangle]
19614pub unsafe extern "C" fn getw(f: *mut core::ffi::c_void) -> i32 {
19615 let c0 = getc(f as *mut FILE);
19616 if c0 < 0 { return -1; }
19617 let c1 = getc(f as *mut FILE);
19618 if c1 < 0 { return -1; }
19619 let c2 = getc(f as *mut FILE);
19620 if c2 < 0 { return -1; }
19621 let c3 = getc(f as *mut FILE);
19622 if c3 < 0 { return -1; }
19623 (c0 | (c1 << 8) | (c2 << 16) | (c3 << 24)) as i32
19624}
19625
19626#[no_mangle]
19627pub unsafe extern "C" fn getwc(f: *mut core::ffi::c_void) -> u32 {
19628 getc(f as *mut FILE) as u32
19629}
19630
19631#[no_mangle]
19632pub unsafe extern "C" fn init_module(module_image: *mut u8, len: usize, param_values: *const core::ffi::c_char) -> i32 {
19633 <Arch as Syscalls>::syscall3(SYS_INIT_MODULE, module_image as i64, len as i64, param_values as i64) as i32
19634}
19635
19636
19637
19638#[no_mangle]
19639pub unsafe extern "C" fn issetugid() -> i32 {
19640 let ruid = crate::getuid();
19641 let euid = crate::geteuid();
19642 let rgid = crate::getgid();
19643 let egid = crate::getegid();
19644 (ruid != euid || rgid != egid) as i32
19645}
19646
19647#[no_mangle]
19652pub unsafe extern "C" fn poll(fds: *mut core::ffi::c_void, nfds: u32, timeout: i32) -> i32 {
19653 #[cfg(target_arch = "x86_64")]
19654 { <Arch as Syscalls>::syscall3(SYS_POLL, fds as i64, nfds as i64, timeout as i64) as i32 }
19655 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
19656 {
19657 <Arch as Syscalls>::syscall5(SYS_PPOLL, fds as i64, nfds as i64, timeout as i64, 0, 0) as i32
19658 }
19659}
19660
19661#[no_mangle]
19662pub unsafe extern "C" fn ppoll(fds: *mut core::ffi::c_void, nfds: u32, timeout: *const core::ffi::c_void, sigmask: *const u64) -> i32 {
19663 <Arch as Syscalls>::syscall5(SYS_PPOLL, fds as i64, nfds as i64, timeout as i64, sigmask as i64, 8) as i32
19664}
19665
19666#[no_mangle]
19667pub 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 {
19668 <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
19669}
19670
19671#[no_mangle]
19680pub unsafe extern "C" fn quick_exit(status: i32) -> ! {
19681 crate::_exit(status)
19682}
19683
19684#[no_mangle]
19689pub unsafe extern "C" fn lstat(path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
19690 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, buf as i64, 0x100) as i32
19691}
19692
19693#[no_mangle]
19694pub unsafe extern "C" fn __xstat(_ver: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
19695 crate::stat(path, buf as *mut Stat)
19696}
19697
19698#[no_mangle]
19699pub unsafe extern "C" fn __lxstat(_ver: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
19700 crate::lstat(path, buf)
19701}
19702
19703#[no_mangle]
19704pub unsafe extern "C" fn __fxstat(_ver: i32, fd: i32, buf: *mut core::ffi::c_void) -> i32 {
19705 crate::fstat(fd, buf as *mut Stat)
19706}
19707
19708#[no_mangle]
19709pub unsafe extern "C" fn __fxstatat(_ver: i32, _dirfd: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void, _flags: i32) -> i32 {
19710 crate::stat(path, buf as *mut Stat)
19711}
19712
19713#[no_mangle]
19718pub unsafe extern "C" fn mempcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
19719 core::ptr::copy_nonoverlapping(src, dest, n);
19720 dest.add(n)
19721}
19722
19723#[no_mangle]
19728pub unsafe extern "C" fn mkostemp(template: *mut core::ffi::c_char, _flags: i32) -> i32 {
19729 mkstemp(template)
19730}
19731
19732#[no_mangle]
19733pub unsafe extern "C" fn mkstemps(template: *mut core::ffi::c_char, _suffixlen: i32) -> i32 {
19734 mkstemp(template)
19735}
19736
19737#[no_mangle]
19742pub unsafe extern "C" fn ptrace(request: i32, mut args: ...) -> i64 {
19743 let pid = args.next_arg::<i64>();
19744 let addr = args.next_arg::<i64>();
19745 let data = args.next_arg::<i64>();
19746 <Arch as Syscalls>::syscall4(sysno(101, 117), request as i64, pid, addr, data)
19747}
19748
19749#[no_mangle]
19750pub unsafe extern "C" fn personality(persona: u64) -> i64 {
19751 <Arch as Syscalls>::syscall1(sysno(135, 92), persona as i64)
19752}
19753
19754#[no_mangle]
19755pub unsafe extern "C" fn reboot(magic: i32, magic2: i32, cmd: u32, arg: *mut u8) -> i32 {
19756 <Arch as Syscalls>::syscall4(SYS_REBOOT, magic as i64, magic2 as i64, cmd as i64, arg as i64) as i32
19757}
19758
19759#[no_mangle]
19760pub unsafe extern "C" fn pivot_root(new_root: *const core::ffi::c_char, put_old: *const core::ffi::c_char) -> i32 {
19761 <Arch as Syscalls>::syscall2(SYS_PIVOT_ROOT, new_root as i64, put_old as i64) as i32
19762}
19763
19764#[no_mangle]
19765pub 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 {
19766 <Arch as Syscalls>::syscall5(SYS_MOUNT, source as i64, target as i64, filesystemtype as i64, mountflags as i64, data as i64) as i32
19767}
19768
19769#[no_mangle]
19770pub unsafe extern "C" fn umount(target: *const core::ffi::c_char) -> i32 {
19771 <Arch as Syscalls>::syscall2(SYS_UMOUNT2, target as i64, 0) as i32
19772}
19773
19774#[no_mangle]
19775pub unsafe extern "C" fn umount2(target: *const core::ffi::c_char, flags: i32) -> i32 {
19776 <Arch as Syscalls>::syscall2(SYS_UMOUNT2, target as i64, flags as i64) as i32
19777}
19778
19779#[no_mangle]
19789pub unsafe extern "C" fn psiginfo(_pinfo: *const core::ffi::c_void, s: *const core::ffi::c_char) {
19790 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
19791 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
19792}
19793
19794#[no_mangle]
19795pub unsafe extern "C" fn psignal(sig: i32, s: *const core::ffi::c_char) {
19796 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
19797 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
19798 crate::write(2, strsignal(sig) as *const core::ffi::c_void, crate::strlen(strsignal(sig)));
19799 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
19800}
19801
19802#[no_mangle]
19803pub unsafe extern "C" fn strsignal(sig: c_int) -> *const c_char {
19804 static NAMES: [&[u8]; 32] = [
19805 b"Unknown signal\0",
19806 b"Hangup\0",
19807 b"Interrupt\0",
19808 b"Quit\0",
19809 b"Illegal instruction\0",
19810 b"Trace/breakpoint trap\0",
19811 b"Aborted\0",
19812 b"Bus error\0",
19813 b"Floating point exception\0",
19814 b"Killed\0",
19815 b"User defined signal 1\0",
19816 b"Segmentation fault\0",
19817 b"User defined signal 2\0",
19818 b"Broken pipe\0",
19819 b"Alarm clock\0",
19820 b"Terminated\0",
19821 b"Stack fault\0",
19822 b"Child process status\0",
19823 b"Continued\0",
19824 b"Stopped (signal)\0",
19825 b"Stopped\0",
19826 b"Stopped (tty input)\0",
19827 b"Stopped (tty output)\0",
19828 b"Urgent I/O condition\0",
19829 b"CPU time limit exceeded\0",
19830 b"File size limit exceeded\0",
19831 b"Virtual timer expired\0",
19832 b"Profiling timer expired\0",
19833 b"Window changed\0",
19834 b"I/O possible\0",
19835 b"Power failure\0",
19836 b"Bad system call\0",
19837 ];
19838 static mut RT_BUF: [c_char; 32] = [0; 32];
19839 if sig > 0 && sig < 32 {
19840 return NAMES[sig as usize].as_ptr() as *const c_char;
19841 }
19842 if sig >= 32 && sig < 65 {
19843 let mut o = 0usize;
19844 for &c in b"Real-time signal \0" {
19845 if c == 0 { break; }
19846 RT_BUF[o] = c as c_char;
19847 o += 1;
19848 }
19849 let mut v = (sig - 32) as u32;
19850 let mut digits = [0u8; 10];
19851 let mut d = 0usize;
19852 if v == 0 { digits[0] = b'0'; d = 1; }
19853 while v > 0 { digits[d] = b'0' + (v % 10) as u8; v /= 10; d += 1; }
19854 while d > 0 { d -= 1; RT_BUF[o] = digits[d] as c_char; o += 1; }
19855 RT_BUF[o] = 0;
19856 return RT_BUF.as_ptr();
19857 }
19858 b"Unknown signal\0".as_ptr() as *const c_char
19859}
19860
19861#[no_mangle]
19862pub unsafe extern "C" fn __strerror_l(errnum: i32, _loc: *mut core::ffi::c_void) -> *const core::ffi::c_char {
19863 crate::strerror(errnum)
19864}
19865
19866#[no_mangle]
19871pub unsafe extern "C" fn preadv(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64) -> isize {
19872 <Arch as Syscalls>::syscall4(sysno(295, 69), fd as i64, iov as i64, iovcnt as i64, offset) as isize
19873}
19874
19875#[no_mangle]
19876pub unsafe extern "C" fn pwritev(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64) -> isize {
19877 <Arch as Syscalls>::syscall4(sysno(296, 70), fd as i64, iov as i64, iovcnt as i64, offset) as isize
19878}
19879
19880#[no_mangle]
19881pub unsafe extern "C" fn preadv2(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64, flags: u32) -> isize {
19882 <Arch as Syscalls>::syscall5(sysno(327, 286), fd as i64, iov as i64, iovcnt as i64, offset, flags as i64) as isize
19883}
19884
19885#[no_mangle]
19886pub unsafe extern "C" fn pwritev2(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64, flags: u32) -> isize {
19887 <Arch as Syscalls>::syscall5(sysno(328, 287), fd as i64, iov as i64, iovcnt as i64, offset, flags as i64) as isize
19888}
19889
19890#[no_mangle]
19895pub unsafe extern "C" fn nice(inc: i32) -> i32 {
19896 let r = <Arch as Syscalls>::syscall2(SYS_GETPRIORITY, 0, 0);
19897 if r < 0 { return -1; }
19898 <Arch as Syscalls>::syscall2(SYS_SETPRIORITY, 0, r + inc as i64) as i32
19899}
19900
19901#[no_mangle]
19906pub unsafe extern "C" fn l64a(value: i64) -> *mut core::ffi::c_char {
19907 static mut BUF: [core::ffi::c_char; 7] = [0; 7];
19908 let mut v = value as u64;
19909 let mut i = 0;
19910 while v > 0 && i < 6 {
19911 let c = (v & 0x3f) as u8;
19912 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;
19913 v >>= 6;
19914 i += 1;
19915 }
19916 BUF[i] = 0;
19917 BUF.as_mut_ptr()
19918}
19919
19920#[no_mangle]
19921pub unsafe extern "C" fn lchmod(path: *const core::ffi::c_char, mode: u32) -> i32 {
19922 <Arch as Syscalls>::syscall4(SYS_FCHMODAT, AT_FDCWD as i64, path as i64, mode as i64, 0x100) as i32
19923}
19924
19925#[no_mangle]
19926pub unsafe extern "C" fn lutimes(filename: *const core::ffi::c_char, times: *const core::ffi::c_void) -> i32 {
19927 utimensat(AT_FDCWD, filename, times as *const timespec, 0x100)
19928}
19929
19930#[no_mangle]
19931pub unsafe extern "C" fn mknod(pathname: *const core::ffi::c_char, mode: u32, dev: u64) -> i32 {
19932 #[cfg(target_arch = "x86_64")]
19933 { <Arch as Syscalls>::syscall3(SYS_MKNOD, pathname as i64, mode as i64, dev as i64) as i32 }
19934 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
19935 {
19936 <Arch as Syscalls>::syscall4(SYS_MKNODAT, AT_FDCWD as i64, pathname as i64, mode as i64, dev as i64) as i32
19937 }
19938}
19939
19940#[no_mangle]
19941pub unsafe extern "C" fn memfd_create(name: *const core::ffi::c_char, flags: u32) -> i32 {
19942 <Arch as Syscalls>::syscall2(sysno(319, 279), name as i64, flags as i64) as i32
19943}
19944
19945#[no_mangle]
19946pub unsafe extern "C" fn mlock2(addr: *const core::ffi::c_void, len: usize, flags: u32) -> i32 {
19947 <Arch as Syscalls>::syscall3(sysno(325, 284), addr as i64, len as i64, flags as i64) as i32
19948}
19949
19950
19951
19952#[no_mangle]
19953pub unsafe extern "C" fn remap_file_pages(addr: *mut core::ffi::c_void, size: usize, prot: i32, pgoff: usize, flags: u32) -> i32 {
19954 <Arch as Syscalls>::syscall5(sysno(216, 234), addr as i64, size as i64, prot as i64, pgoff as i64, flags as i64) as i32
19955}
19956
19957#[no_mangle]
19962pub unsafe extern "C" fn nan(_tagp: *const core::ffi::c_char) -> f64 {
19963 f64::NAN
19964}
19965
19966#[no_mangle]
19967pub unsafe extern "C" fn nanf(_tagp: *const core::ffi::c_char) -> f32 {
19968 f32::NAN
19969}
19970
19971#[no_mangle]
19976pub unsafe extern "C" fn __lgammal_r(x: f64, signgamp: *mut i32) -> f64 {
19977 *signgamp = 1;
19978 lgamma(x)
19979}
19980
19981#[no_mangle]
19982pub unsafe extern "C" fn __libc_current_sigrtmax() -> i32 {
19983 64
19984}
19985
19986#[no_mangle]
19987pub unsafe extern "C" fn _longjmp(env: *mut core::ffi::c_void, val: i32) {
19988 crate::longjmp(env as *mut u64, val)
19989}
19990
19991#[no_mangle]
19992pub unsafe extern "C" fn __newlocale(_mask: i32, _name: *const core::ffi::c_char, base: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
19993 base
19994}
19995
19996#[no_mangle]
19997pub unsafe extern "C" fn __nl_langinfo(_item: i32) -> *mut core::ffi::c_char {
19998 b"\0".as_ptr() as *mut core::ffi::c_char
19999}
20000
20001#[no_mangle]
20002pub unsafe extern "C" fn __nl_langinfo_l(_item: i32, _loc: *mut core::ffi::c_void) -> *mut core::ffi::c_char {
20003 b"\0".as_ptr() as *mut core::ffi::c_char
20004}
20005
20006#[no_mangle]
20007pub unsafe extern "C" fn ns_get16(cp: *const u8) -> u16 {
20008 ((*cp.add(0) as u16) << 8) | *cp.add(1) as u16
20009}
20010
20011#[no_mangle]
20012pub unsafe extern "C" fn ns_get32(cp: *const u8) -> u32 {
20013 ((*cp.add(0) as u32) << 24) | ((*cp.add(1) as u32) << 16) | ((*cp.add(2) as u32) << 8) | *cp.add(3) as u32
20014}
20015
20016#[no_mangle]
20017pub unsafe extern "C" fn ns_put16(s: u16, dst: *mut u8) {
20018 *dst.add(0) = (s >> 8) as u8;
20019 *dst.add(1) = (s & 0xff) as u8;
20020}
20021
20022#[no_mangle]
20023pub unsafe extern "C" fn ns_put32(l: u32, dst: *mut u8) {
20024 *dst.add(0) = (l >> 24) as u8;
20025 *dst.add(1) = ((l >> 16) & 0xff) as u8;
20026 *dst.add(2) = ((l >> 8) & 0xff) as u8;
20027 *dst.add(3) = (l & 0xff) as u8;
20028}
20029
20030#[no_mangle]
20031pub unsafe extern "C" fn posix_close(fd: i32) -> i32 {
20032 crate::close(fd)
20033}
20034
20035#[no_mangle]
20036pub unsafe extern "C" fn posix_openpt(flags: i32) -> i32 {
20037 crate::open(b"/dev/ptmx\0".as_ptr() as *const core::ffi::c_char, flags, 0)
20038}
20039
20040#[no_mangle]
20041pub unsafe extern "C" fn putw(w: i32, f: *mut core::ffi::c_void) {
20042 putc((w & 0xff) as i32, f as *mut FILE);
20043 putc(((w >> 8) & 0xff) as i32, f as *mut FILE);
20044 putc(((w >> 16) & 0xff) as i32, f as *mut FILE);
20045 putc(((w >> 24) & 0xff) as i32, f as *mut FILE);
20046}
20047
20048
20049
20050#[no_mangle]
20051pub unsafe extern "C" fn rand_r(seedp: *mut u32) -> i32 {
20052 let seed = (*seedp).wrapping_mul(1103515245).wrapping_add(12345);
20053 *seedp = seed;
20054 ((seed >> 16) & 0x7fff) as i32
20055}
20056
20057#[no_mangle]
20058pub unsafe extern "C" fn reallocarray(ptr: *mut core::ffi::c_void, nmemb: usize, size: usize) -> *mut core::ffi::c_void {
20059 let total = match nmemb.checked_mul(size) {
20060 Some(v) => v,
20061 None => { ERRNO = ENOMEM; return core::ptr::null_mut(); }
20062 };
20063 crate::realloc(ptr, total)
20064}
20065
20066#[no_mangle]
20067pub unsafe extern "C" fn __res_state() -> *mut core::ffi::c_void {
20068 static mut STATE: [u8; 512] = [0; 512];
20069 STATE.as_mut_ptr() as *mut core::ffi::c_void
20070}
20071
20072#[no_mangle]
20073pub unsafe extern "C" fn sbrk(increment: isize) -> *mut u8 {
20074 let cur = <Arch as Syscalls>::syscall1(sysno(12, 214), 0);
20075 if increment == 0 { return cur as *mut u8; }
20076 let new = cur + increment as i64;
20077 let r = <Arch as Syscalls>::syscall1(sysno(12, 214), new);
20078 if r < 0 { return -1isize as usize as *mut u8; }
20079 cur as *mut u8
20080}
20081
20082#[no_mangle]
20083pub unsafe extern "C" fn scalb(x: f64, exp: f64) -> f64 {
20084 if x.is_nan() || exp.is_nan() { return x * exp; }
20085 if !exp.is_finite() {
20086 let r = if exp > 0.0 { x * exp } else { x / (-exp) };
20087 if r.is_nan() && !x.is_nan() {
20088 feraiseexcept(FE_INVALID);
20089 }
20090 return r;
20091 }
20092 if libm::rint(exp) != exp {
20093 return __math_invalid(exp);
20094 }
20095 if exp > 65000.0 { return libm::scalbn(x, 65000); }
20096 if -exp > 65000.0 { return libm::scalbn(x, -65000); }
20097 libm::scalbn(x, exp as i32)
20098}
20099
20100#[no_mangle]
20101pub unsafe extern "C" fn scalbf(x: f32, exp: f32) -> f32 {
20102 if x.is_nan() || exp.is_nan() { return x * exp; }
20103 if !exp.is_finite() {
20104 let r = if exp > 0.0 { x * exp } else { x / (-exp) };
20105 if r.is_nan() && !x.is_nan() {
20106 feraiseexcept(FE_INVALID);
20107 }
20108 return r;
20109 }
20110 if libm::rintf(exp) != exp {
20111 return __math_invalidf(exp);
20112 }
20113 if exp > 65000.0 { return libm::scalbnf(x, 65000); }
20114 if -exp > 65000.0 { return libm::scalbnf(x, -65000); }
20115 libm::scalbnf(x, exp as i32)
20116}
20117
20118#[no_mangle]
20119pub unsafe extern "C" fn __sched_cpucount(setsize: usize, setp: *const u8) -> i32 {
20120 let mut count = 0;
20121 let mut i = 0;
20122 while i < setsize * 8 {
20123 if (*setp.add(i / 8) >> (i % 8)) & 1 != 0 { count += 1; }
20124 i += 1;
20125 }
20126 count
20127}
20128
20129
20130
20131#[no_mangle]
20132pub unsafe extern "C" fn select(nfds: i32, readfds: *mut u8, writefds: *mut u8, exceptfds: *mut u8, timeout: *mut core::ffi::c_void) -> i32 {
20133 <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
20134}
20135
20136
20137
20138#[no_mangle]
20139pub unsafe extern "C" fn sendfile(out_fd: i32, in_fd: i32, offset: *mut i64, count: usize) -> isize {
20140 <Arch as Syscalls>::syscall4(sysno(40, 71), out_fd as i64, in_fd as i64, offset as i64, count as i64) as isize
20141}
20142
20143
20144
20145
20146
20147#[no_mangle]
20148pub unsafe extern "C" fn __setjmp(env: *mut core::ffi::c_void) -> i32 {
20149 crate::setjmp(env as *mut u64)
20150}
20151
20152#[no_mangle]
20153pub unsafe extern "C" fn _setjmp(env: *mut core::ffi::c_void) -> i32 {
20154 crate::setjmp(env as *mut u64)
20155}
20156
20157#[no_mangle]
20158pub unsafe extern "C" fn setlinebuf(stream: *mut core::ffi::c_void) {
20159 setvbuf(stream as *mut FILE, core::ptr::null_mut(), 1, 0);
20160}
20161
20162
20163
20164
20165
20166
20167
20168
20169
20170
20171
20172
20173
20174
20175
20176#[no_mangle]
20177pub unsafe extern "C" fn significand(x: f64) -> f64 {
20178 let bits = x.to_bits();
20179 let exp = ((bits >> 52) & 0x7ff) as i32;
20180 if exp == 0 || exp == 0x7ff { return x; }
20181 f64::from_bits((bits & 0x000fffffffffffff) | (1023u64 << 52))
20182}
20183
20184#[no_mangle]
20185pub unsafe extern "C" fn significandf(x: f32) -> f32 {
20186 let bits = x.to_bits();
20187 let exp = ((bits >> 23) & 0xff) as i32;
20188 if exp == 0 || exp == 0xff { return x; }
20189 f32::from_bits((bits & 0x007fffff) | (127u32 << 23))
20190}
20191
20192
20193
20194
20195
20196#[no_mangle]
20197pub unsafe extern "C" fn sigset(_sig: i32, handler: Option<unsafe extern "C" fn(i32)>) -> Option<unsafe extern "C" fn(i32)> {
20198 handler
20199}
20200
20201#[no_mangle]
20202pub unsafe extern "C" fn sincos(x: f64, sin: *mut f64, cos: *mut f64) {
20203 *sin = libm::sin(x);
20204 *cos = libm::cos(x);
20205}
20206
20207#[no_mangle]
20208pub unsafe extern "C" fn sincosf(x: f32, sin: *mut f32, cos: *mut f32) {
20209 *sin = libm::sinf(x);
20210 *cos = libm::cosf(x);
20211}
20212
20213
20214
20215
20216
20217
20218
20219
20220
20221unsafe fn nd_ascii_lower(c: c_char) -> c_int {
20222 let b = c as u8;
20223 if b >= b'A' && b <= b'Z' { (b + 32) as c_int } else { b as c_int }
20224}
20225
20226unsafe fn nd_strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
20227 let mut i = 0usize;
20228 while i < n {
20229 let c1 = nd_ascii_lower(*s1.add(i));
20230 let c2 = nd_ascii_lower(*s2.add(i));
20231 if c1 != c2 || c1 == 0 { return c1 - c2; }
20232 i += 1;
20233 }
20234 0
20235}
20236
20237#[no_mangle]
20238pub unsafe extern "C" fn strcasecmp(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char) -> i32 {
20239 nd_strncasecmp(s1, s2, usize::MAX)
20240}
20241
20242#[no_mangle]
20243pub 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 {
20244 nd_strncasecmp(s1, s2, usize::MAX)
20245}
20246
20247#[no_mangle]
20248pub unsafe extern "C" fn strcasestr(haystack: *const core::ffi::c_char, needle: *const core::ffi::c_char) -> *mut core::ffi::c_char {
20249 let nlen = crate::strlen(needle);
20250 if nlen == 0 { return haystack as *mut core::ffi::c_char; }
20251 let mut i = 0;
20252 loop {
20253 let h = haystack.add(i);
20254 if *h == 0 { return core::ptr::null_mut(); }
20255 if crate::strncasecmp(h, needle, nlen) == 0 { return h as *mut core::ffi::c_char; }
20256 i += 1;
20257 }
20258}
20259
20260#[no_mangle]
20261pub 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 {
20262 crate::strcmp(s1 as *const u8, s2 as *const u8)
20263}
20264
20265#[no_mangle]
20266pub unsafe extern "C" fn strncasecmp(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char, n: usize) -> i32 {
20267 nd_strncasecmp(s1, s2, n)
20268}
20269
20270#[no_mangle]
20271pub 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 {
20272 nd_strncasecmp(s1, s2, n)
20273}
20274
20275#[no_mangle]
20276pub unsafe extern "C" fn strsep(stringp: *mut *mut core::ffi::c_char, delim: *const core::ffi::c_char) -> *mut core::ffi::c_char {
20277 let s = *stringp;
20278 if s.is_null() { return core::ptr::null_mut(); }
20279 let mut p = s;
20280 while *p != 0 {
20281 let mut d = delim;
20282 while *d != 0 {
20283 if *p == *d { *p = 0; *stringp = p.add(1); return s; }
20284 d = d.add(1);
20285 }
20286 p = p.add(1);
20287 }
20288 *stringp = core::ptr::null_mut();
20289 s
20290}
20291
20292#[no_mangle]
20293pub unsafe extern "C" fn strtoimax(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, base: i32) -> i64 {
20294 crate::strtol(nptr, endptr, base)
20295}
20296
20297#[no_mangle]
20298pub 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 {
20299 let mut s = if s.is_null() { *saveptr } else { s };
20300 if s.is_null() { return core::ptr::null_mut(); }
20301 while *s != 0 {
20303 let mut d = delim;
20304 let mut found = false;
20305 while *d != 0 {
20306 if *s == *d { found = true; break; }
20307 d = d.add(1);
20308 }
20309 if !found { break; }
20310 s = s.add(1);
20311 }
20312 if *s == 0 { *saveptr = s; return core::ptr::null_mut(); }
20313 let start = s;
20314 while *s != 0 {
20316 let mut d = delim;
20317 while *d != 0 {
20318 if *s == *d { *s = 0; *saveptr = s.add(1); return start; }
20319 d = d.add(1);
20320 }
20321 s = s.add(1);
20322 }
20323 *saveptr = s;
20324 start
20325}
20326
20327#[no_mangle]
20328pub unsafe extern "C" fn strtoumax(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, base: i32) -> u64 {
20329 crate::strtoul(nptr, endptr, base) as u64
20330}
20331
20332#[no_mangle]
20333pub 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 {
20334 crate::strlcpy(dest as *mut u8, src as *const u8, n)
20335}
20336
20337#[no_mangle]
20338pub unsafe extern "C" fn swab(src: *const u8, dest: *mut u8, nbytes: isize) {
20339 let mut i = 0;
20340 while i + 1 < nbytes {
20341 let a = *src.add(i as usize);
20342 let b = *src.add(i as usize + 1);
20343 *dest.add(i as usize) = b;
20344 *dest.add(i as usize + 1) = a;
20345 i += 2;
20346 }
20347}
20348
20349
20350
20351
20352
20353
20354
20355
20356
20357
20358
20359#[no_mangle]
20360pub unsafe extern "C" fn __tls_get_addr(ti: *mut core::ffi::c_void) -> *mut u8 {
20361 let p = ti as *mut usize;
20363 let _module_id = *p;
20364 let offset = *p.add(1);
20365 static mut TLS_BUF: [u8; 4096] = [0; 4096];
20367 TLS_BUF.as_mut_ptr().add(offset)
20368}
20369
20370#[no_mangle]
20371pub unsafe extern "C" fn __tolower_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20372 if c >= 'A' as i32 && c <= 'Z' as i32 { c + 32 } else { c }
20373}
20374
20375#[no_mangle]
20376pub unsafe extern "C" fn __toupper_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20377 if c >= 'a' as i32 && c <= 'z' as i32 { c - 32 } else { c }
20378}
20379
20380#[no_mangle]
20381pub unsafe extern "C" fn ulimit(cmd: c_int, mut args: ...) -> c_long {
20382 let mut rl: Rlimit = core::mem::zeroed();
20383 if getrlimit(RLIMIT_FSIZE, &mut rl) != 0 { return -1; }
20384 if cmd == 2 {
20385 let val = args.next_arg::<c_long>();
20386 rl.rlim_cur = 512u64.wrapping_mul(val as u64);
20387 if setrlimit(RLIMIT_FSIZE, &rl) != 0 { return -1; }
20388 }
20389 (rl.rlim_cur / 512) as c_long
20390}
20391
20392#[repr(C)]
20393struct UtsName {
20394 sysname: [u8; 65],
20395 nodename: [u8; 65],
20396 release: [u8; 65],
20397 version: [u8; 65],
20398 machine: [u8; 65],
20399 domainname: [u8; 65],
20400}
20401
20402#[no_mangle]
20403pub unsafe extern "C" fn uname(buf: *mut c_void) -> c_int {
20404 if buf.is_null() { ERRNO = EINVAL; return -1; }
20405 let mut uts: UtsName = core::mem::zeroed();
20406 let r = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
20407 if r < 0 { ERRNO = (-r) as c_int; return -1; }
20408 core::ptr::copy_nonoverlapping(&uts as *const UtsName as *const u8, buf as *mut u8, core::mem::size_of::<UtsName>());
20409 0
20410}
20411
20412#[no_mangle]
20413pub unsafe extern "C" fn unshare(flags: i32) -> i32 {
20414 let r = <Arch as Syscalls>::syscall1(SYS_UNSHARE, flags as i64);
20415 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
20416}
20417
20418#[no_mangle]
20419pub unsafe extern "C" fn updwtmpx(wtmpx_file: *const core::ffi::c_char, utx: *const core::ffi::c_void) {
20420 updwtmp(wtmpx_file, utx)
20421}
20422
20423#[no_mangle]
20424pub unsafe extern "C" fn __uselocale(loc: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
20425 loc
20426}
20427
20428#[repr(C)]
20429pub struct Utimbuf { actime: i64, modtime: i64 }
20430
20431#[no_mangle]
20432pub unsafe extern "C" fn utime(filename: *const c_char, times: *const Utimbuf) -> c_int {
20433 if times.is_null() {
20434 return utimensat(AT_FDCWD, filename, core::ptr::null(), 0);
20435 }
20436 let ts = [
20437 timespec { tv_sec: (*times).actime, tv_nsec: 0 },
20438 timespec { tv_sec: (*times).modtime, tv_nsec: 0 },
20439 ];
20440 utimensat(AT_FDCWD, filename, ts.as_ptr(), 0)
20441}
20442
20443#[no_mangle]
20444pub unsafe extern "C" fn vhangup() -> c_int {
20445 let r = <Arch as Syscalls>::syscall0(SYS_VHANGUP);
20446 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
20447}
20448
20449#[no_mangle]
20450pub unsafe extern "C" fn vmsplice(fd: i32, iov: *const c_void, nr_segs: usize, flags: u32) -> isize {
20451 let r = <Arch as Syscalls>::syscall4(SYS_VMSPLICE, fd as i64, iov as i64, nr_segs as i64, flags as i64);
20452 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
20453}
20454
20455
20456
20457#[no_mangle]
20458pub unsafe extern "C" fn wait4(pid: i32, wstatus: *mut i32, options: i32, rusage: *mut core::ffi::c_void) -> i32 {
20459 <Arch as Syscalls>::syscall4(SYS_WAIT4, pid as i64, wstatus as i64, options as i64, rusage as i64) as i32
20460}
20461
20462#[no_mangle]
20463pub unsafe extern "C" fn waitid(idtype: i32, id: u32, infop: *mut core::ffi::c_void, options: i32) -> i32 {
20464 <Arch as Syscalls>::syscall4(sysno(247, 95), idtype as i64, id as i64, infop as i64, options as i64) as i32
20465}
20466
20467#[no_mangle]
20468pub unsafe extern "C" fn __wcscoll_l(s1: *const u32, s2: *const u32, _loc: *mut core::ffi::c_void) -> i32 {
20469 crate::wcscmp(s1 as *const i32, s2 as *const i32)
20470}
20471
20472#[no_mangle]
20473pub unsafe extern "C" fn __wcsxfrm_l(dest: *mut u32, src: *const u32, n: usize, _loc: *mut core::ffi::c_void) -> usize {
20474 crate::wcscpy(dest as *mut i32, src as *const i32);
20475 n
20476}
20477
20478#[no_mangle]
20479pub unsafe extern "C" fn wcwidth(c: u32) -> i32 {
20480 if c == 0 { return 0; }
20481 if c < 32 || (c >= 0x7f && c < 0xa0) { return -1; }
20482 1
20483}
20484
20485
20486
20487
20488
20489#[no_mangle]
20496pub 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 {
20497 crate::strtod(nptr, endptr)
20498}
20499
20500#[no_mangle]
20501pub 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 {
20502 crate::strtof(nptr, endptr)
20503}
20504
20505#[no_mangle]
20506pub 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 {
20507 crate::strtod(nptr, endptr)
20508}
20509
20510#[repr(C)]
20515struct linux_dirent64 {
20516 d_ino: u64,
20517 d_off: i64,
20518 d_reclen: u16,
20519 d_type: u8,
20520 d_name: [u8; 0], }
20522
20523static mut DIR_BUF: [u8; 1024] = [0; 1024];
20524static mut DIR_FD: i32 = -1;
20525static mut DIR_POS: usize = 0;
20526static mut DIR_LEN: usize = 0;
20527
20528#[no_mangle]
20529pub unsafe extern "C" fn opendir(dirname: *const core::ffi::c_char) -> *mut core::ffi::c_void {
20530 let fd = openat(AT_FDCWD, dirname, O_DIRECTORY, 0); if fd < 0 { return core::ptr::null_mut(); }
20532 DIR_FD = fd;
20533 DIR_POS = 0;
20534 DIR_LEN = 0;
20535 &DIR_FD as *const i32 as *mut core::ffi::c_void
20536}
20537
20538#[no_mangle]
20539pub unsafe extern "C" fn closedir(dirp: *mut core::ffi::c_void) -> i32 {
20540 if dirp.is_null() { return -1; }
20541 let fd = *(dirp as *const i32);
20542 crate::close(fd)
20543}
20544
20545#[no_mangle]
20546pub unsafe extern "C" fn readdir(dirp: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
20547 if dirp.is_null() { return core::ptr::null_mut(); }
20548 let fd = *(dirp as *const i32);
20549
20550 loop {
20551 if DIR_POS >= DIR_LEN {
20552 let nread = <Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, DIR_BUF.as_mut_ptr() as i64, 1024) as isize;
20553 if nread <= 0 { return core::ptr::null_mut(); }
20554 DIR_LEN = nread as usize;
20555 DIR_POS = 0;
20556 }
20557
20558 let ent = DIR_BUF.as_ptr().add(DIR_POS) as *const linux_dirent64;
20559 let ent_ref = &*ent;
20560 DIR_POS += ent_ref.d_reclen as usize;
20561
20562 return ent as *mut core::ffi::c_void;
20564 }
20565}
20566
20567#[no_mangle]
20568pub 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 {
20569 let ent = readdir(dirp);
20570 if ent.is_null() {
20571 *result = core::ptr::null_mut();
20572 } else {
20573 *result = ent;
20574 }
20575 0
20576}
20577
20578#[no_mangle]
20579pub unsafe extern "C" fn seekdir(dirp: *mut core::ffi::c_void, loc: i64) {
20580 if dirp.is_null() { return; }
20581 let fd = *(dirp as *const i32);
20582 <Arch as Syscalls>::syscall3(SYS_LSEEK, fd as i64, loc, 0);
20583}
20584
20585#[no_mangle]
20586pub unsafe extern "C" fn telldir(_dirp: *mut core::ffi::c_void) -> i64 {
20587 DIR_POS as i64
20588}
20589
20590#[no_mangle]
20591pub unsafe extern "C" fn rewinddir(_dirp: *mut core::ffi::c_void) {
20592 DIR_POS = 0;
20593 DIR_LEN = 0;
20594}
20595
20596#[no_mangle]
20597pub unsafe extern "C" fn dirfd(dirp: *mut core::ffi::c_void) -> i32 {
20598 if dirp.is_null() { return -1; }
20599 unsafe { *(dirp as *const i32) }
20600}
20601
20602#[no_mangle]
20607pub unsafe extern "C" fn mprotect(addr: *mut u8, len: usize, prot: i32) -> i32 {
20608 <Arch as Syscalls>::syscall3(SYS_MPROTECT, addr as i64, len as i64, prot as i64) as i32
20609}
20610
20611#[no_mangle]
20612pub unsafe extern "C" fn msync(addr: *mut u8, len: usize, flags: i32) -> i32 {
20613 <Arch as Syscalls>::syscall3(sysno(26, 227), addr as i64, len as i64, flags as i64) as i32
20614}
20615
20616#[no_mangle]
20617pub unsafe extern "C" fn mlock(addr: *const u8, len: usize) -> i32 {
20618 <Arch as Syscalls>::syscall2(sysno(149, 228), addr as i64, len as i64) as i32
20619}
20620
20621#[no_mangle]
20622pub unsafe extern "C" fn munlock(addr: *const u8, len: usize) -> i32 {
20623 <Arch as Syscalls>::syscall2(sysno(150, 229), addr as i64, len as i64) as i32
20624}
20625
20626#[no_mangle]
20627pub unsafe extern "C" fn mlockall(flags: i32) -> i32 {
20628 <Arch as Syscalls>::syscall1(sysno(151, 230), flags as i64) as i32
20629}
20630
20631#[no_mangle]
20632pub unsafe extern "C" fn munlockall() -> i32 {
20633 <Arch as Syscalls>::syscall0(sysno(152, 231)) as i32
20634}
20635
20636#[no_mangle]
20637pub unsafe extern "C" fn madvise(addr: *mut u8, len: usize, advice: i32) -> i32 {
20638 <Arch as Syscalls>::syscall3(sysno(28, 233), addr as i64, len as i64, advice as i64) as i32
20639}
20640
20641#[no_mangle]
20642pub unsafe extern "C" fn mincore(addr: *mut u8, len: usize, vec: *mut u8) -> i32 {
20643 <Arch as Syscalls>::syscall3(sysno(27, 232), addr as i64, len as i64, vec as i64) as i32
20644}
20645
20646#[no_mangle]
20653pub unsafe extern "C" fn drem(x: f64, y: f64) -> f64 {
20654 remainder(x, y)
20655}
20656
20657#[no_mangle]
20658pub unsafe extern "C" fn dremf(x: f32, y: f32) -> f32 {
20659 remainderf(x, y)
20660}
20661
20662#[no_mangle]
20663pub unsafe extern "C" fn pow10(x: f64) -> f64 {
20664 libm::pow(10.0, x)
20665}
20666
20667#[no_mangle]
20668pub unsafe extern "C" fn pow10f(x: f32) -> f32 {
20669 libm::powf(10.0, x)
20670}
20671
20672#[no_mangle]
20673pub unsafe extern "C" fn pow10l(x: f64) -> f64 {
20674 libm::pow(10.0, x)
20675}
20676
20677#[no_mangle]
20678pub unsafe extern "C" fn isless(x: f64, y: f64) -> i32 {
20679 if x.is_nan() || y.is_nan() { 0 } else { (x < y) as i32 }
20680}
20681
20682#[no_mangle]
20683pub unsafe extern "C" fn islessf(x: f32, y: f32) -> i32 {
20684 if x.is_nan() || y.is_nan() { 0 } else { (x < y) as i32 }
20685}
20686
20687#[no_mangle]
20688pub unsafe extern "C" fn lgamma_r(x: f64, signgamp: *mut i32) -> f64 {
20689 lgamma_r_impl(x, signgamp)
20690}
20691
20692#[no_mangle]
20693pub unsafe extern "C" fn lgammaf_r(x: f32, signgamp: *mut i32) -> f32 {
20694 if x.is_nan() {
20695 if !signgamp.is_null() { *signgamp = 1; }
20696 return x;
20697 }
20698 if x == 0.0 {
20699 if !signgamp.is_null() { *signgamp = if x.is_sign_negative() { -1 } else { 1 }; }
20700 feraiseexcept(FE_DIVBYZERO);
20701 return f32::INFINITY;
20702 }
20703 let (r, sign) = libm::lgammaf_r(x);
20704 if !signgamp.is_null() { *signgamp = sign; }
20705 r
20706}
20707
20708#[no_mangle]
20709pub unsafe extern "C" fn lgammal_r(x: f64, signgamp: *mut i32) -> f64 {
20710 lgamma_r(x, signgamp)
20711}
20712
20713#[no_mangle]
20718pub unsafe extern "C" fn islessequal(x: f64, y: f64) -> i32 {
20719 if x.is_nan() || y.is_nan() { 0 } else { (x <= y) as i32 }
20720}
20721
20722#[no_mangle]
20723pub unsafe extern "C" fn islessequalf(x: f32, y: f32) -> i32 {
20724 if x.is_nan() || y.is_nan() { 0 } else { (x <= y) as i32 }
20725}
20726
20727#[no_mangle]
20728pub unsafe extern "C" fn islessgreater(x: f64, y: f64) -> i32 {
20729 if x.is_nan() || y.is_nan() { 0 } else { (x < y || x > y) as i32 }
20730}
20731
20732#[no_mangle]
20733pub unsafe extern "C" fn islessgreaterf(x: f32, y: f32) -> i32 {
20734 if x.is_nan() || y.is_nan() { 0 } else { (x < y || x > y) as i32 }
20735}
20736
20737#[no_mangle]
20738pub unsafe extern "C" fn isgreater(x: f64, y: f64) -> i32 {
20739 if x.is_nan() || y.is_nan() { 0 } else { (x > y) as i32 }
20740}
20741
20742#[no_mangle]
20743pub unsafe extern "C" fn isgreaterf(x: f32, y: f32) -> i32 {
20744 if x.is_nan() || y.is_nan() { 0 } else { (x > y) as i32 }
20745}
20746
20747#[no_mangle]
20748pub unsafe extern "C" fn isgreaterequal(x: f64, y: f64) -> i32 {
20749 if x.is_nan() || y.is_nan() { 0 } else { (x >= y) as i32 }
20750}
20751
20752#[no_mangle]
20753pub unsafe extern "C" fn isgreaterequalf(x: f32, y: f32) -> i32 {
20754 if x.is_nan() || y.is_nan() { 0 } else { (x >= y) as i32 }
20755}
20756
20757#[no_mangle]
20762pub unsafe extern "C" fn stpcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char {
20763 let mut d = dest;
20764 let mut s = src;
20765 while *s != 0 {
20766 *d = *s;
20767 d = d.add(1);
20768 s = s.add(1);
20769 }
20770 *d = 0;
20771 d
20772}
20773
20774#[no_mangle]
20775pub unsafe extern "C" fn stpncpy(dest: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
20776 let mut i = 0;
20777 while i < n && *src.add(i) != 0 {
20778 *dest.add(i) = *src.add(i);
20779 i += 1;
20780 }
20781 let end = dest.add(i);
20782 while i < n {
20783 *dest.add(i) = 0;
20784 i += 1;
20785 }
20786 end
20787}
20788
20789#[no_mangle]
20790pub unsafe extern "C" fn strchrnul(s: *const c_char, c: c_int) -> *mut c_char {
20791 let mut p = s;
20792 while *p != 0 && *p as c_int != c {
20793 p = p.add(1);
20794 }
20795 p as *mut c_char
20796}
20797
20798#[no_mangle]
20799pub unsafe extern "C" fn fstatat(dirfd: c_int, path: *const c_char, buf: *mut Stat, flags: c_int) -> c_int {
20800 let r = sys_newfstatat(dirfd, path, buf as *mut u8, flags);
20801 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
20802}
20803
20804#[no_mangle]
20805pub unsafe extern "C" fn execvpe(
20806 file: *const c_char,
20807 argv: *const *const c_char,
20808 envp: *const *const c_char,
20809) -> c_int {
20810 if file.is_null() { return -1; }
20811 let mut has_slash = false;
20812 let mut p = file;
20813 while *p != 0 {
20814 if *p == b'/' as c_char { has_slash = true; break; }
20815 p = p.add(1);
20816 }
20817 if has_slash {
20818 return execve(file, argv, envp) as c_int;
20819 }
20820
20821 let file_len = crate::strlen(file);
20822 let path = crate::getenv(b"PATH\0".as_ptr() as *const c_char);
20823 if path.is_null() {
20824 return execve(file, argv, envp) as c_int;
20825 }
20826
20827 let mut buf = [0 as c_char; 4096];
20828 let mut dir = path;
20829 loop {
20830 let mut end = dir;
20831 while *end != 0 && *end != b':' as c_char { end = end.add(1); }
20832 let dlen = end.offset_from(dir) as usize;
20833 if dlen + 1 + file_len < buf.len() {
20834 let mut i = 0;
20835 while i < dlen {
20836 buf[i] = *dir.add(i);
20837 i += 1;
20838 }
20839 buf[i] = b'/' as c_char;
20840 i += 1;
20841 let mut j = 0;
20842 while j < file_len {
20843 buf[i + j] = *file.add(j);
20844 j += 1;
20845 }
20846 buf[i + j] = 0;
20847 execve(buf.as_ptr(), argv, envp);
20848 }
20849 if *end == 0 { break; }
20850 dir = end.add(1);
20851 }
20852 -1
20853}
20854
20855#[no_mangle]
20858pub unsafe extern "C" fn strcoll_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int {
20859 strcoll(s1, s2)
20860}
20861
20862#[no_mangle]
20863pub unsafe extern "C" fn strxfrm_l(dest: *mut c_char, src: *const c_char, n: usize, _loc: locale_t) -> usize {
20864 strxfrm(dest, src, n)
20865}
20866
20867#[no_mangle]
20868pub unsafe extern "C" fn strerror_l(errnum: c_int, _loc: locale_t) -> *mut c_char {
20869 strerror(errnum)
20870}
20871
20872#[no_mangle]
20873pub unsafe extern "C" fn strcasecmp_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int {
20874 strcasecmp(s1, s2)
20875}
20876
20877#[no_mangle]
20878pub unsafe extern "C" fn strncasecmp_l(s1: *const c_char, s2: *const c_char, n: usize, _loc: locale_t) -> c_int {
20879 strncasecmp(s1, s2, n)
20880}
20881
20882#[no_mangle]
20883pub unsafe extern "C" fn strftime_l(s: *mut c_char, max: usize, fmt: *const c_char, tm: *const tm, _loc: locale_t) -> usize {
20884 strftime(s, max, fmt, tm)
20885}
20886
20887#[no_mangle]
20888pub unsafe extern "C" fn nl_langinfo_l(item: c_int, _loc: locale_t) -> *mut c_char {
20889 nl_langinfo(item)
20890}
20891
20892#[no_mangle]
20893pub unsafe extern "C" fn wcscoll_l(s1: *const u32, s2: *const u32, _loc: locale_t) -> c_int {
20894 wcscoll(s1, s2)
20895}
20896
20897#[no_mangle]
20898pub unsafe extern "C" fn wcsxfrm_l(dst: *mut wchar_t, src: *const wchar_t, n: usize, _loc: locale_t) -> usize {
20899 wcsxfrm(dst, src, n)
20900}
20901
20902#[no_mangle]
20903pub unsafe extern "C" fn wcsftime_l(s: *mut u32, max: usize, fmt: *const u32, tm: *const c_void, _loc: locale_t) -> usize {
20904 wcsftime(s, max, fmt, tm)
20905}
20906
20907#[no_mangle]
20908pub unsafe extern "C" fn wctype_l(name: *const c_char, _loc: locale_t) -> wctype_t {
20909 wctype(name)
20910}
20911
20912#[no_mangle]
20913pub unsafe extern "C" fn wctrans_l(name: *const c_char, _loc: locale_t) -> wctrans_t {
20914 wctrans(name)
20915}
20916
20917#[no_mangle]
20918pub unsafe extern "C" fn towlower_l(c: wint_t, _loc: locale_t) -> wint_t {
20919 towlower(c)
20920}
20921
20922#[no_mangle]
20923pub unsafe extern "C" fn towupper_l(c: wint_t, _loc: locale_t) -> wint_t {
20924 towupper(c)
20925}
20926
20927#[no_mangle]
20928pub unsafe extern "C" fn towctrans_l(c: wint_t, desc: wctrans_t, _loc: locale_t) -> wint_t {
20929 towctrans(c, desc)
20930}
20931
20932#[no_mangle] pub unsafe extern "C" fn iswalnum_l(c: wint_t, _l: locale_t) -> c_int { iswalnum(c) }
20933#[no_mangle] pub unsafe extern "C" fn iswalpha_l(c: wint_t, _l: locale_t) -> c_int { iswalpha(c) }
20934#[no_mangle] pub unsafe extern "C" fn iswblank_l(c: wint_t, _l: locale_t) -> c_int { iswblank(c) }
20935#[no_mangle] pub unsafe extern "C" fn iswcntrl_l(c: wint_t, _l: locale_t) -> c_int { iswcntrl(c) }
20936#[no_mangle] pub unsafe extern "C" fn iswdigit_l(c: wint_t, _l: locale_t) -> c_int { iswdigit(c) }
20937#[no_mangle] pub unsafe extern "C" fn iswgraph_l(c: wint_t, _l: locale_t) -> c_int { iswgraph(c) }
20938#[no_mangle] pub unsafe extern "C" fn iswlower_l(c: wint_t, _l: locale_t) -> c_int { iswlower(c) }
20939#[no_mangle] pub unsafe extern "C" fn iswprint_l(c: wint_t, _l: locale_t) -> c_int { iswprint(c) }
20940#[no_mangle] pub unsafe extern "C" fn iswpunct_l(c: wint_t, _l: locale_t) -> c_int { iswpunct(c) }
20941#[no_mangle] pub unsafe extern "C" fn iswspace_l(c: wint_t, _l: locale_t) -> c_int { iswspace(c) }
20942#[no_mangle] pub unsafe extern "C" fn iswupper_l(c: wint_t, _l: locale_t) -> c_int { iswupper(c) }
20943#[no_mangle] pub unsafe extern "C" fn iswxdigit_l(c: wint_t, _l: locale_t) -> c_int { iswxdigit(c) }
20944#[no_mangle] pub unsafe extern "C" fn iswctype_l(c: wint_t, desc: wctype_t, _l: locale_t) -> c_int { iswctype(c, desc) }
20945
20946#[no_mangle] pub unsafe extern "C" fn __isoc99_scanf(fmt: *const c_char, args: ...) -> c_int { vfscanf(stdin, fmt, args) }
20948#[no_mangle] pub unsafe extern "C" fn __isoc99_fscanf(f: *mut FILE, fmt: *const c_char, args: ...) -> c_int { vfscanf(f, fmt, args) }
20949#[no_mangle] pub unsafe extern "C" fn __isoc99_sscanf(s: *const c_char, fmt: *const c_char, args: ...) -> c_int { vsscanf(s, fmt, args) }
20950#[no_mangle] pub unsafe extern "C" fn __isoc99_vscanf(fmt: *const c_char, args: VaList) -> c_int { vfscanf(stdin, fmt, args) }
20951#[no_mangle] pub unsafe extern "C" fn __isoc99_vfscanf(f: *mut FILE, fmt: *const c_char, args: VaList) -> c_int { vfscanf(f, fmt, args) }
20952#[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) }
20953#[no_mangle] pub unsafe extern "C" fn __isoc99_wscanf(fmt: *const wchar_t, args: ...) -> c_int { vfwscanf(stdin, fmt, args) }
20954#[no_mangle] pub unsafe extern "C" fn __isoc99_fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int { vfwscanf(f, fmt, args) }
20955#[no_mangle] pub unsafe extern "C" fn __isoc99_swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int { vswscanf(s, fmt, args) }
20956#[no_mangle] pub unsafe extern "C" fn __isoc99_vwscanf(fmt: *const wchar_t, args: VaList) -> c_int { vfwscanf(stdin, fmt, args) }
20957#[no_mangle] pub unsafe extern "C" fn __isoc99_vfwscanf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int { vfwscanf(f, fmt, args) }
20958#[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) }
20959
20960#[no_mangle] pub unsafe extern "C" fn clearerr_unlocked(f: *mut FILE) { clearerr(f) }
20963#[no_mangle] pub unsafe extern "C" fn feof_unlocked(f: *mut FILE) -> c_int { feof(f) }
20964#[no_mangle] pub unsafe extern "C" fn ferror_unlocked(f: *mut FILE) -> c_int { ferror(f) }
20965#[no_mangle] pub unsafe extern "C" fn fileno_unlocked(f: *mut FILE) -> c_int { fileno(f) }
20966#[no_mangle] pub unsafe extern "C" fn fflush_unlocked(f: *mut FILE) -> c_int { fflush(f) }
20967#[no_mangle] pub unsafe extern "C" fn fgetc_unlocked(f: *mut FILE) -> c_int { fgetc(f) }
20968#[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) }
20969#[no_mangle] pub unsafe extern "C" fn fputc_unlocked(c: c_int, f: *mut FILE) -> c_int { fputc(c, f) }
20970#[no_mangle] pub unsafe extern "C" fn fputs_unlocked(s: *const c_char, f: *mut FILE) -> c_int { fputs(s, f) }
20971#[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) }
20972#[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) }
20973#[no_mangle] pub unsafe extern "C" fn fgetwc_unlocked(f: *mut FILE) -> wint_t { fgetwc(f) }
20974#[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) }
20975#[no_mangle] pub unsafe extern "C" fn fputwc_unlocked(c: wchar_t, f: *mut FILE) -> wint_t { fputwc(c, f) }
20976#[no_mangle] pub unsafe extern "C" fn fputws_unlocked(s: *const wchar_t, f: *mut FILE) -> c_int { fputws(s, f) }
20977#[no_mangle] pub unsafe extern "C" fn getwc_unlocked(f: *mut c_void) -> wint_t { getwc(f) }
20978#[no_mangle] pub unsafe extern "C" fn putwc_unlocked(c: u32, f: *mut c_void) -> wint_t { putwc(c, f) }
20979#[no_mangle] pub unsafe extern "C" fn getwchar_unlocked() -> wint_t { getwchar() }
20980#[no_mangle] pub unsafe extern "C" fn putwchar_unlocked(c: wchar_t) -> wint_t { putwchar(c) }
20981#[no_mangle] pub unsafe extern "C" fn fpurge(f: *mut FILE) { clearerr(f) }
20982#[no_mangle] pub unsafe extern "C" fn _IO_getc(f: *mut FILE) -> c_int { getc(f) }
20983#[no_mangle] pub unsafe extern "C" fn _IO_putc(c: c_int, f: *mut FILE) -> c_int { putc(c, f) }
20984#[no_mangle] pub unsafe extern "C" fn _IO_getc_unlocked(f: *mut FILE) -> c_int { getc(f) }
20985#[no_mangle] pub unsafe extern "C" fn _IO_putc_unlocked(c: c_int, f: *mut FILE) -> c_int { putc(c, f) }
20986#[no_mangle] pub unsafe extern "C" fn _IO_feof_unlocked(f: *mut FILE) -> c_int { feof(f) }
20987#[no_mangle] pub unsafe extern "C" fn _IO_ferror_unlocked(f: *mut FILE) -> c_int { ferror(f) }
20988
20989#[no_mangle] pub unsafe extern "C" fn __getauxval(t: c_ulong) -> c_ulong { getauxval(t) }
20991#[no_mangle] pub unsafe extern "C" fn __longjmp(env: *const c_ulong, val: c_int) -> ! { longjmp(env, val) }
20992#[no_mangle] pub unsafe extern "C" fn bsd_signal(sig: c_int, handler: usize) -> usize { signal(sig, handler) }
20993#[no_mangle] pub unsafe extern "C" fn __sysv_signal(sig: c_int, handler: usize) -> usize { signal(sig, handler) }
20994#[no_mangle] pub unsafe extern "C" fn eaccess(path: *const c_char, mode: c_int) -> c_int { access(path, mode) }
20995#[no_mangle] pub unsafe extern "C" fn __xpg_basename(path: *mut c_char) -> *mut c_char { basename(path) }
20996#[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) }
20997#[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) }
20998
20999#[no_mangle]
21004pub unsafe extern "C" fn cfsetspeed(termios_p: *mut c_void, speed: u32) -> c_int {
21005 let r = cfsetispeed(termios_p, speed);
21006 if r != 0 { return r; }
21007 cfsetospeed(termios_p, speed)
21008}
21009
21010#[no_mangle]
21011pub unsafe extern "C" fn futimesat(dirfd: c_int, path: *const c_char, times: *const timeval) -> c_int {
21012 if times.is_null() {
21013 return utimensat(dirfd, path, core::ptr::null(), 0);
21014 }
21015 let tv = times as *const [timeval; 2];
21016 let mut ts: [timespec; 2] = [
21017 timespec { tv_sec: (*tv)[0].tv_sec, tv_nsec: (*tv)[0].tv_usec * 1000 },
21018 timespec { tv_sec: (*tv)[1].tv_sec, tv_nsec: (*tv)[1].tv_usec * 1000 },
21019 ];
21020 for t in &mut ts {
21021 if t.tv_nsec < 0 || t.tv_nsec >= 1_000_000_000 {
21022 ERRNO = EINVAL;
21023 return -1;
21024 }
21025 }
21026 utimensat(dirfd, path, ts.as_ptr(), 0)
21027}
21028
21029#[no_mangle]
21030pub unsafe extern "C" fn membarrier(cmd: c_int, flags: c_int, cpu_id: c_int) -> c_int {
21031 <Arch as Syscalls>::syscall3(SYS_MEMBARRIER, cmd as i64, flags as i64, cpu_id as i64) as c_int
21032}
21033
21034#[no_mangle]
21035pub unsafe extern "C" fn mremap(
21036 old_address: *mut c_void,
21037 old_size: usize,
21038 new_size: usize,
21039 flags: c_int,
21040 mut args: ...
21041) -> *mut c_void {
21042 let new_address = if flags & 2 != 0 { args.next_arg::<*mut c_void>() } else { core::ptr::null_mut() };
21043 let r = <Arch as Syscalls>::syscall5(
21044 SYS_MREMAP,
21045 old_address as i64,
21046 old_size as i64,
21047 new_size as i64,
21048 flags as i64,
21049 new_address as i64,
21050 );
21051 if r < 0 {
21052 ERRNO = (-r) as c_int;
21053 return (-1isize) as *mut c_void;
21054 }
21055 r as *mut c_void
21056}
21057
21058#[no_mangle]
21059pub unsafe extern "C" fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: usize) -> c_int {
21060 let name = ptsname(fd);
21061 if name.is_null() { return -1; }
21062 let n = crate::strlen(name);
21063 if n + 1 > buflen {
21064 ERRNO = ERANGE_VAL;
21065 return ERANGE_VAL;
21066 }
21067 core::ptr::copy_nonoverlapping(name, buf, n + 1);
21068 0
21069}
21070
21071#[no_mangle]
21072pub unsafe extern "C" fn posix_getdents(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize {
21073 if flags != 0 {
21074 ERRNO = EINVAL;
21075 return -1;
21076 }
21077 let r = <Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, buf as i64, len as i64);
21078 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
21079}
21080
21081#[no_mangle]
21082pub unsafe extern "C" fn riscv_flush_icache(start: *mut c_void, end: *mut c_void, flags: c_ulong) -> c_int {
21083 #[cfg(target_arch = "riscv64")]
21084 {
21085 let r = <Arch as Syscalls>::syscall3(259, start as i64, end as i64, flags as i64);
21086 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21087 }
21088 #[cfg(not(target_arch = "riscv64"))]
21089 {
21090 let _ = (start, end, flags);
21091 0
21092 }
21093}
21094
21095#[no_mangle]
21096pub unsafe extern "C" fn __riscv_flush_icache(start: *mut c_void, end: *mut c_void, flags: c_ulong) -> c_int {
21097 riscv_flush_icache(start, end, flags)
21098}
21099
21100#[no_mangle]
21101pub unsafe extern "C" fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int {
21102 let fd = mkstemps(template, suffixlen);
21103 if fd >= 0 && flags & O_CLOEXEC != 0 {
21104 sys_fcntl(fd, F_SETFD, FD_CLOEXEC as i64);
21105 }
21106 fd
21107}
21108
21109#[no_mangle]
21110pub unsafe extern "C" fn statfs(path: *const c_char, buf: *mut c_void) -> c_int {
21111 let r = <Arch as Syscalls>::syscall2(SYS_STATFS, path as i64, buf as i64);
21112 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21113}
21114
21115#[no_mangle]
21116pub unsafe extern "C" fn fstatfs(fd: c_int, buf: *mut c_void) -> c_int {
21117 let r = <Arch as Syscalls>::syscall2(SYS_FSTATFS, fd as i64, buf as i64);
21118 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21119}
21120
21121#[no_mangle]
21122pub unsafe extern "C" fn sysinfo(info: *mut c_void) -> c_int {
21123 let r = <Arch as Syscalls>::syscall1(SYS_SYSINFO, info as i64);
21124 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21125}
21126
21127#[no_mangle]
21128pub unsafe extern "C" fn pthread_tryjoin_np(thread: PthreadT, retval: *mut *mut c_void) -> c_int {
21129 let slot = thread as *mut Thread;
21130 if slot.is_null() { return EINVAL; }
21131 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
21132 let tid = core::ptr::read_volatile(&raw const (*slot).tid);
21133 if tid > 0 { return EBUSY; }
21134 if tid < 0 { return EINVAL; }
21135 pthread_join(thread, retval)
21136}
21137
21138#[no_mangle]
21139pub unsafe extern "C" fn pthread_timedjoin_np(thread: PthreadT, retval: *mut *mut c_void, abstime: *const timespec) -> c_int {
21140 let slot = thread as *mut Thread;
21141 if slot.is_null() { return EINVAL; }
21142 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
21143 loop {
21144 let r = pthread_tryjoin_np(thread, retval);
21145 if r != EBUSY { return r; }
21146 let tid = core::ptr::read_volatile(&raw const (*slot).tid);
21147 if tid <= 0 { continue; }
21148 let e = futex_timedwait(&raw mut (*slot).tid, tid, abstime);
21149 if e == ETIMEDOUT { return ETIMEDOUT; }
21150 }
21151}
21152
21153
21154#[repr(C)]
21157pub struct UtmpExit {
21158 pub e_termination: i16,
21159 pub e_exit: i16,
21160}
21161
21162#[repr(C)]
21163pub struct Utmpx {
21164 pub ut_type: i16,
21165 pub __ut_pad1: i16,
21166 pub ut_pid: i32,
21167 pub ut_line: [c_char; 32],
21168 pub ut_id: [c_char; 4],
21169 pub ut_user: [c_char; 32],
21170 pub ut_host: [c_char; 256],
21171 pub ut_exit: UtmpExit,
21172 pub ut_session: i32,
21173 pub __ut_pad2: i32,
21174 pub ut_tv: timeval,
21175 pub ut_addr_v6: [u32; 4],
21176 pub __unused: [u8; 20],
21177}
21178
21179const UTMP_SIZE: usize = 400;
21180const _: [(); UTMP_SIZE] = [(); core::mem::size_of::<Utmpx>()];
21181
21182static mut UTMP_FD: c_int = -1;
21183static mut UTMP_PATH: [u8; 256] = [0; 256];
21184static mut UTMP_PATH_SET: bool = false;
21185#[repr(align(8))]
21186struct UtmpBuf([u8; UTMP_SIZE]);
21187static mut UTMP_BUF: UtmpBuf = UtmpBuf([0; UTMP_SIZE]);
21188
21189unsafe fn utmp_path_ptr() -> *const c_char {
21190 if !UTMP_PATH_SET {
21191 let default = b"/var/run/utmp\0";
21192 let mut i = 0;
21193 while i < default.len() && i < UTMP_PATH.len() {
21194 UTMP_PATH[i] = default[i];
21195 i += 1;
21196 }
21197 UTMP_PATH_SET = true;
21198 }
21199 UTMP_PATH.as_ptr() as *const c_char
21200}
21201
21202unsafe fn utmp_open_read() -> c_int {
21203 if UTMP_FD >= 0 {
21204 crate::close(UTMP_FD);
21205 }
21206 UTMP_FD = crate::open(utmp_path_ptr(), 0, 0);
21207 UTMP_FD
21208}
21209
21210unsafe fn utmp_open_append() -> c_int {
21211 crate::open(utmp_path_ptr(), 1 | 64 | 1024, 0o644)
21212}
21213
21214#[no_mangle]
21215pub unsafe extern "C" fn setutent() {
21216 let _ = utmp_open_read();
21217}
21218
21219#[no_mangle]
21220pub unsafe extern "C" fn endutent() {
21221 if UTMP_FD >= 0 {
21222 crate::close(UTMP_FD);
21223 UTMP_FD = -1;
21224 }
21225}
21226
21227#[no_mangle]
21228pub unsafe extern "C" fn getutent() -> *mut c_void {
21229 if UTMP_FD < 0 && utmp_open_read() < 0 {
21230 return core::ptr::null_mut();
21231 }
21232 let n = crate::read(UTMP_FD, UTMP_BUF.0.as_mut_ptr() as *mut c_void, UTMP_SIZE);
21233 if n == UTMP_SIZE as isize {
21234 UTMP_BUF.0.as_mut_ptr() as *mut c_void
21235 } else {
21236 core::ptr::null_mut()
21237 }
21238}
21239
21240unsafe fn utmp_id_eq(a: &[c_char; 4], b: &[c_char; 4]) -> bool {
21241 a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]
21242}
21243
21244unsafe fn utmp_line_eq(a: &[c_char; 32], b: &[c_char; 32]) -> bool {
21245 let mut i = 0;
21246 while i < 32 {
21247 if a[i] != b[i] { return false; }
21248 if a[i] == 0 { return true; }
21249 i += 1;
21250 }
21251 true
21252}
21253
21254#[no_mangle]
21255pub unsafe extern "C" fn getutid(ut: *const c_void) -> *mut c_void {
21256 if ut.is_null() { return core::ptr::null_mut(); }
21257 let want = &*(ut as *const Utmpx);
21258 loop {
21259 let p = getutent();
21260 if p.is_null() { return p; }
21261 let cur = &*(p as *const Utmpx);
21262 let matched = match want.ut_type {
21263 1 | 2 | 3 | 4 => cur.ut_type == want.ut_type,
21264 _ => utmp_id_eq(&cur.ut_id, &want.ut_id)
21265 && (want.ut_type == 0 || cur.ut_type == want.ut_type),
21266 };
21267 if matched { return p; }
21268 }
21269}
21270
21271#[no_mangle]
21272pub unsafe extern "C" fn getutline(ut: *const c_void) -> *mut c_void {
21273 if ut.is_null() { return core::ptr::null_mut(); }
21274 let want = &*(ut as *const Utmpx);
21275 loop {
21276 let p = getutent();
21277 if p.is_null() { return p; }
21278 if utmp_line_eq(&(*(p as *const Utmpx)).ut_line, &want.ut_line) {
21279 return p;
21280 }
21281 }
21282}
21283
21284#[no_mangle]
21285pub unsafe extern "C" fn pututline(ut: *const c_void) -> *mut c_void {
21286 if ut.is_null() { return core::ptr::null_mut(); }
21287 let fd = utmp_open_append();
21288 if fd < 0 { return core::ptr::null_mut(); }
21289 let n = crate::write(fd, ut, UTMP_SIZE);
21290 crate::close(fd);
21291 if n == UTMP_SIZE as isize { ut as *mut c_void } else { core::ptr::null_mut() }
21292}
21293
21294#[no_mangle]
21295pub unsafe extern "C" fn updwtmp(file: *const c_char, ut: *const c_void) {
21296 if file.is_null() || ut.is_null() { return; }
21297 let fd = crate::open(file, 1 | 64 | 1024, 0o644);
21298 if fd >= 0 {
21299 let _ = crate::write(fd, ut, UTMP_SIZE);
21300 crate::close(fd);
21301 }
21302}
21303
21304unsafe fn utmp_set_name(file: *const c_char) -> c_int {
21305 if file.is_null() { return -1; }
21306 let len = crate::strlen(file);
21307 if len + 1 > UTMP_PATH.len() { return -1; }
21308 if UTMP_FD >= 0 {
21309 crate::close(UTMP_FD);
21310 UTMP_FD = -1;
21311 }
21312 core::ptr::copy_nonoverlapping(file, UTMP_PATH.as_mut_ptr() as *mut c_char, len + 1);
21313 UTMP_PATH_SET = true;
21314 0
21315}
21316
21317#[no_mangle]
21318pub unsafe extern "C" fn utmpname(file: *const c_char) -> c_int { utmp_set_name(file) }
21319
21320#[no_mangle]
21321pub unsafe extern "C" fn utmpxname(file: *const c_char) -> c_int { utmp_set_name(file) }
21322
21323
21324#[no_mangle] pub static mut ___environ: *mut *mut c_char = core::ptr::null_mut();
21326#[no_mangle] pub static mut _environ: *mut *mut c_char = core::ptr::null_mut();
21327#[no_mangle] pub unsafe extern "C" fn __freelocale(loc: locale_t) { freelocale(loc) }
21328#[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) }
21329#[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) }
21330#[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) }
21331#[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) }
21332
21333#[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) }
21334#[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) }
21335#[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) }
21336#[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) }
21337#[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) }
21338#[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) }
21339
21340const MAX_NS: usize = 3;
21345const MAX_SEARCH: usize = 6;
21346const HOST_NOT_FOUND: c_int = 1;
21347const TRY_AGAIN: c_int = 2;
21348const NO_RECOVERY: c_int = 3;
21349const NO_DATA: c_int = 4;
21350
21351static mut NS_COUNT: usize = 0;
21352static mut NS_ADDRS: [u32; MAX_NS] = [0; MAX_NS];
21353static mut SEARCH_COUNT: usize = 0;
21354static mut SEARCH_DOMAINS: [[u8; 256]; MAX_SEARCH] = [[0; 256]; MAX_SEARCH];
21355static mut RESOLV_INITIALIZED: bool = false;
21356
21357#[repr(C)]
21358struct SockAddrIn {
21359 sin_family: u16,
21360 sin_port: u16,
21361 sin_addr: u32,
21362 sin_zero: [u8; 8],
21363}
21364
21365#[repr(C)]
21366struct PollFd {
21367 fd: c_int,
21368 events: i16,
21369 revents: i16,
21370}
21371
21372unsafe fn resolv_skip_ws(line: &[u8], mut i: usize) -> usize {
21373 while i < line.len() && (line[i] == b' ' || line[i] == b'\t') { i += 1; }
21374 i
21375}
21376
21377unsafe fn resolv_token<'a>(line: &'a [u8], mut i: usize) -> (&'a [u8], usize) {
21378 let start = i;
21379 while i < line.len() && line[i] != b' ' && line[i] != b'\t' && line[i] != b'#' { i += 1; }
21380 (&line[start..i], i)
21381}
21382
21383unsafe fn resolv_parse_config() -> c_int {
21384 RESOLV_INITIALIZED = true;
21385 NS_COUNT = 0;
21386 SEARCH_COUNT = 0;
21387 let path = b"/etc/resolv.conf\0";
21388 let fd = crate::open(path.as_ptr() as *const c_char, 0, 0);
21389 if fd < 0 { return -1; }
21390 let mut buf = [0u8; 4096];
21391 let n = crate::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len());
21392 crate::close(fd);
21393 if n <= 0 { return -1; }
21394 let len = n as usize;
21395 let mut i = 0;
21396 while i < len {
21397 let start = i;
21398 while i < len && buf[i] != b'\n' { i += 1; }
21399 let line = &buf[start..i];
21400 i += 1;
21401 let mut j = resolv_skip_ws(line, 0);
21402 if j >= line.len() || line[j] == b'#' { continue; }
21403 let (key, next) = resolv_token(line, j);
21404 j = next;
21405 if key == b"nameserver" {
21406 j = resolv_skip_ws(line, j);
21407 let (tok, _) = resolv_token(line, j);
21408 if !tok.is_empty() && NS_COUNT < MAX_NS {
21409 let mut name = [0u8; 64];
21410 let l = core::cmp::min(tok.len(), 63);
21411 name[..l].copy_from_slice(&tok[..l]);
21412 let addr = crate::inet_addr(name.as_ptr() as *const c_char);
21413 if addr != u32::MAX {
21414 NS_ADDRS[NS_COUNT] = addr;
21415 NS_COUNT += 1;
21416 }
21417 }
21418 } else if key == b"search" || key == b"domain" {
21419 loop {
21420 j = resolv_skip_ws(line, j);
21421 if j >= line.len() || line[j] == b'#' { break; }
21422 let (tok, next) = resolv_token(line, j);
21423 j = next;
21424 if tok.is_empty() { break; }
21425 if SEARCH_COUNT < MAX_SEARCH {
21426 let l = core::cmp::min(tok.len(), 255);
21427 SEARCH_DOMAINS[SEARCH_COUNT][..l].copy_from_slice(&tok[..l]);
21428 SEARCH_DOMAINS[SEARCH_COUNT][l] = 0;
21429 SEARCH_COUNT += 1;
21430 }
21431 if key == b"domain" { break; }
21432 }
21433 }
21434 }
21435 0
21436}
21437
21438#[no_mangle]
21439pub unsafe extern "C" fn res_init() -> c_int {
21440 let _ = resolv_parse_config();
21441 0
21442}
21443
21444#[no_mangle]
21445pub unsafe extern "C" fn res_mkquery(
21446 op: c_int,
21447 dname: *const c_char,
21448 class: c_int,
21449 type_: c_int,
21450 _data: *const u8,
21451 _datalen: c_int,
21452 _newrr: *const u8,
21453 buf: *mut u8,
21454 buflen: c_int,
21455) -> c_int {
21456 if dname.is_null() || buf.is_null() { return -1; }
21457 let mut l = crate::strnlen(dname as *const u8, 255);
21458 if l > 0 && *dname.add(l - 1) == b'.' as c_char { l -= 1; }
21459 if l > 0 && *dname.add(l - 1) == b'.' as c_char { return -1; }
21460 let n = 17 + l + if l != 0 { 1 } else { 0 };
21461 if l > 253 || buflen < n as c_int || op < 0 || op > 15 || class < 0 || class > 255 || type_ < 0 || type_ > 255 {
21462 return -1;
21463 }
21464 let mut q = [0u8; 280];
21465 crate::memset(q.as_mut_ptr() as *mut c_void, 0, n);
21466 q[2] = (op * 8 + 1) as u8;
21467 q[3] = 32;
21468 q[5] = 1;
21469 core::ptr::copy_nonoverlapping(dname as *const u8, q.as_mut_ptr().add(13), l);
21470 let mut i = 13;
21471 while q[i] != 0 {
21472 let mut j = i;
21473 while q[j] != 0 && q[j] != b'.' { j += 1; }
21474 if j - i - 1 > 62 { return -1; }
21475 q[i - 1] = (j - i) as u8;
21476 i = j + 1;
21477 }
21478 q[i + 1] = type_ as u8;
21479 q[i + 3] = class as u8;
21480 let mut ts = timespec { tv_sec: 0, tv_nsec: 0 };
21481 let _ = clock_gettime(CLOCK_REALTIME, &mut ts);
21482 let id = (((ts.tv_nsec as u64) + (ts.tv_nsec as u64) / 65536) & 0xffff) as u16;
21483 q[0] = (id >> 8) as u8;
21484 q[1] = id as u8;
21485 core::ptr::copy_nonoverlapping(q.as_ptr(), buf, n);
21486 n as c_int
21487}
21488
21489unsafe fn res_send_inner(msg: *const u8, msglen: c_int, answer: *mut u8, anslen: c_int) -> c_int {
21490 if msg.is_null() || answer.is_null() || msglen < 12 || anslen < 12 { return -1; }
21491 if !RESOLV_INITIALIZED { let _ = resolv_parse_config(); }
21492 if NS_COUNT == 0 {
21493 h_errno = TRY_AGAIN;
21494 return -1;
21495 }
21496 for n in 0..NS_COUNT {
21497 let fd = crate::socket(AF_INET, SOCK_DGRAM, 0);
21498 if fd < 0 { continue; }
21499 let sa = SockAddrIn {
21500 sin_family: AF_INET as u16,
21501 sin_port: 53u16.to_be(),
21502 sin_addr: NS_ADDRS[n],
21503 sin_zero: [0; 8],
21504 };
21505 let sent = crate::sendto(fd, msg as *const c_void, msglen as usize, 0, &sa as *const SockAddrIn as *const crate::sockaddr, 16);
21506 if sent != msglen as isize {
21507 crate::close(fd);
21508 continue;
21509 }
21510 let mut pfd = PollFd { fd, events: 1, revents: 0 };
21511 let pr = crate::poll(&mut pfd as *mut PollFd as *mut c_void, 1, 5000);
21512 if pr <= 0 {
21513 crate::close(fd);
21514 continue;
21515 }
21516 let r = crate::recvfrom(fd, answer as *mut c_void, anslen as usize, 0, core::ptr::null_mut(), core::ptr::null_mut());
21517 crate::close(fd);
21518 if r >= 12 {
21519 let id_ok = *answer == *msg && *answer.add(1) == *msg.add(1);
21520 let qr = (*answer.add(2) & 0x80) != 0;
21521 if id_ok && qr {
21522 return r as c_int;
21523 }
21524 }
21525 }
21526 h_errno = TRY_AGAIN;
21527 -1
21528}
21529
21530#[no_mangle]
21531pub unsafe extern "C" fn res_send(msg: *const u8, msglen: c_int, answer: *mut u8, anslen: c_int) -> c_int {
21532 if anslen < 512 {
21533 let mut buf = [0u8; 512];
21534 let r = res_send_inner(msg, msglen, buf.as_mut_ptr(), 512);
21535 if r >= 0 {
21536 let copy = core::cmp::min(r, anslen) as usize;
21537 if copy > 0 { core::ptr::copy_nonoverlapping(buf.as_ptr(), answer, copy); }
21538 }
21539 return r;
21540 }
21541 res_send_inner(msg, msglen, answer, anslen)
21542}
21543
21544#[no_mangle]
21545pub unsafe extern "C" fn res_query(
21546 dname: *const c_char,
21547 class: c_int,
21548 type_: c_int,
21549 answer: *mut u8,
21550 anslen: c_int,
21551) -> c_int {
21552 let mut q = [0u8; 280];
21553 let ql = res_mkquery(0, dname, class, type_, core::ptr::null(), 0, core::ptr::null(), q.as_mut_ptr(), q.len() as c_int);
21554 if ql < 0 { return ql; }
21555 let r = res_send(q.as_ptr(), ql, answer, anslen);
21556 if r < 12 {
21557 h_errno = TRY_AGAIN;
21558 return -1;
21559 }
21560 let rcode = answer.add(3).read() & 0x0f;
21561 if rcode == 3 {
21562 h_errno = HOST_NOT_FOUND;
21563 return -1;
21564 }
21565 if rcode == 0 && *answer.add(6) == 0 && *answer.add(7) == 0 {
21566 h_errno = NO_DATA;
21567 return -1;
21568 }
21569 if rcode != 0 {
21570 h_errno = NO_RECOVERY;
21571 return -1;
21572 }
21573 r
21574}
21575
21576#[no_mangle]
21577pub unsafe extern "C" fn res_querydomain(
21578 name: *const c_char,
21579 domain: *const c_char,
21580 class: c_int,
21581 type_: c_int,
21582 answer: *mut u8,
21583 anslen: c_int,
21584) -> c_int {
21585 if domain.is_null() || *domain == 0 { return res_query(name, class, type_, answer, anslen); }
21586 let mut buf = [0u8; 512];
21587 let nl = crate::strlen(name);
21588 let dl = crate::strlen(domain);
21589 if nl + 1 + dl >= buf.len() { return -1; }
21590 core::ptr::copy_nonoverlapping(name, buf.as_mut_ptr() as *mut c_char, nl);
21591 buf[nl] = b'.';
21592 core::ptr::copy_nonoverlapping(domain, buf.as_mut_ptr().add(nl + 1) as *mut c_char, dl);
21593 buf[nl + 1 + dl] = 0;
21594 res_query(buf.as_ptr() as *const c_char, class, type_, answer, anslen)
21595}
21596
21597#[no_mangle]
21598pub unsafe extern "C" fn res_search(
21599 name: *const c_char,
21600 class: c_int,
21601 type_: c_int,
21602 answer: *mut u8,
21603 anslen: c_int,
21604) -> c_int {
21605 if name.is_null() { return -1; }
21606 if !RESOLV_INITIALIZED { let _ = resolv_parse_config(); }
21607 let len = crate::strlen(name);
21608 let mut dots = 0;
21609 for i in 0..len {
21610 if *name.add(i) == b'.' as c_char { dots += 1; }
21611 }
21612 let trailing_dot = len > 0 && *name.add(len - 1) == b'.' as c_char;
21613 if trailing_dot || dots >= 1 {
21614 let r = res_query(name, class, type_, answer, anslen);
21615 if r >= 0 { return r; }
21616 if trailing_dot { return -1; }
21617 }
21618 for i in 0..SEARCH_COUNT {
21619 let dom = SEARCH_DOMAINS[i].as_ptr() as *const c_char;
21620 let r = res_querydomain(name, dom, class, type_, answer, anslen);
21621 if r >= 0 { return r; }
21622 if h_errno != HOST_NOT_FOUND && h_errno != NO_DATA { return -1; }
21623 }
21624 if dots == 0 {
21625 return res_query(name, class, type_, answer, anslen);
21626 }
21627 -1
21628}
21629
21630#[repr(C)]
21635pub struct HostEnt {
21636 pub h_name: *mut c_char,
21637 pub h_aliases: *mut *mut c_char,
21638 pub h_addrtype: c_int,
21639 pub h_length: c_int,
21640 pub h_addr_list: *mut *mut c_char,
21641}
21642
21643#[repr(C)]
21644pub struct AddrInfo {
21645 pub ai_flags: c_int,
21646 pub ai_family: c_int,
21647 pub ai_socktype: c_int,
21648 pub ai_protocol: c_int,
21649 pub ai_addrlen: u32,
21650 pub ai_addr: *mut c_void,
21651 pub ai_canonname: *mut c_char,
21652 pub ai_next: *mut AddrInfo,
21653}
21654
21655static mut HOST_ENT: HostEnt = HostEnt {
21656 h_name: core::ptr::null_mut(),
21657 h_aliases: core::ptr::null_mut(),
21658 h_addrtype: 0,
21659 h_length: 0,
21660 h_addr_list: core::ptr::null_mut(),
21661};
21662static mut HOST_NAME: [c_char; 256] = [0; 256];
21663static mut HOST_ALIASES: [*mut c_char; 1] = [core::ptr::null_mut()];
21664static mut HOST_ADDR: [u8; 16] = [0; 16];
21665static mut HOST_ADDR_PTRS: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
21666
21667unsafe fn dns_skip_name(p: *const u8, end: *const u8) -> *const u8 {
21668 let mut q = p;
21669 while q < end {
21670 let c = *q;
21671 if c == 0 { return q.add(1); }
21672 if c & 0xc0 == 0xc0 { return q.add(2); }
21673 q = q.add(1 + c as usize);
21674 }
21675 end
21676}
21677
21678unsafe fn dns_read_u16(p: *const u8) -> u16 {
21679 ((*p as u16) << 8) | *p.add(1) as u16
21680}
21681
21682unsafe fn dns_expand_name(p: *const u8, msg: *const u8, out: *mut c_char, outlen: usize) -> bool {
21683 let mut q = p;
21684 let mut o = 0usize;
21685 let mut jumps = 0;
21686 loop {
21687 let c = *q;
21688 if c == 0 {
21689 if o < outlen { *out.add(o) = 0; }
21690 return true;
21691 }
21692 if c & 0xc0 == 0xc0 {
21693 let off = (((c & 0x3f) as usize) << 8) | *q.add(1) as usize;
21694 q = msg.add(off);
21695 jumps += 1;
21696 if jumps > 16 { return false; }
21697 continue;
21698 }
21699 let l = c as usize;
21700 if l > 63 { return false; }
21701 if o + l + 1 >= outlen { return false; }
21702 core::ptr::copy_nonoverlapping(q.add(1), out.add(o) as *mut u8, l);
21703 o += l;
21704 *out.add(o) = b'.' as c_char;
21705 o += 1;
21706 q = q.add(1 + l);
21707 }
21708}
21709
21710unsafe fn host_from_answer(answer: *const u8, len: c_int, af: c_int) -> *mut HostEnt {
21711 if len < 12 { return core::ptr::null_mut(); }
21712 let end = answer.add(len as usize);
21713 let qd = dns_read_u16(answer.add(4)) as usize;
21714 let an = dns_read_u16(answer.add(6)) as usize;
21715 let mut p = answer.add(12);
21716 for _ in 0..qd {
21717 p = dns_skip_name(p, end);
21718 p = p.add(4);
21719 }
21720 let want_type: u16 = if af == AF_INET6 { 28 } else { 1 };
21721 let want_len = if af == AF_INET6 { 16 } else { 4 };
21722 for _ in 0..an {
21723 p = dns_skip_name(p, end);
21724 if p.add(10) > end { break; }
21725 let typ = dns_read_u16(p);
21726 let class = dns_read_u16(p.add(2));
21727 let rdlen = dns_read_u16(p.add(8)) as usize;
21728 let rdata = p.add(10);
21729 if rdata.add(rdlen) > end { break; }
21730 if typ == want_type && class == 1 && rdlen == want_len {
21731 core::ptr::copy_nonoverlapping(rdata, HOST_ADDR.as_mut_ptr(), want_len);
21732 HOST_ENT.h_addrtype = af;
21733 HOST_ENT.h_length = want_len as c_int;
21734 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
21735 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
21736 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
21737 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
21738 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
21739 h_errno = 0;
21740 return &raw mut HOST_ENT;
21741 }
21742 p = rdata.add(rdlen);
21743 }
21744 core::ptr::null_mut()
21745}
21746
21747#[no_mangle]
21748pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut HostEnt {
21749 gethostbyname2(name, AF_INET)
21750}
21751
21752#[no_mangle]
21753pub unsafe extern "C" fn gethostbyname2(name: *const c_char, af: c_int) -> *mut HostEnt {
21754 if name.is_null() { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
21755 let mut addr = [0u8; 16];
21756 let addrlen = if af == AF_INET6 { 16 } else { 4 };
21757 if inet_pton(af, name, addr.as_mut_ptr() as *mut c_void) == 1 {
21758 core::ptr::copy_nonoverlapping(addr.as_ptr(), HOST_ADDR.as_mut_ptr(), addrlen);
21759 let n = crate::strlen(name);
21760 let l = core::cmp::min(n, 255);
21761 core::ptr::copy_nonoverlapping(name, HOST_NAME.as_mut_ptr(), l);
21762 HOST_NAME[l] = 0;
21763 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
21764 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
21765 HOST_ENT.h_addrtype = af;
21766 HOST_ENT.h_length = addrlen as c_int;
21767 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
21768 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
21769 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
21770 h_errno = 0;
21771 return &raw mut HOST_ENT;
21772 }
21773 let mut answer = [0u8; 512];
21774 let qtype = if af == AF_INET6 { 28 } else { 1 };
21775 let r = res_query(name, 1, qtype, answer.as_mut_ptr(), answer.len() as c_int);
21776 if r < 0 {
21777 if h_errno == 0 { h_errno = TRY_AGAIN; }
21778 return core::ptr::null_mut();
21779 }
21780 let ent = host_from_answer(answer.as_ptr(), r, af);
21781 if !ent.is_null() {
21782 let n = crate::strlen(name);
21783 let l = core::cmp::min(n, 255);
21784 core::ptr::copy_nonoverlapping(name, HOST_NAME.as_mut_ptr(), l);
21785 HOST_NAME[l] = 0;
21786 } else {
21787 h_errno = HOST_NOT_FOUND;
21788 }
21789 ent
21790}
21791
21792#[no_mangle]
21793pub unsafe extern "C" fn gethostbyaddr(addr: *const c_void, len: u32, type_: c_int) -> *mut HostEnt {
21794 if addr.is_null() || type_ != AF_INET || len != 4 { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
21795 let a = addr as *const u8;
21796 let mut name = [0u8; 128];
21797 let mut pos = 0;
21798 for i in 0..4 {
21799 let v = *a.add(3 - i) as u32;
21800 if v >= 100 { name[pos] = b'0' + (v / 100) as u8; pos += 1; }
21801 if v >= 10 { name[pos] = b'0' + ((v / 10) % 10) as u8; pos += 1; }
21802 name[pos] = b'0' + (v % 10) as u8; pos += 1;
21803 name[pos] = b'.'; pos += 1;
21804 }
21805 let suffix = b"in-addr.arpa";
21806 for &c in suffix { name[pos] = c; pos += 1; }
21807 name[pos] = 0;
21808 let mut answer = [0u8; 512];
21809 let r = res_query(name.as_ptr() as *const c_char, 1, 12, answer.as_mut_ptr(), answer.len() as c_int);
21810 if r < 12 { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
21811 let end = answer.as_ptr().add(r as usize);
21812 let qd = dns_read_u16(answer.as_ptr().add(4)) as usize;
21813 let an = dns_read_u16(answer.as_ptr().add(6)) as usize;
21814 let mut p = answer.as_ptr().add(12);
21815 for _ in 0..qd { p = dns_skip_name(p, end); p = p.add(4); }
21816 for _ in 0..an {
21817 p = dns_skip_name(p, end);
21818 if p.add(10) > end { break; }
21819 let typ = dns_read_u16(p);
21820 let rdlen = dns_read_u16(p.add(8)) as usize;
21821 let rdata = p.add(10);
21822 if typ == 12 && dns_expand_name(rdata, answer.as_ptr(), HOST_NAME.as_mut_ptr(), HOST_NAME.len()) {
21823 let mut o = crate::strlen(HOST_NAME.as_ptr());
21824 if o > 0 && HOST_NAME[o - 1] == b'.' as c_char { o -= 1; }
21825 HOST_NAME[o] = 0;
21826 core::ptr::copy_nonoverlapping(a, HOST_ADDR.as_mut_ptr(), 4);
21827 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
21828 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
21829 HOST_ENT.h_addrtype = AF_INET;
21830 HOST_ENT.h_length = 4;
21831 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
21832 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
21833 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
21834 h_errno = 0;
21835 return &raw mut HOST_ENT;
21836 }
21837 p = rdata.add(rdlen);
21838 }
21839 h_errno = HOST_NOT_FOUND;
21840 core::ptr::null_mut()
21841}
21842
21843#[inline]
21848fn sysno(x86_64: i64, generic: i64) -> i64 {
21849 if cfg!(target_arch = "x86_64") { x86_64 } else { generic }
21850}
21851
21852#[no_mangle]
21853pub unsafe extern "C" fn settimeofday(tv: *const c_void, tz: *const c_void) -> c_int {
21854 let r = <Arch as Syscalls>::syscall2(sysno(164, 170), tv as i64, tz as i64);
21855 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21856}
21857
21858#[no_mangle]
21859pub unsafe extern "C" fn stime(t: *const i64) -> c_int {
21860 if t.is_null() { ERRNO = EINVAL; return -1; }
21861 let tv = timeval { tv_sec: *t, tv_usec: 0 };
21862 settimeofday(&tv as *const timeval as *const c_void, core::ptr::null())
21863}
21864
21865#[no_mangle]
21866pub unsafe extern "C" fn times(buf: *mut c_void) -> c_long {
21867 let r = <Arch as Syscalls>::syscall1(sysno(100, 153), buf as i64);
21868 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_long }
21869}
21870
21871#[no_mangle]
21872pub 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 {
21873 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);
21874 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
21875}
21876
21877#[no_mangle]
21878pub unsafe extern "C" fn tee(fd_in: c_int, fd_out: c_int, len: usize, flags: u32) -> isize {
21879 let r = <Arch as Syscalls>::syscall4(sysno(276, 77), fd_in as i64, fd_out as i64, len as i64, flags as i64);
21880 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
21881}
21882
21883#[no_mangle]
21884pub unsafe extern "C" fn statx(dirfd: c_int, path: *const c_char, flags: c_int, mask: u32, buf: *mut c_void) -> c_int {
21885 let r = <Arch as Syscalls>::syscall5(sysno(332, 291), dirfd as i64, path as i64, flags as i64, mask as i64, buf as i64);
21886 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21887}
21888
21889#[no_mangle]
21890pub unsafe extern "C" fn setns(fd: c_int, nstype: c_int) -> c_int {
21891 let r = <Arch as Syscalls>::syscall2(SYS_SETNS, fd as i64, nstype as i64);
21892 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21893}
21894
21895#[no_mangle]
21896pub unsafe extern "C" fn setfsuid(uid: u32) -> c_int {
21897 <Arch as Syscalls>::syscall1(sysno(122, 151), uid as i64) as c_int
21898}
21899
21900#[no_mangle]
21901pub unsafe extern "C" fn setfsgid(gid: u32) -> c_int {
21902 <Arch as Syscalls>::syscall1(sysno(123, 152), gid as i64) as c_int
21903}
21904
21905#[no_mangle]
21906pub unsafe extern "C" fn setregid(rgid: u32, egid: u32) -> c_int {
21907 let r = <Arch as Syscalls>::syscall2(sysno(114, 143), rgid as i64, egid as i64);
21908 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21909}
21910
21911#[no_mangle]
21912pub 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 {
21913 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);
21914 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
21915}
21916
21917#[no_mangle]
21918pub 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 {
21919 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);
21920 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as isize }
21921}
21922
21923#[no_mangle]
21924pub unsafe extern "C" fn tcgetwinsize(fd: c_int, ws: *mut c_void) -> c_int {
21925 if fd < 0 || ws.is_null() { ERRNO = EINVAL; return -1; }
21926 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5413, ws as i64);
21927 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21928}
21929
21930#[no_mangle]
21931pub unsafe extern "C" fn tcsetwinsize(fd: c_int, ws: *const c_void) -> c_int {
21932 if fd < 0 || ws.is_null() { ERRNO = EINVAL; return -1; }
21933 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5414, ws as i64);
21934 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
21935}
21936
21937#[no_mangle]
21938pub unsafe extern "C" fn sockatmark(fd: c_int) -> c_int {
21939 let mut at: c_int = 0;
21940 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x8905, &mut at as *mut c_int as i64);
21941 if r < 0 { ERRNO = (-r) as c_int; -1 } else { at }
21942}
21943
21944#[no_mangle]
21945pub unsafe extern "C" fn isastream(fd: c_int) -> c_int {
21946 let mut buf = [0u8; 64];
21947 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5401, buf.as_mut_ptr() as i64);
21948 if r < 0 { ERRNO = (-r) as c_int; 0 } else { 1 }
21949}
21950
21951#[no_mangle]
21952pub unsafe extern "C" fn posix_madvise(addr: *mut c_void, len: usize, advice: c_int) -> c_int {
21953 madvise(addr as *mut u8, len, advice)
21954}
21955
21956#[no_mangle]
21957pub unsafe extern "C" fn secure_getenv(name: *const c_char) -> *mut c_char {
21958 if getauxval(23) != 0 { return core::ptr::null_mut(); }
21959 getenv(name)
21960}
21961
21962#[no_mangle]
21963pub unsafe extern "C" fn sigandset(dest: *mut c_ulong, left: *const c_ulong, right: *const c_ulong) -> c_int {
21964 if dest.is_null() || left.is_null() || right.is_null() { return -1; }
21965 *dest = *left & *right;
21966 0
21967}
21968
21969#[no_mangle]
21970pub unsafe extern "C" fn sigorset(dest: *mut c_ulong, left: *const c_ulong, right: *const c_ulong) -> c_int {
21971 if dest.is_null() || left.is_null() || right.is_null() { return -1; }
21972 *dest = *left | *right;
21973 0
21974}
21975
21976#[no_mangle]
21977pub unsafe extern "C" fn sigisemptyset(set: *const c_ulong) -> c_int {
21978 if set.is_null() { return 1; }
21979 (*set == 0) as c_int
21980}
21981
21982#[no_mangle]
21983pub unsafe extern "C" fn sighold(sig: c_int) -> c_int {
21984 let set: c_ulong = 1u64 << (sig - 1) as u32;
21985 sigprocmask(0, &set, core::ptr::null_mut());
21986 0
21987}
21988
21989#[no_mangle]
21990pub unsafe extern "C" fn sigignore(sig: c_int) -> c_int {
21991 let _ = signal(sig, 1);
21992 0
21993}
21994
21995#[no_mangle]
21996pub unsafe extern "C" fn sigrelse(sig: c_int) -> c_int {
21997 let set: c_ulong = 1u64 << (sig - 1) as u32;
21998 sigprocmask(1, &set, core::ptr::null_mut());
21999 0
22000}
22001
22002#[no_mangle]
22003pub unsafe extern "C" fn siginterrupt(sig: c_int, flag: c_int) -> c_int {
22004 let mut sa: sigaction = core::mem::zeroed();
22005 if sigaction(sig, core::ptr::null(), &mut sa) != 0 { return -1; }
22006 if flag != 0 { sa.sa_flags &= !(SA_RESTART as c_ulong); } else { sa.sa_flags |= SA_RESTART as c_ulong; }
22007 sigaction(sig, &sa, core::ptr::null_mut())
22008}
22009
22010#[no_mangle]
22011pub unsafe extern "C" fn sigpause(sig: c_int) -> c_int {
22012 let set: c_ulong = 1u64 << (sig - 1) as u32;
22013 sigsuspend(&set)
22014}
22015
22016#[no_mangle]
22017pub unsafe extern "C" fn semtimedop(semid: c_int, sops: *mut c_void, nsops: usize, timeout: *const timespec) -> c_int {
22018 let r = <Arch as Syscalls>::syscall4(sysno(220, 192), semid as i64, sops as i64, nsops as i64, timeout as i64);
22019 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
22020}
22021
22022#[no_mangle]
22023pub unsafe extern "C" fn wait3(status: *mut c_int, options: c_int, rusage: *mut c_void) -> i32 {
22024 wait4(-1, status, options, rusage) as i32
22025}
22026
22027#[no_mangle]
22028pub unsafe extern "C" fn tempnam(dir: *const c_char, pfx: *const c_char) -> *mut c_char {
22029 let mut path = [0 as c_char; 256];
22030 let mut i = 0;
22031 if !dir.is_null() {
22032 while *dir.add(i) != 0 && i < 200 { path[i] = *dir.add(i); i += 1; }
22033 if i > 0 && path[i-1] != b'/' as c_char { path[i] = b'/' as c_char; i += 1; }
22034 } else {
22035 for &c in b"/tmp/" { path[i] = c as c_char; i += 1; }
22036 }
22037 if !pfx.is_null() {
22038 let mut j = 0;
22039 while *pfx.add(j) != 0 && i < 220 { path[i] = *pfx.add(j); i += 1; j += 1; }
22040 }
22041 for &c in b"XXXXXX" { path[i] = c as c_char; i += 1; }
22042 path[i] = 0;
22043 let fd = mkstemp(path.as_mut_ptr());
22044 if fd < 0 { return core::ptr::null_mut(); }
22045 close(fd);
22046 unlink(path.as_ptr());
22047 let n = strlen(path.as_ptr());
22048 let out = malloc(n + 1) as *mut c_char;
22049 if out.is_null() { return core::ptr::null_mut(); }
22050 core::ptr::copy_nonoverlapping(path.as_ptr(), out, n + 1);
22051 out
22052}
22053
22054#[no_mangle]
22055pub unsafe extern "C" fn putwc(c: u32, f: *mut c_void) -> u32 {
22056 fputwc(c as c_int, f as *mut FILE) as u32
22057}
22058
22059#[no_mangle]
22060pub unsafe extern "C" fn __uflow(f: *mut c_void) -> c_int {
22061 fgetc(f as *mut FILE)
22062}
22063
22064#[no_mangle]
22065pub unsafe extern "C" fn __xmknod(_ver: c_int, path: *const c_char, mode: c_uint, dev: u64) -> c_int {
22066 mknod(path, mode, dev)
22067}
22068
22069#[no_mangle]
22070pub unsafe extern "C" fn __xmknodat(_ver: c_int, dirfd: c_int, path: *const c_char, mode: c_uint, dev: u64) -> c_int {
22071 mknodat(dirfd, path, mode, dev)
22072}
22073
22074#[no_mangle]
22075pub 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 {
22076 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);
22077 if r < 0 { ERRNO = (-r) as c_int; -1 } else { 0 }
22078}
22079
22080#[no_mangle]
22081pub unsafe extern "C" fn open_by_handle_at(mount_fd: c_int, handle: *mut c_void, flags: c_int) -> c_int {
22082 let r = <Arch as Syscalls>::syscall3(sysno(304, 265), mount_fd as i64, handle as i64, flags as i64);
22083 if r < 0 { ERRNO = (-r) as c_int; -1 } else { r as c_int }
22084}
22085
22086#[no_mangle]
22087pub unsafe extern "C" fn dn_skipname(comp: *const u8, eom: *const u8) -> c_int {
22088 let p = dns_skip_name(comp, eom);
22089 if p <= eom { (p as isize - comp as isize) as c_int } else { -1 }
22090}
22091
22092#[no_mangle]
22093pub 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 {
22094 if exp.is_null() || dst.is_null() || dstsiz <= 0 { return -1; }
22095 let mut o = 0usize;
22096 let mut p = exp;
22097 loop {
22098 let start = p;
22099 while *p != 0 && *p != b'.' as c_char { p = p.add(1); }
22100 let l = p as usize - start as usize;
22101 if l > 63 || o + l + 2 > dstsiz as usize { return -1; }
22102 *dst.add(o) = l as u8; o += 1;
22103 core::ptr::copy_nonoverlapping(start as *const u8, dst.add(o), l);
22104 o += l;
22105 if *p == 0 { break; }
22106 p = p.add(1);
22107 }
22108 if o + 1 > dstsiz as usize { return -1; }
22109 *dst.add(o) = 0;
22110 (o + 1) as c_int
22111}
22112
22113#[repr(C)]
22118#[derive(Copy, Clone)]
22119pub struct Spwd {
22120 pub sp_namp: *mut c_char,
22121 pub sp_pwdp: *mut c_char,
22122 pub sp_lstchg: c_long,
22123 pub sp_min: c_long,
22124 pub sp_max: c_long,
22125 pub sp_warn: c_long,
22126 pub sp_inact: c_long,
22127 pub sp_expire: c_long,
22128 pub sp_flag: c_ulong,
22129}
22130
22131static mut SPWD_ENT: Spwd = Spwd {
22132 sp_namp: core::ptr::null_mut(), sp_pwdp: core::ptr::null_mut(),
22133 sp_lstchg: 0, sp_min: 0, sp_max: 0, sp_warn: 0, sp_inact: 0,
22134 sp_expire: 0, sp_flag: 0,
22135};
22136static mut SPWD_BUF: [c_char; 1024] = [0; 1024];
22137static mut SPWD_FILE: *mut FILE = core::ptr::null_mut();
22138
22139unsafe fn parse_spwd(line: *const c_char, ent: *mut Spwd, buf: *mut c_char, buflen: usize) -> bool {
22140 let mut src = line;
22141 let mut o = 0usize;
22142 let mut fields: [*mut c_char; 9] = [core::ptr::null_mut(); 9];
22143 let mut n = 0usize;
22144 while n < 9 {
22145 let start = o;
22146 while *src != 0 && *src != b':' as c_char {
22147 if o + 1 >= buflen { return false; }
22148 *buf.add(o) = *src;
22149 o += 1;
22150 src = src.add(1);
22151 }
22152 *buf.add(o) = 0;
22153 o += 1;
22154 fields[n] = buf.add(start);
22155 n += 1;
22156 if *src == 0 { break; }
22157 src = src.add(1);
22158 }
22159 if n < 9 { return false; }
22160 (*ent).sp_namp = fields[0];
22161 (*ent).sp_pwdp = fields[1];
22162 (*ent).sp_lstchg = crate::strtol(fields[2], core::ptr::null_mut(), 10) as c_long;
22163 (*ent).sp_min = crate::strtol(fields[3], core::ptr::null_mut(), 10) as c_long;
22164 (*ent).sp_max = crate::strtol(fields[4], core::ptr::null_mut(), 10) as c_long;
22165 (*ent).sp_warn = crate::strtol(fields[5], core::ptr::null_mut(), 10) as c_long;
22166 (*ent).sp_inact = crate::strtol(fields[6], core::ptr::null_mut(), 10) as c_long;
22167 (*ent).sp_expire = crate::strtol(fields[7], core::ptr::null_mut(), 10) as c_long;
22168 (*ent).sp_flag = crate::strtoul(fields[8], core::ptr::null_mut(), 10) as c_ulong;
22169 true
22170}
22171
22172#[no_mangle]
22173pub unsafe extern "C" fn setspent() {
22174 endspent();
22175 SPWD_FILE = crate::fopen(b"/etc/shadow\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
22176}
22177
22178#[no_mangle]
22179pub unsafe extern "C" fn endspent() {
22180 if !SPWD_FILE.is_null() { crate::fclose(SPWD_FILE); SPWD_FILE = core::ptr::null_mut(); }
22181}
22182
22183#[no_mangle]
22184pub unsafe extern "C" fn getspent() -> *mut Spwd {
22185 if SPWD_FILE.is_null() { setspent(); if SPWD_FILE.is_null() { return core::ptr::null_mut(); } }
22186 let mut line = [0 as c_char; 1024];
22187 loop {
22188 if crate::fgets(line.as_mut_ptr(), 1024, SPWD_FILE).is_null() { return core::ptr::null_mut(); }
22189 if parse_spwd(line.as_ptr(), &raw mut SPWD_ENT, SPWD_BUF.as_mut_ptr(), SPWD_BUF.len()) {
22190 return &raw mut SPWD_ENT;
22191 }
22192 }
22193}
22194
22195#[no_mangle]
22196pub unsafe extern "C" fn fgetspent(f: *mut FILE) -> *mut Spwd {
22197 if f.is_null() { return core::ptr::null_mut(); }
22198 let mut line = [0 as c_char; 1024];
22199 loop {
22200 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
22201 if parse_spwd(line.as_ptr(), &raw mut SPWD_ENT, SPWD_BUF.as_mut_ptr(), SPWD_BUF.len()) {
22202 return &raw mut SPWD_ENT;
22203 }
22204 }
22205}
22206
22207#[no_mangle]
22208pub unsafe extern "C" fn getspnam(name: *const c_char) -> *mut Spwd {
22209 if name.is_null() { return core::ptr::null_mut(); }
22210 setspent();
22211 loop {
22212 let sp = getspent();
22213 if sp.is_null() { break; }
22214 if crate::strcmp((*sp).sp_namp as *const u8, name as *const u8) == 0 { endspent(); return sp; }
22215 }
22216 endspent();
22217 core::ptr::null_mut()
22218}
22219
22220#[no_mangle]
22221pub 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 {
22222 if result.is_null() { return EINVAL; }
22223 let p = getspnam(name);
22224 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *sp = *p; *result = sp; 0 }
22225}
22226
22227#[no_mangle]
22228pub unsafe extern "C" fn putspent(sp: *const Spwd, f: *mut FILE) -> c_int {
22229 if sp.is_null() || f.is_null() { return -1; }
22230 crate::fprintf(f, b"%s:%s:%ld:%ld:%ld:%ld:%ld:%ld:%lu\\n\0".as_ptr() as *const c_char,
22231 (*sp).sp_namp, (*sp).sp_pwdp, (*sp).sp_lstchg, (*sp).sp_min, (*sp).sp_max,
22232 (*sp).sp_warn, (*sp).sp_inact, (*sp).sp_expire, (*sp).sp_flag)
22233}
22234
22235#[no_mangle]
22236pub unsafe extern "C" fn getgrouplist(user: *const c_char, group: u32, groups: *mut u32, ngroups: *mut i32) -> c_int {
22237 if user.is_null() || groups.is_null() || ngroups.is_null() { return -1; }
22238 let max = *ngroups as usize;
22239 let mut n = 0usize;
22240 if n < max { *groups.add(n) = group; }
22241 n += 1;
22242 setgrent();
22243 loop {
22244 let g = getgrent();
22245 if g.is_null() { break; }
22246 if (*g).gr_gid == group { continue; }
22247 let mut found = false;
22248 let mut i = 0;
22249 while !(*(*g).gr_mem.add(i)).is_null() {
22250 if crate::strcmp(*(*g).gr_mem.add(i) as *const u8, user as *const u8) == 0 {
22251 found = true;
22252 break;
22253 }
22254 i += 1;
22255 }
22256 if found {
22257 if n < max { *groups.add(n) = (*g).gr_gid; }
22258 n += 1;
22259 }
22260 }
22261 endgrent();
22262 if n > max { *ngroups = n as i32; return -1; }
22263 *ngroups = n as i32;
22264 n as c_int
22265}