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