1#[repr(C)]
13pub struct Aiocb {
14 pub aio_fildes: c_int,
15 pub aio_lio_opcode: c_int,
16 pub aio_reqprio: c_int,
17 __pad: c_int,
18 pub aio_buf: *mut c_void,
19 pub aio_nbytes: usize,
20 pub aio_sigevent: [u8; 64],
21 pub aio_offset: i64,
22}
23
24const _: [(); 104] = [(); core::mem::size_of::<Aiocb>()];
25
26#[derive(Copy, Clone)]
27struct AioSlot {
28 cb: *mut Aiocb,
29 ret: isize,
30 err: c_int,
31 active: bool,
32 next: *mut AioSlot,
33 prev: *mut AioSlot,
34}
35
36static mut AIO_HEAD: *mut AioSlot = core::ptr::null_mut();
39static mut AIO_FREE: *mut AioSlot = core::ptr::null_mut();
40static AIO_LOCK: AtomicI32 = AtomicI32::new(0);
41
42unsafe fn aio_lock() {
43 while AIO_LOCK
44 .compare_exchange_weak(0, 1, Ordering::Acquire, Ordering::Relaxed)
45 .is_err()
46 {
47 core::hint::spin_loop();
48 }
49}
50
51unsafe fn aio_unlock() {
52 AIO_LOCK.store(0, Ordering::Release);
53}
54
55unsafe fn aio_alloc() -> *mut AioSlot {
56 let slot = if AIO_FREE.is_null() {
57 crate::malloc(core::mem::size_of::<AioSlot>()) as *mut AioSlot
58 } else {
59 let slot = AIO_FREE;
60 AIO_FREE = (*slot).next;
61 slot
62 };
63 if !slot.is_null() {
64 (*slot).cb = core::ptr::null_mut();
65 (*slot).ret = 0;
66 (*slot).err = 0;
67 (*slot).active = false;
68 (*slot).next = core::ptr::null_mut();
69 (*slot).prev = core::ptr::null_mut();
70 }
71 slot
72}
73
74unsafe fn aio_get(cb: *mut Aiocb) -> *mut AioSlot {
75 let mut slot = AIO_HEAD;
76 while !slot.is_null() {
77 if (*slot).cb == cb {
78 return slot;
79 }
80 slot = (*slot).next;
81 }
82 let slot = aio_alloc();
83 if slot.is_null() {
84 return core::ptr::null_mut();
85 }
86 (*slot).cb = cb;
87 (*slot).next = AIO_HEAD;
88 if !AIO_HEAD.is_null() {
89 (*AIO_HEAD).prev = slot;
90 }
91 AIO_HEAD = slot;
92 slot
93}
94
95unsafe fn aio_find(cb: *const Aiocb) -> *mut AioSlot {
96 let mut slot = AIO_HEAD;
97 while !slot.is_null() {
98 if (*slot).cb == cb as *mut Aiocb && (*slot).active {
99 return slot;
100 }
101 slot = (*slot).next;
102 }
103 core::ptr::null_mut()
104}
105
106unsafe fn aio_unlink(slot: *mut AioSlot) {
107 let prev = (*slot).prev;
108 let next = (*slot).next;
109 if prev.is_null() {
110 AIO_HEAD = next;
111 } else {
112 (*prev).next = next;
113 }
114 if !next.is_null() {
115 (*next).prev = prev;
116 }
117 (*slot).prev = core::ptr::null_mut();
118 (*slot).next = core::ptr::null_mut();
119}
120
121unsafe fn aio_finish(cb: *mut Aiocb, ret: isize, err: c_int) -> bool {
122 aio_lock();
123 let slot = aio_get(cb);
124 if slot.is_null() {
125 aio_unlock();
126 return false;
127 }
128 (*slot).ret = ret;
129 (*slot).err = err;
130 (*slot).active = true;
131 aio_unlock();
132 true
133}
134
135#[no_mangle]
136pub unsafe extern "C" fn aio_read(aiocbp: *mut Aiocb) -> c_int {
137 if aiocbp.is_null() { ERRNO!() = EINVAL; return -1; }
138 let r = crate::pread(
139 (*aiocbp).aio_fildes,
140 (*aiocbp).aio_buf,
141 (*aiocbp).aio_nbytes,
142 (*aiocbp).aio_offset,
143 );
144 let ok = if r < 0 {
145 aio_finish(aiocbp, -1, ERRNO!())
146 } else {
147 aio_finish(aiocbp, r, 0)
148 };
149 if !ok { ERRNO!() = EAGAIN; return -1; }
150 0
151}
152
153#[no_mangle]
154pub unsafe extern "C" fn aio_write(aiocbp: *mut Aiocb) -> c_int {
155 if aiocbp.is_null() { ERRNO!() = EINVAL; return -1; }
156 let r = crate::pwrite(
157 (*aiocbp).aio_fildes,
158 (*aiocbp).aio_buf as *const u8,
159 (*aiocbp).aio_nbytes,
160 (*aiocbp).aio_offset,
161 );
162 let ok = if r < 0 {
163 aio_finish(aiocbp, -1, ERRNO!())
164 } else {
165 aio_finish(aiocbp, r, 0)
166 };
167 if !ok { ERRNO!() = EAGAIN; return -1; }
168 0
169}
170
171#[no_mangle]
172pub unsafe extern "C" fn aio_fsync(op: c_int, aiocbp: *mut Aiocb) -> c_int {
173 if aiocbp.is_null() { ERRNO!() = EINVAL; return -1; }
174 let r = if op == 1 { crate::fdatasync((*aiocbp).aio_fildes) } else { crate::fsync((*aiocbp).aio_fildes) };
175 let ok = if r < 0 {
176 aio_finish(aiocbp, -1, ERRNO!())
177 } else {
178 aio_finish(aiocbp, 0, 0)
179 };
180 if !ok { ERRNO!() = EAGAIN; return -1; }
181 0
182}
183
184#[no_mangle]
185pub unsafe extern "C" fn aio_error(aiocbp: *const Aiocb) -> c_int {
186 if aiocbp.is_null() { return EINVAL; }
187 aio_lock();
188 let slot = aio_find(aiocbp);
189 let err = if slot.is_null() { EINVAL } else { (*slot).err };
190 aio_unlock();
191 err
192}
193
194#[no_mangle]
195pub unsafe extern "C" fn aio_return(aiocbp: *mut Aiocb) -> isize {
196 if aiocbp.is_null() { ERRNO!() = EINVAL; return -1; }
197 aio_lock();
198 let slot = aio_find(aiocbp);
199 if slot.is_null() {
200 aio_unlock();
201 ERRNO!() = EINVAL;
202 return -1;
203 }
204 let ret = (*slot).ret;
205 (*slot).active = false;
206 (*slot).cb = core::ptr::null_mut();
207 (*slot).ret = 0;
208 (*slot).err = 0;
209 aio_unlink(slot);
210 (*slot).next = AIO_FREE;
211 AIO_FREE = slot;
212 aio_unlock();
213 ret
214}
215
216#[no_mangle]
217pub unsafe extern "C" fn aio_cancel(fd: c_int, aiocbp: *mut Aiocb) -> c_int {
218 aio_lock();
219 if !aiocbp.is_null() {
220 let slot = aio_find(aiocbp);
221 let canceled = !slot.is_null() && (*slot).active && (*aiocbp).aio_fildes == fd;
222 if canceled {
223 (*slot).ret = -1;
224 (*slot).err = ECANCELED;
225 }
226 aio_unlock();
227 return if canceled { 1 } else { 2 };
228 }
229 let mut canceled = false;
230 let mut slot = AIO_HEAD;
231 while !slot.is_null() {
232 if (*slot).active && !(*slot).cb.is_null() && (*(*slot).cb).aio_fildes == fd {
233 (*slot).ret = -1;
234 (*slot).err = ECANCELED;
235 canceled = true;
236 }
237 slot = (*slot).next;
238 }
239 aio_unlock();
240 if canceled { 1 } else { 2 }
241}
242
243#[no_mangle]
244pub unsafe extern "C" fn aio_suspend(
245 aiocb_list: *const *const Aiocb,
246 nent: c_int,
247 _timeout: *const timespec,
248) -> c_int {
249 if nent <= 0 || aiocb_list.is_null() { ERRNO!() = EINVAL; return -1; }
250 aio_lock();
252 for i in 0..nent as usize {
253 let cb = *aiocb_list.add(i);
254 if cb.is_null() { continue; }
255 if aio_find(cb).is_null() {
256 aio_unlock();
257 ERRNO!() = EINVAL;
258 return -1;
259 }
260 }
261 aio_unlock();
262 0
263}
264
265#[repr(C)]
266#[derive(Copy, Clone)]
267pub struct SigEvent {
268 pub sigev_value: usize,
269 pub sigev_signo: c_int,
270 pub sigev_notify: c_int,
271 pub sigev_un: [u8; 48],
272}
273
274const SIGEV_SIGNAL_V: c_int = 0;
275const SIGEV_NONE_V: c_int = 1;
276const SIGEV_THREAD_V: c_int = 2;
277
278unsafe fn aio_notify(sev: *const SigEvent) {
279 if sev.is_null() { return; }
280 match (*sev).sigev_notify {
281 SIGEV_SIGNAL_V => {
282 crate::sigqueue(crate::getpid(), (*sev).sigev_signo, (*sev).sigev_value as *mut c_void);
283 }
284 SIGEV_THREAD_V => {
285 let fnptr = core::ptr::read_unaligned((*sev).sigev_un.as_ptr().add(0) as *const usize);
286 if fnptr != 0 {
287 let f: unsafe extern "C" fn(usize) = core::mem::transmute(fnptr);
288 f((*sev).sigev_value);
289 }
290 }
291 _ => {}
292 }
293}
294
295#[no_mangle]
296pub unsafe extern "C" fn lio_listio(
297 mode: c_int,
298 aiocb_list: *const *mut Aiocb,
299 nent: c_int,
300 sevp: *mut SigEvent,
301) -> c_int {
302 if nent < 0 || aiocb_list.is_null() { ERRNO!() = EINVAL; return -1; }
303 let mut ok = 0;
304 for i in 0..nent as usize {
305 let cb = *aiocb_list.add(i);
306 if cb.is_null() { continue; }
307 let r = match (*cb).aio_lio_opcode {
308 0 => aio_read(cb),
309 1 => aio_write(cb),
310 _ => 0,
311 };
312 if r == 0 { ok += 1; }
313 }
314 if mode == 1 && !sevp.is_null() {
315 aio_notify(sevp);
316 }
317 if ok == 0 && nent > 0 { -1 } else { 0 }
318}
319
320static mut PTHREAD_DEFAULT_STACK: usize = STACK_SIZE;
325static mut PTHREAD_DEFAULT_GUARD: usize = 4096;
326static mut PTHREAD_CONCURRENCY: c_int = 0;
327
328unsafe fn mapping_containing(addr: usize) -> Option<(usize, usize)> {
332 let fd = crate::open(b"/proc/self/maps\0".as_ptr() as *const core::ffi::c_char, 0, 0);
333 if fd < 0 {
334 return None;
335 }
336 let size: i64 = crate::lseek(fd, 0, 2);
337 let want: i64 = if size > 16384 { 16384 } else { size };
338 let start = if size > want { size - want } else { 0 };
339 if crate::lseek(fd, start, 0) < 0 {
340 crate::close(fd);
341 return None;
342 }
343 let mut buf = [0u8; 16384];
344 let mut len = 0usize;
345 while len < buf.len() {
346 let n = crate::read(
347 fd,
348 buf.as_mut_ptr().add(len) as *mut core::ffi::c_void,
349 buf.len() - len,
350 );
351 if n <= 0 {
352 break;
353 }
354 len += n as usize;
355 }
356 crate::close(fd);
357
358 let mut result = None;
359 let mut line_start = 0usize;
360 while line_start < len {
361 let mut line_end = line_start;
362 while line_end < len && buf[line_end] != b'\n' {
363 line_end += 1;
364 }
365 let line = &buf[line_start..line_end];
366 if let Some(dash) = line.iter().position(|&c| c == b'-') {
367 let mut lo = 0usize;
368 let mut ok = true;
369 for &c in &line[..dash] {
370 if c.is_ascii_digit() {
371 lo = lo * 16 + (c - b'0') as usize;
372 } else if (b'a'..=b'f').contains(&c) {
373 lo = lo * 16 + (c - b'a' + 10) as usize;
374 } else {
375 ok = false;
376 break;
377 }
378 }
379 if ok && !line[..dash].is_empty() {
380 let mut hi = 0usize;
381 let mut i = dash + 1;
382 while i < line.len() {
383 let c = line[i];
384 if c.is_ascii_digit() {
385 hi = hi * 16 + (c - b'0') as usize;
386 } else if (b'a'..=b'f').contains(&c) {
387 hi = hi * 16 + (c - b'a' + 10) as usize;
388 } else {
389 break;
390 }
391 i += 1;
392 }
393 if i > dash + 1 && lo <= addr && addr < hi {
394 result = Some((lo, hi - lo));
395 }
396 }
397 }
398 line_start = line_end + 1;
399 }
400 result
401}
402
403#[no_mangle]
404pub unsafe extern "C" fn pthread_getattr_np(thread: PthreadT, attr: *mut pthread_attr_t) -> c_int {
405 if attr.is_null() || thread == 0 { return EINVAL; }
406 let slot = thread as *mut Thread;
407 core::ptr::write_bytes(attr, 0, 1);
408 let mut stack_base = (*slot).stack as usize;
409 let mut stack_size = if (*slot).stack_size > 0 { (*slot).stack_size } else { PTHREAD_DEFAULT_STACK };
410 if stack_base == 0 {
411 let sp: usize;
415 #[cfg(target_arch = "x86_64")]
416 core::arch::asm!("mov {}, rsp", out(reg) sp, options(nomem, nostack));
417 #[cfg(target_arch = "aarch64")]
418 core::arch::asm!("mov {}, sp", out(reg) sp, options(nomem, nostack));
419 #[cfg(target_arch = "riscv64")]
420 core::arch::asm!("mv {}, sp", out(reg) sp, options(nomem, nostack));
421 if let Some((base, size)) = mapping_containing(sp) {
422 stack_base = base;
423 stack_size = size;
424 } else {
425 stack_base = sp & !0xfff;
426 stack_size = 4096;
427 }
428 }
429 *((*attr).__i.as_mut_ptr() as *mut usize) = stack_size;
430 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = PTHREAD_DEFAULT_GUARD;
431 *((*attr).__i.as_mut_ptr().add(4) as *mut *mut c_void) =
432 (stack_base + stack_size) as *mut c_void;
433 (*attr).__i[6] = if (*slot).detach_state == DT_DETACHED { 1 } else { 0 };
434 (*attr).__i[7] = 0;
435 0
436}
437
438#[no_mangle]
439pub unsafe extern "C" fn pthread_getattr_default_np(attr: *mut pthread_attr_t) -> c_int {
440 if attr.is_null() { return EINVAL; }
441 core::ptr::write_bytes(attr, 0, 1);
442 *((*attr).__i.as_mut_ptr() as *mut usize) = PTHREAD_DEFAULT_STACK;
443 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = PTHREAD_DEFAULT_GUARD;
444 (*attr).__i[6] = 0;
445 (*attr).__i[7] = 1;
446 0
447}
448
449#[no_mangle]
450pub unsafe extern "C" fn pthread_setattr_default_np(attr: *const pthread_attr_t) -> c_int {
451 if attr.is_null() { return EINVAL; }
452 let stack = *((*attr).__i.as_ptr() as *const usize);
453 let guard = *((*attr).__i.as_ptr().add(2) as *const usize);
454 if (*attr).__i[6] != 0 { return EINVAL; }
456 if stack > 0 {
457 if stack < 16384 { return EINVAL; }
458 PTHREAD_DEFAULT_STACK = stack;
459 }
460 if guard > 0 { PTHREAD_DEFAULT_GUARD = guard; }
461 0
462}
463
464#[no_mangle]
465pub unsafe extern "C" fn pthread_getconcurrency() -> c_int {
466 PTHREAD_CONCURRENCY
467}
468
469#[no_mangle]
470pub unsafe extern "C" fn pthread_setconcurrency(level: c_int) -> c_int {
471 if level < 0 { return EINVAL; }
472 PTHREAD_CONCURRENCY = level;
473 0
474}
475
476#[no_mangle]
477pub unsafe extern "C" fn pthread_getcpuclockid(thread: PthreadT, clockid: *mut i32) -> c_int {
478 if thread == 0 || clockid.is_null() { return EINVAL; }
479 let slot = thread as *mut Thread;
480 let tid = (*slot).tid as i64;
481 *clockid = (((-tid - 1) * 8 + 6) & 0xffffffff) as i32;
482 0
483}
484
485#[no_mangle]
486pub unsafe extern "C" fn pthread_setname_np(thread: PthreadT, name: *const c_char) -> c_int {
487 if thread == 0 || name.is_null() { return EINVAL; }
488 if crate::strnlen(name as *const u8, 16) > 15 { return 34; }
489 let slot = thread as *mut Thread;
490 if slot == pthread_self() as *mut Thread {
491 return if crate::prctl(15, name as c_long) < 0 { ERRNO!() } else { 0 };
492 }
493 let mut path = [0 as c_char; 48];
494 let mut o = 0usize;
495 for &c in b"/proc/self/task/" { path[o] = c as c_char; o += 1; }
496 let mut tid = (*slot).tid as u32;
497 let mut digits = [0u8; 10];
498 let mut d = 0usize;
499 if tid == 0 { digits[0] = b'0'; d = 1; }
500 while tid > 0 { digits[d] = b'0' + (tid % 10) as u8; tid /= 10; d += 1; }
501 while d > 0 { d -= 1; path[o] = digits[d] as c_char; o += 1; }
502 for &c in b"/comm\0" { path[o] = c as c_char; o += 1; }
503 let fd = crate::open(path.as_ptr(), 1, 0);
504 if fd < 0 { return ERRNO!(); }
505 let n = crate::strlen(name);
506 let w = crate::write(fd, name as *const c_void, n);
507 crate::close(fd);
508 if w < 0 { ERRNO!() } else { 0 }
509}
510
511#[no_mangle]
512pub unsafe extern "C" fn pthread_getname_np(thread: PthreadT, name: *mut c_char, len: usize) -> c_int {
513 if thread == 0 || name.is_null() { return EINVAL; }
514 if len < 16 { return 34; }
515 let slot = thread as *mut Thread;
516 if slot == pthread_self() as *mut Thread {
517 return if crate::prctl(16, name as c_long) < 0 { ERRNO!() } else { 0 };
518 }
519 let mut path = [0 as c_char; 48];
520 let mut o = 0usize;
521 for &c in b"/proc/self/task/" { path[o] = c as c_char; o += 1; }
522 let mut tid = (*slot).tid as u32;
523 let mut digits = [0u8; 10];
524 let mut d = 0usize;
525 if tid == 0 { digits[0] = b'0'; d = 1; }
526 while tid > 0 { digits[d] = b'0' + (tid % 10) as u8; tid /= 10; d += 1; }
527 while d > 0 { d -= 1; path[o] = digits[d] as c_char; o += 1; }
528 for &c in b"/comm\0" { path[o] = c as c_char; o += 1; }
529 let fd = crate::open(path.as_ptr(), 0, 0);
530 if fd < 0 { return ERRNO!(); }
531 let n = crate::read(fd, name as *mut c_void, len);
532 crate::close(fd);
533 if n < 0 { return ERRNO!(); }
534 let mut l = n as usize;
535 if l > 0 && *name.add(l - 1) == b'\n' as c_char { l -= 1; }
536 *name.add(l) = 0;
537 0
538}
539
540#[no_mangle]
541pub unsafe extern "C" fn pthread_getschedparam(thread: PthreadT, policy: *mut c_int, param: *mut sched_param) -> c_int {
542 if thread == 0 || policy.is_null() || param.is_null() { return EINVAL; }
543 let tid = (*(thread as *mut Thread)).tid;
544 *policy = crate::sched_getscheduler(tid);
545 crate::sched_getparam(tid, param as *mut c_void)
546}
547
548#[no_mangle]
549pub unsafe extern "C" fn pthread_setschedparam(thread: PthreadT, policy: c_int, param: *const sched_param) -> c_int {
550 if thread == 0 || param.is_null() { return EINVAL; }
551 let tid = (*(thread as *mut Thread)).tid;
552 crate::sched_setscheduler(tid, policy, param as *const c_void)
553}
554
555#[no_mangle]
556pub unsafe extern "C" fn pthread_setschedprio(thread: PthreadT, prio: c_int) -> c_int {
557 if thread == 0 { return EINVAL; }
558 let tid = (*(thread as *mut Thread)).tid;
559 let p = sched_param { sched_priority: prio };
560 crate::sched_setparam(tid, &p as *const sched_param as *const c_void)
561}
562
563#[no_mangle]
564pub unsafe extern "C" fn pthread_mutex_getprioceiling(mutex: *const pthread_mutex_t, ceiling: *mut c_int) -> c_int {
565 if mutex.is_null() || ceiling.is_null() { return EINVAL; }
566 *ceiling = 0;
567 0
568}
569
570#[no_mangle]
571pub unsafe extern "C" fn pthread_mutex_setprioceiling(mutex: *mut pthread_mutex_t, ceiling: c_int, old: *mut c_int) -> c_int {
572 if mutex.is_null() { return EINVAL; }
573 if !old.is_null() { *old = 0; }
574 let _ = ceiling;
575 0
576}
577
578#[repr(C)]
584pub struct posix_spawn_file_actions_t {
585 __pad0: [c_int; 2],
586 __actions: *mut c_void,
587 __pad: [c_int; 16],
588}
589
590#[repr(C)]
591#[derive(Copy, Clone)]
592pub struct posix_spawnattr_t {
593 __flags: c_int,
594 __pgrp: c_int,
595 __def: [c_ulong; 16],
596 __mask: [c_ulong; 16],
597 __prio: c_int,
598 __pol: c_int,
599 __fn: *mut c_void,
600 __pad: [u8; 64 - core::mem::size_of::<*mut c_void>()],
601}
602
603#[repr(C)]
604struct SpawnAction {
605 next: *mut SpawnAction,
606 kind: c_int,
607 fd: c_int,
608 newfd: c_int,
609 oflag: c_int,
610 mode: u32,
611 path: *mut c_char,
612 path_owned: bool,
613}
614
615static mut SPAWN_DEFAULT_ATTR: posix_spawnattr_t = posix_spawnattr_t {
616 __flags: 0,
617 __pgrp: 0,
618 __def: [0; 16],
619 __mask: [0; 16],
620 __prio: 0,
621 __pol: 0,
622 __fn: core::ptr::null_mut(),
623 __pad: [0; 64 - core::mem::size_of::<*mut c_void>()],
624};
625
626unsafe fn spawn_actions(fa: *const posix_spawn_file_actions_t) -> *mut SpawnAction {
627 (*fa).__actions as *mut SpawnAction
628}
629
630unsafe fn spawn_action_add(
631 fa: *mut posix_spawn_file_actions_t,
632 kind: c_int,
633 fd: c_int,
634 newfd: c_int,
635 oflag: c_int,
636 mode: u32,
637 path: *const c_char,
638) -> c_int {
639 let node = crate::calloc(1, core::mem::size_of::<SpawnAction>()) as *mut SpawnAction;
640 if node.is_null() { return ENOMEM; }
641 (*node).kind = kind;
642 (*node).fd = fd;
643 (*node).newfd = newfd;
644 (*node).oflag = oflag;
645 (*node).mode = mode;
646 (*node).next = core::ptr::null_mut();
647 if !path.is_null() {
648 let n = crate::strlen(path);
649 let p = crate::malloc(n + 1) as *mut c_char;
650 if p.is_null() { crate::free(node as *mut c_void); return ENOMEM; }
651 core::ptr::copy_nonoverlapping(path, p, n + 1);
652 (*node).path = p;
653 (*node).path_owned = true;
654 }
655 if (*fa).__actions.is_null() {
656 (*fa).__actions = node as *mut c_void;
657 } else {
658 let mut tail = (*fa).__actions as *mut SpawnAction;
659 while !(*tail).next.is_null() { tail = (*tail).next; }
660 (*tail).next = node;
661 }
662 0
663}
664
665#[no_mangle]
666pub unsafe extern "C" fn posix_spawn_file_actions_init(fa: *mut posix_spawn_file_actions_t) -> c_int {
667 if fa.is_null() { return EINVAL; }
668 core::ptr::write_bytes(fa, 0, 1);
669 0
670}
671
672#[no_mangle]
673pub unsafe extern "C" fn posix_spawn_file_actions_destroy(fa: *mut posix_spawn_file_actions_t) -> c_int {
674 if fa.is_null() { return EINVAL; }
675 let mut p = spawn_actions(fa);
676 while !p.is_null() {
677 let next = (*p).next;
678 if (*p).path_owned && !(*p).path.is_null() { crate::free((*p).path as *mut c_void); }
679 crate::free(p as *mut c_void);
680 p = next;
681 }
682 (*fa).__actions = core::ptr::null_mut();
683 0
684}
685
686#[no_mangle]
687pub unsafe extern "C" fn posix_spawn_file_actions_addclose(fa: *mut posix_spawn_file_actions_t, fd: c_int) -> c_int {
688 if fa.is_null() || fd < 0 { return EINVAL; }
689 spawn_action_add(fa, 0, fd, 0, 0, 0, core::ptr::null())
690}
691
692#[no_mangle]
693pub unsafe extern "C" fn posix_spawn_file_actions_adddup2(fa: *mut posix_spawn_file_actions_t, fd: c_int, newfd: c_int) -> c_int {
694 if fa.is_null() || fd < 0 || newfd < 0 { return EINVAL; }
695 spawn_action_add(fa, 1, fd, newfd, 0, 0, core::ptr::null())
696}
697
698#[no_mangle]
699pub unsafe extern "C" fn posix_spawn_file_actions_addopen(
700 fa: *mut posix_spawn_file_actions_t,
701 fd: c_int,
702 path: *const c_char,
703 oflag: c_int,
704 mode: u32,
705) -> c_int {
706 if fa.is_null() || fd < 0 || path.is_null() { return EINVAL; }
707 spawn_action_add(fa, 2, fd, 0, oflag, mode, path)
708}
709
710#[no_mangle]
711pub unsafe extern "C" fn posix_spawn_file_actions_addchdir_np(fa: *mut posix_spawn_file_actions_t, path: *const c_char) -> c_int {
712 if fa.is_null() || path.is_null() { return EINVAL; }
713 spawn_action_add(fa, 3, 0, 0, 0, 0, path)
714}
715
716#[no_mangle]
717pub unsafe extern "C" fn posix_spawn_file_actions_addfchdir_np(fa: *mut posix_spawn_file_actions_t, fd: c_int) -> c_int {
718 if fa.is_null() || fd < 0 { return EINVAL; }
719 spawn_action_add(fa, 4, fd, 0, 0, 0, core::ptr::null())
720}
721
722unsafe fn spawn_apply_actions(fa: *const posix_spawn_file_actions_t) {
723 if fa.is_null() { return; }
724 let mut p = spawn_actions(fa);
725 while !p.is_null() {
726 match (*p).kind {
727 0 => { crate::close((*p).fd); }
728 1 => { crate::dup2((*p).fd, (*p).newfd); }
729 2 => {
730 let fd = crate::open((*p).path, (*p).oflag, (*p).mode as c_int);
731 if fd >= 0 && fd != (*p).fd {
732 crate::dup2(fd, (*p).fd);
733 crate::close(fd);
734 }
735 }
736 3 => { crate::chdir((*p).path); }
737 4 => { crate::fchdir((*p).fd); }
738 _ => {}
739 }
740 p = (*p).next;
741 }
742}
743
744unsafe fn spawn_apply_attr(attr: *const posix_spawnattr_t) {
745 if attr.is_null() { return; }
746 let flags = (*attr).__flags;
747 if flags & 1 != 0 {
748 if crate::geteuid() == 0 {
749 crate::setgid(crate::getgid());
750 crate::setuid(crate::getuid());
751 }
752 }
753 if flags & 2 != 0 { crate::setpgid(0, (*attr).__pgrp); }
754 if flags & 4 != 0 {
755 for sig in 1..65 {
756 let idx = (sig - 1) / 64;
757 let bit = (sig - 1) % 64;
758 if idx < 16 && ((*attr).__def[idx] >> bit) & 1 != 0 {
759 crate::signal(sig as c_int, 0);
760 }
761 }
762 }
763 if flags & 8 != 0 {
764 crate::sigprocmask(2, (*attr).__mask.as_ptr() as *const SigSetT, core::ptr::null_mut());
765 }
766 if flags & 16 != 0 {
767 let p = sched_param { sched_priority: (*attr).__prio };
768 crate::sched_setparam(0, &p as *const sched_param as *const c_void);
769 }
770 if flags & 32 != 0 {
771 let p = sched_param { sched_priority: (*attr).__prio };
772 crate::sched_setscheduler(0, (*attr).__pol, &p as *const sched_param as *const c_void);
773 }
774}
775
776#[no_mangle]
777pub unsafe extern "C" fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> c_int {
778 if attr.is_null() { return EINVAL; }
779 *attr = SPAWN_DEFAULT_ATTR;
780 0
781}
782
783#[no_mangle]
784pub unsafe extern "C" fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> c_int {
785 if attr.is_null() { return EINVAL; }
786 0
787}
788
789#[no_mangle]
790pub unsafe extern "C" fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *mut i16) -> c_int {
791 if attr.is_null() || flags.is_null() { return EINVAL; }
792 *flags = (*attr).__flags as i16;
793 0
794}
795
796#[no_mangle]
797pub unsafe extern "C" fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: i16) -> c_int {
798 if attr.is_null() { return EINVAL; }
799 if (flags as c_int) & !0x7f != 0 { return EINVAL; }
800 (*attr).__flags = flags as c_int;
801 0
802}
803
804#[no_mangle]
805pub unsafe extern "C" fn posix_spawnattr_getpgroup(attr: *const posix_spawnattr_t, pgroup: *mut c_int) -> c_int {
806 if attr.is_null() || pgroup.is_null() { return EINVAL; }
807 *pgroup = (*attr).__pgrp;
808 0
809}
810
811#[no_mangle]
812pub unsafe extern "C" fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, pgroup: c_int) -> c_int {
813 if attr.is_null() { return EINVAL; }
814 (*attr).__pgrp = pgroup;
815 0
816}
817
818#[no_mangle]
819pub unsafe extern "C" fn posix_spawnattr_getschedparam(attr: *const posix_spawnattr_t, param: *mut sched_param) -> c_int {
820 if attr.is_null() || param.is_null() { return EINVAL; }
821 (*param).sched_priority = (*attr).__prio;
822 0
823}
824
825#[no_mangle]
826pub unsafe extern "C" fn posix_spawnattr_setschedparam(attr: *mut posix_spawnattr_t, param: *const sched_param) -> c_int {
827 if attr.is_null() || param.is_null() { return EINVAL; }
828 (*attr).__prio = (*param).sched_priority;
829 0
830}
831
832#[no_mangle]
833pub unsafe extern "C" fn posix_spawnattr_getschedpolicy(attr: *const posix_spawnattr_t, policy: *mut c_int) -> c_int {
834 if attr.is_null() || policy.is_null() { return EINVAL; }
835 *policy = (*attr).__pol;
836 0
837}
838
839#[no_mangle]
840pub unsafe extern "C" fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, policy: c_int) -> c_int {
841 if attr.is_null() { return EINVAL; }
842 (*attr).__pol = policy;
843 0
844}
845
846#[no_mangle]
847pub unsafe extern "C" fn posix_spawnattr_getsigdefault(attr: *const posix_spawnattr_t, set: *mut SigSetT) -> c_int {
848 if attr.is_null() || set.is_null() { return EINVAL; }
849 *set = (*attr).__def[0];
850 0
851}
852
853#[no_mangle]
854pub unsafe extern "C" fn posix_spawnattr_setsigdefault(attr: *mut posix_spawnattr_t, set: *const SigSetT) -> c_int {
855 if attr.is_null() || set.is_null() { return EINVAL; }
856 (*attr).__def = [0; 16];
857 (*attr).__def[0] = *set;
858 0
859}
860
861#[no_mangle]
862pub unsafe extern "C" fn posix_spawnattr_getsigmask(attr: *const posix_spawnattr_t, set: *mut SigSetT) -> c_int {
863 if attr.is_null() || set.is_null() { return EINVAL; }
864 *set = (*attr).__mask[0];
865 0
866}
867
868#[no_mangle]
869pub unsafe extern "C" fn posix_spawnattr_setsigmask(attr: *mut posix_spawnattr_t, set: *const SigSetT) -> c_int {
870 if attr.is_null() || set.is_null() { return EINVAL; }
871 (*attr).__mask = [0; 16];
872 (*attr).__mask[0] = *set;
873 0
874}
875
876#[no_mangle]
881pub unsafe extern "C" fn __fbufsize(f: *mut FILE) -> usize {
882 if f.is_null() { return 0; }
883 (*f).buf_size
884}
885
886#[no_mangle]
887pub unsafe extern "C" fn __flbf(f: *mut FILE) -> c_int {
888 if f.is_null() { return 0; }
889 if (*f).lbf >= 0 { 1 } else { 0 }
890}
891
892#[no_mangle]
893pub unsafe extern "C" fn __fpending(f: *mut FILE) -> usize {
894 if f.is_null() || (*f).wend.is_null() { return 0; }
895 (*f).wpos as usize - (*f).wbase as usize
896}
897
898#[no_mangle]
899pub unsafe extern "C" fn __fpurge(f: *mut FILE) {
900 if f.is_null() { return; }
901 (*f).wpos = core::ptr::null_mut();
902 (*f).wbase = core::ptr::null_mut();
903 (*f).wend = core::ptr::null_mut();
904 (*f).rpos = core::ptr::null_mut();
905 (*f).rend = core::ptr::null_mut();
906}
907
908#[no_mangle]
909pub unsafe extern "C" fn __freadable(f: *mut FILE) -> c_int {
910 if f.is_null() { return 0; }
911 if (*f).flags & F_NORD == 0 { 1 } else { 0 }
912}
913
914#[no_mangle]
915pub unsafe extern "C" fn __freadahead(f: *mut FILE) -> usize {
916 if f.is_null() || (*f).rend.is_null() { return 0; }
917 (*f).rend as usize - (*f).rpos as usize
918}
919
920#[no_mangle]
921pub unsafe extern "C" fn __freading(f: *mut FILE) -> c_int {
922 if f.is_null() { return 0; }
923 if (*f).flags & F_NOWR != 0 || !(*f).rend.is_null() { 1 } else { 0 }
924}
925
926#[no_mangle]
927pub unsafe extern "C" fn __freadptr(f: *mut FILE, sizep: *mut usize) -> *const c_char {
928 if f.is_null() || sizep.is_null() { return core::ptr::null(); }
929 if (*f).rpos == (*f).rend { *sizep = 0; return core::ptr::null(); }
930 *sizep = (*f).rend as usize - (*f).rpos as usize;
931 (*f).rpos as *const c_char
932}
933
934#[no_mangle]
935pub unsafe extern "C" fn __freadptrinc(f: *mut FILE, inc: usize) {
936 if f.is_null() || (*f).rpos.is_null() { return; }
937 let left = (*f).rend as usize - (*f).rpos as usize;
938 let step = if inc > left { left } else { inc };
939 (*f).rpos = (*f).rpos.add(step);
940}
941
942#[no_mangle]
943pub unsafe extern "C" fn __fsetlocking(_f: *mut FILE, _type: c_int) -> c_int {
944 1
945}
946
947#[no_mangle]
948pub unsafe extern "C" fn __fwritable(f: *mut FILE) -> c_int {
949 if f.is_null() { return 0; }
950 if (*f).flags & F_NOWR == 0 { 1 } else { 0 }
951}
952
953#[no_mangle]
954pub unsafe extern "C" fn __fwriting(f: *mut FILE) -> c_int {
955 if f.is_null() { return 0; }
956 if (*f).flags & F_NORD != 0 || !(*f).wend.is_null() { 1 } else { 0 }
957}
958
959#[no_mangle]
960pub unsafe extern "C" fn __fseterr(f: *mut FILE) {
961 if !f.is_null() { (*f).flags |= F_ERR; }
962}
963
964#[no_mangle]
965pub unsafe extern "C" fn __fputwc_unlocked(c: wchar_t, f: *mut FILE) -> wint_t {
966 crate::fputwc(c, f)
967}
968
969#[no_mangle]
974pub unsafe extern "C" fn sigqueue(pid: c_int, sig: c_int, value: *mut c_void) -> c_int {
975 let mut si = [0u8; 128];
976 *(si.as_mut_ptr() as *mut c_int) = sig;
977 *(si.as_mut_ptr().add(8) as *mut c_int) = -1; *(si.as_mut_ptr().add(16) as *mut c_int) = crate::getpid();
979 *(si.as_mut_ptr().add(20) as *mut u32) = crate::getuid();
980 *(si.as_mut_ptr().add(24) as *mut *mut c_void) = value;
981 let r = <Arch as Syscalls>::syscall3(sysno(129, 138), pid as i64, sig as i64, si.as_ptr() as i64);
982 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
983}
984
985#[no_mangle]
986pub unsafe extern "C" fn timespec_get(ts: *mut timespec, base: c_int) -> c_int {
987 if base != 1 || ts.is_null() { return 0; }
988 if crate::clock_gettime(0, ts) != 0 { return 0; }
989 base
990}
991
992#[no_mangle]
993pub unsafe extern "C" fn ualarm(usecs: u32, interval: u32) -> u32 {
994 #[repr(C)]
995 struct ITV {
996 sec: i64,
997 usec: i64,
998 }
999 let mut new: [ITV; 2] = [
1000 ITV { sec: (interval / 1_000_000) as i64, usec: (interval % 1_000_000) as i64 },
1001 ITV { sec: (usecs / 1_000_000) as i64, usec: (usecs % 1_000_000) as i64 },
1002 ];
1003 let mut old: [ITV; 2] = [ITV { sec: 0, usec: 0 }, ITV { sec: 0, usec: 0 }];
1004 if crate::setitimer(0, new.as_mut_ptr() as *const c_void, old.as_mut_ptr() as *mut c_void) != 0 {
1005 return u32::MAX;
1006 }
1007 (old[0].sec as u32) * 1_000_000 + old[0].usec as u32
1008}
1009
1010static mut LCKPWDF_FD: c_int = -1;
1011
1012#[repr(C)]
1013#[derive(Copy, Clone)]
1014struct FlockT {
1015 l_type: i16,
1016 l_whence: i16,
1017 l_start: i64,
1018 l_len: i64,
1019 l_pid: i32,
1020 __pad: i32,
1021}
1022
1023#[no_mangle]
1024pub unsafe extern "C" fn lckpwdf() -> c_int {
1025 if LCKPWDF_FD >= 0 { return 0; }
1026 let fd = crate::open(
1027 b"/etc/.pwd.lock\0".as_ptr() as *const c_char,
1028 1 | 0x40 | 0x80000,
1029 0o600,
1030 );
1031 if fd < 0 { return -1; }
1032 let fl = FlockT { l_type: 1, l_whence: 0, l_start: 0, l_len: 0, l_pid: 0, __pad: 0 };
1033 if crate::fcntl(fd, 7, &fl as *const FlockT as *mut c_void) != 0 {
1034 crate::close(fd);
1035 return -1;
1036 }
1037 LCKPWDF_FD = fd;
1038 0
1039}
1040
1041#[no_mangle]
1042pub unsafe extern "C" fn ulckpwdf() -> c_int {
1043 if LCKPWDF_FD < 0 { return -1; }
1044 let fd = LCKPWDF_FD;
1045 LCKPWDF_FD = -1;
1046 crate::close(fd);
1047 0
1048}
1049
1050#[no_mangle]
1051pub unsafe extern "C" fn malloc_usable_size(ptr: *mut u8) -> usize {
1052 crate::alloc_usable_size(ptr)
1053}
1054
1055#[no_mangle]
1056pub unsafe extern "C" fn __wcsftime_l(
1057 s: *mut wchar_t,
1058 max: usize,
1059 fmt: *const wchar_t,
1060 tm: *const c_void,
1061 _loc: locale_t,
1062) -> usize {
1063 crate::wcsftime(s as *mut u32, max, fmt as *const u32, tm)
1064}
1065
1066#[no_mangle]
1067pub unsafe extern "C" fn __wctype_l(name: *const c_char, _loc: locale_t) -> wctype_t {
1068 crate::wctype(name)
1069}
1070
1071#[no_mangle]
1072pub unsafe extern "C" fn __wctrans_l(name: *const c_char, _loc: locale_t) -> wctrans_t {
1073 crate::wctrans(name)
1074}
1075
1076#[no_mangle]
1077pub unsafe extern "C" fn __fgetwc_unlocked(f: *mut FILE) -> wint_t {
1078 crate::fgetwc(f)
1079}
1080
1081#[no_mangle]
1082pub unsafe extern "C" fn _flushlbf() {
1083 crate::fflush(core::ptr::null_mut());
1084}