xref: /drstd/dlibc/src/unix/header/unistd/mod.rs (revision a84e10c84bc578bd0ee0ebe48f105474ac9992e9)
1 //! unistd implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/unistd.h.html
2 
3 use core::{convert::TryFrom, mem, ptr, slice};
4 
5 pub use self::{brk::*, getopt::*, pathconf::*, sysconf::*};
6 use crate::unix::platform;
7 use crate::unix::{
8     c_str::CStr,
9     header::{errno, limits, stdlib::getenv, sys_time, termios},
10 };
11 use alloc::collections::LinkedList;
12 use ioctl;
13 use TIOCGPGRP;
14 use TIOCSPGRP;
15 
16 mod brk;
17 mod getopt;
18 mod pathconf;
19 mod sysconf;
20 
21 pub use self::brk::*;
22 
23 pub const F_OK: ::c_int = 0;
24 pub const R_OK: ::c_int = 4;
25 pub const W_OK: ::c_int = 2;
26 pub const X_OK: ::c_int = 1;
27 
28 pub const SEEK_SET: ::c_int = 0;
29 pub const SEEK_CUR: ::c_int = 1;
30 pub const SEEK_END: ::c_int = 2;
31 
32 pub const F_ULOCK: ::c_int = 0;
33 pub const F_LOCK: ::c_int = 1;
34 pub const F_TLOCK: ::c_int = 2;
35 pub const F_TEST: ::c_int = 3;
36 
37 pub const STDIN_FILENO: ::c_int = 0;
38 pub const STDOUT_FILENO: ::c_int = 1;
39 pub const STDERR_FILENO: ::c_int = 2;
40 
41 #[cfg(not(target_os = "dragonos"))]
42 #[thread_local]
43 pub static mut fork_hooks_static: Option<[LinkedList<extern "C" fn()>; 3]> = None;
44 
45 /// due to dragonos not supporting thread_local, we need to use a static directly
46 #[cfg(target_os = "dragonos")]
47 pub static mut fork_hooks_static: Option<[LinkedList<extern "C" fn()>; 3]> = None;
48 
49 unsafe fn init_fork_hooks<'a>() -> &'a mut [LinkedList<extern "C" fn()>; 3] {
50     // Transmute the lifetime so we can return here. Should be safe as
51     // long as one does not access the original fork_hooks.
52     mem::transmute(
53         fork_hooks_static
54             .get_or_insert_with(|| [LinkedList::new(), LinkedList::new(), LinkedList::new()]),
55     )
56 }
57 
58 #[no_mangle]
59 pub extern "C" fn _exit(status: ::c_int) {
60     platform::pal::exit(status)
61 }
62 
63 pub unsafe fn access(path: *const ::c_char, mode: ::c_int) -> ::c_int {
64     platform::pal::access(path, mode)
65 }
66 
67 #[no_mangle]
68 pub extern "C" fn alarm(seconds: ::c_uint) -> ::c_uint {
69     let mut timer = sys_time::itimerval {
70         it_value: sys_time::timeval {
71             tv_sec: seconds as ::time_t,
72             tv_usec: 0,
73         },
74         ..Default::default()
75     };
76     let errno_backup = unsafe { platform::errno };
77     let secs = if ::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) < 0 {
78         0
79     } else {
80         timer.it_value.tv_sec as ::c_uint + if timer.it_value.tv_usec > 0 { 1 } else { 0 }
81     };
82     unsafe {
83         platform::errno = errno_backup;
84     }
85 
86     secs
87 }
88 
89 // #[no_mangle]
90 // pub unsafe extern "C" fn chdir(path: *const ::c_char) -> ::c_int {
91 //     platform::pal::chdir(path)
92 // }
93 
94 #[no_mangle]
95 pub extern "C" fn chroot(_path: *const ::c_char) -> ::c_int {
96     // TODO: Implement
97     unsafe {
98         platform::errno = crate::unix::header::errno::EPERM;
99     }
100 
101     -1
102 }
103 
104 // #[no_mangle]
105 // pub unsafe extern "C" fn chown(path: *const ::c_char, owner: ::uid_t, group: ::gid_t) -> ::c_int {
106 //     platform::pal::chown(path, owner, group)
107 // }
108 
109 // #[no_mangle]
110 // pub extern "C" fn close(fildes: ::c_int) -> ::c_int {
111 //     platform::pal::close(fildes)
112 // }
113 
114 // #[no_mangle]
115 // pub extern "C" fn confstr(name: ::c_int, buf: *mut ::c_char, len: ::size_t) -> ::size_t {
116 //     unimplemented!();
117 // }
118 
119 // #[no_mangle]
120 // pub extern "C" fn crypt(key: *const ::c_char, salt: *const ::c_char) -> *mut ::c_char {
121 //     unimplemented!();
122 // }
123 
124 // #[no_mangle]
125 // pub extern "C" fn dup(fildes: ::c_int) -> ::c_int {
126 //     platform::pal::dup(fildes)
127 // }
128 
129 // #[no_mangle]
130 // pub extern "C" fn dup2(fildes: ::c_int, fildes2: ::c_int) -> ::c_int {
131 //     platform::pal::dup2(fildes, fildes2)
132 // }
133 
134 // #[no_mangle]
135 // pub extern "C" fn encrypt(block: [::c_char; 64], edflag: ::c_int) {
136 //     unimplemented!();
137 // }
138 
139 // #[no_mangle]
140 // pub extern "C" fn execl(path: *const ::c_char, args: *const *mut ::c_char) -> ::c_int {
141 //     unimplemented!();
142 // }
143 
144 // #[no_mangle]
145 // pub extern "C" fn execle(
146 //   path: *const ::c_char,
147 //   args: *const *mut ::c_char,
148 //   envp: *const *mut ::c_char,
149 // ) -> ::c_int {
150 //     unimplemented!();
151 // }
152 
153 // #[no_mangle]
154 // pub extern "C" fn execlp(file: *const ::c_char, args: *const *mut ::c_char) -> ::c_int {
155 //     unimplemented!();
156 // }
157 
158 #[no_mangle]
159 pub unsafe extern "C" fn execv(path: *const ::c_char, argv: *const *const ::c_char) -> ::c_int {
160     ::execve(path, argv, platform::environ as *const *const ::c_char)
161 }
162 
163 // #[no_mangle]
164 // pub unsafe extern "C" fn execve(
165 //     path: *const ::c_char,
166 //     argv: *const *mut ::c_char,
167 //     envp: *const *mut ::c_char,
168 // ) -> ::c_int {
169 //     platform::pal::execve(path, argv as *const *const i8, envp as *const *const i8)
170 // }
171 
172 #[cfg(target_os = "linux")]
173 const PATH_SEPARATOR: u8 = b':';
174 
175 #[cfg(target_os = "dragonos")]
176 const PATH_SEPARATOR: u8 = b':';
177 
178 #[cfg(target_os = "redox")]
179 const PATH_SEPARATOR: u8 = b';';
180 
181 #[no_mangle]
182 pub unsafe extern "C" fn execvp(file: *const ::c_char, argv: *const *const ::c_char) -> ::c_int {
183     let file = CStr::from_ptr(file);
184 
185     if file.to_bytes().contains(&b'/')
186         || (cfg!(target_os = "redox") && file.to_bytes().contains(&b':'))
187     {
188         execv(file.as_ptr(), argv)
189     } else {
190         let mut error = errno::ENOENT;
191 
192         let path_env = getenv(c_str!("PATH\0").as_ptr());
193         if !path_env.is_null() {
194             let path_env = CStr::from_ptr(path_env);
195             for path in path_env.to_bytes().split(|&b| b == PATH_SEPARATOR) {
196                 let mut program = path.to_vec();
197                 program.push(b'/');
198                 program.extend_from_slice(file.to_bytes());
199                 program.push(b'\0');
200 
201                 let program_c = CStr::from_bytes_with_nul(&program).unwrap();
202                 execv(program_c.as_ptr(), argv);
203 
204                 match platform::errno {
205                     errno::ENOENT => (),
206                     other => error = other,
207                 }
208             }
209         }
210 
211         platform::errno = error;
212         -1
213     }
214 }
215 
216 // #[no_mangle]
217 // pub extern "C" fn fchown(fildes: ::c_int, owner: ::uid_t, group: ::gid_t) -> ::c_int {
218 //     platform::pal::fchown(fildes, owner, group)
219 // }
220 
221 // #[no_mangle]
222 // pub extern "C" fn fchdir(fildes: ::c_int) -> ::c_int {
223 //     platform::pal::fchdir(fildes)
224 // }
225 
226 // #[no_mangle]
227 pub extern "C" fn fdatasync(_fildes: ::c_int) -> ::c_int {
228     unimplemented!();
229 }
230 
231 #[no_mangle]
232 pub extern "C" fn fork() -> ::pid_t {
233     let fork_hooks = unsafe { init_fork_hooks() };
234     for prepare in &fork_hooks[0] {
235         prepare();
236     }
237     let pid = platform::pal::fork();
238     if pid == 0 {
239         for child in &fork_hooks[2] {
240             child();
241         }
242     } else if pid != -1 {
243         for parent in &fork_hooks[1] {
244             parent();
245         }
246     }
247     pid
248 }
249 
250 // #[no_mangle]
251 // pub extern "C" fn fsync(fildes: ::c_int) -> ::c_int {
252 //     platform::pal::fsync(fildes)
253 // }
254 
255 // #[no_mangle]
256 // pub extern "C" fn ftruncate(fildes: ::c_int, length: ::off_t) -> ::c_int {
257 //     platform::pal::ftruncate(fildes, length)
258 // }
259 
260 #[no_mangle]
261 pub extern "C" fn getcwd(mut buf: *mut ::c_char, mut size: ::size_t) -> *mut ::c_char {
262     let alloc = buf.is_null();
263     let mut stack_buf = [0; limits::PATH_MAX];
264     if alloc {
265         buf = stack_buf.as_mut_ptr();
266         size = stack_buf.len();
267     }
268 
269     let ret = platform::pal::getcwd(buf, size);
270     if ret.is_null() {
271         return ptr::null_mut();
272     }
273 
274     if alloc {
275         let len = stack_buf
276             .iter()
277             .position(|b| *b == 0)
278             .expect("no nul-byte in getcwd string")
279             + 1;
280         let heap_buf = unsafe { platform::alloc(len) as *mut ::c_char };
281         for i in 0..len {
282             unsafe {
283                 *heap_buf.add(i) = stack_buf[i];
284             }
285         }
286         heap_buf
287     } else {
288         ret
289     }
290 }
291 
292 // #[no_mangle]
293 pub extern "C" fn getdtablesize() -> ::c_int {
294     unimplemented!();
295 }
296 
297 // #[no_mangle]
298 // pub extern "C" fn getegid() -> ::gid_t {
299 //     platform::pal::getegid()
300 // }
301 
302 // #[no_mangle]
303 // pub extern "C" fn geteuid() -> ::uid_t {
304 //     platform::pal::geteuid()
305 // }
306 
307 // #[no_mangle]
308 // pub extern "C" fn getgid() -> ::gid_t {
309 //     platform::pal::getgid()
310 // }
311 
312 // #[no_mangle]
313 // pub extern "C" fn getgroups(gidsetsize: ::c_int, grouplist: *mut ::gid_t) -> ::c_int {
314 //     unimplemented!();
315 // }
316 
317 // #[no_mangle]
318 // pub extern "C" fn gethostid() -> ::c_long {
319 //     unimplemented!();
320 // }
321 
322 #[no_mangle]
323 pub unsafe extern "C" fn gethostname(mut name: *mut ::c_char, mut len: ::size_t) -> ::c_int {
324     let mut uts = mem::MaybeUninit::<::utsname>::uninit();
325     let err = platform::pal::uname(uts.as_mut_ptr());
326     if err < 0 {
327         mem::forget(uts);
328         return err;
329     }
330     for c in uts.assume_init().nodename.iter() {
331         if len == 0 {
332             break;
333         }
334         len -= 1;
335 
336         *name = *c;
337 
338         if *name == 0 {
339             // We do want to copy the zero also, so we check this after the copying.
340             break;
341         }
342 
343         name = name.offset(1);
344     }
345     0
346 }
347 
348 #[no_mangle]
349 pub unsafe extern "C" fn getlogin() -> *mut ::c_char {
350     static mut LOGIN: [::c_char; 256] = [0; 256];
351     if getlogin_r(LOGIN.as_mut_ptr(), LOGIN.len()) == 0 {
352         LOGIN.as_mut_ptr()
353     } else {
354         ptr::null_mut()
355     }
356 }
357 
358 #[no_mangle]
359 pub extern "C" fn getlogin_r(_name: *mut ::c_char, _namesize: ::size_t) -> ::c_int {
360     //TODO: Determine correct getlogin result on Redox
361     unsafe { platform::errno = errno::ENOENT };
362     -1
363 }
364 
365 #[no_mangle]
366 pub extern "C" fn getpagesize() -> ::c_int {
367     match ::c_int::try_from(sysconf(_SC_PAGESIZE)) {
368         Ok(page_size) => page_size,
369         Err(_) => {
370             /* Behavior not specified by POSIX for this case. The -1
371              * value mimics sysconf()'s behavior, though.
372              *
373              * As specified for the limits.h header, the minimum
374              * acceptable value for {PAGESIZE} is 1. The -1 value thus
375              * cannot be mistaken for an acceptable value.
376              *
377              * POSIX does not specify any possible errors for this
378              * function, hence no errno setting. */
379             -1
380         }
381     }
382 }
383 
384 // #[no_mangle]
385 // pub extern "C" fn getpass(prompt: *const ::c_char) -> *mut ::c_char {
386 //     unimplemented!();
387 // }
388 
389 // #[no_mangle]
390 // pub extern "C" fn getpgid(pid: ::pid_t) -> ::pid_t {
391 //     platform::pal::getpgid(pid)
392 // }
393 
394 #[no_mangle]
395 pub extern "C" fn getpgrp() -> ::pid_t {
396     platform::pal::getpgid(platform::pal::getpid())
397 }
398 
399 // #[no_mangle]
400 // pub extern "C" fn getpid() -> ::pid_t {
401 //     platform::pal::getpid()
402 // }
403 
404 // #[no_mangle]
405 // pub extern "C" fn getppid() -> ::pid_t {
406 //     platform::pal::getppid()
407 // }
408 
409 // #[no_mangle]
410 // pub extern "C" fn getsid(pid: ::pid_t) -> ::pid_t {
411 //     platform::pal::getsid(pid)
412 // }
413 
414 // #[no_mangle]
415 // pub extern "C" fn getuid() -> ::uid_t {
416 //     platform::pal::getuid()
417 // }
418 
419 #[no_mangle]
420 pub extern "C" fn getwd(path_name: *mut ::c_char) -> *mut ::c_char {
421     getcwd(path_name, limits::PATH_MAX)
422 }
423 
424 #[no_mangle]
425 pub extern "C" fn isatty(fd: ::c_int) -> ::c_int {
426     let mut t = termios::termios::default();
427     if unsafe { termios::tcgetattr(fd, &mut t as *mut termios::termios) == 0 } {
428         1
429     } else {
430         0
431     }
432 }
433 
434 // #[no_mangle]
435 // pub unsafe extern "C" fn lchown(path: *const ::c_char, owner: ::uid_t, group: ::gid_t) -> ::c_int {
436 //     platform::pal::lchown(path, owner, group)
437 // }
438 
439 // #[no_mangle]
440 // pub unsafe extern "C" fn link(path1: *const ::c_char, path2: *const ::c_char) -> ::c_int {
441 //     platform::pal::link(path1, path2)
442 // }
443 
444 // #[no_mangle]
445 // pub extern "C" fn lockf(fildes: ::c_int, function: ::c_int, size: ::off_t) -> ::c_int {
446 //     unimplemented!();
447 // }
448 
449 // #[no_mangle]
450 // pub extern "C" fn lseek(fildes: ::c_int, offset: ::off_t, whence: ::c_int) -> ::off_t {
451 //     platform::pal::lseek(fildes, offset, whence)
452 // }
453 
454 // #[no_mangle]
455 pub extern "C" fn nice(_incr: ::c_int) -> ::c_int {
456     unimplemented!();
457 }
458 
459 // #[no_mangle]
460 pub extern "C" fn pause() -> ::c_int {
461     unimplemented!();
462 }
463 
464 //#[no_mangle]
465 pub unsafe extern "C" fn pipe(fildes: *mut ::c_int) -> ::c_int {
466     ::pipe2(fildes, 0)
467 }
468 
469 // #[no_mangle]
470 // pub unsafe extern "C" fn pipe2(fildes: *mut ::c_int, flags: ::c_int) -> ::c_int {
471 //     platform::pal::pipe2(fildes, flags)
472 // }
473 
474 #[no_mangle]
475 pub unsafe extern "C" fn pread(
476     fildes: ::c_int,
477     buf: *mut ::c_void,
478     nbyte: ::size_t,
479     offset: ::off_t,
480 ) -> ::ssize_t {
481     //TODO: better pread using system calls
482 
483     let previous = ::lseek(fildes, offset, SEEK_SET);
484     if previous == -1 {
485         return -1;
486     }
487 
488     let res = ::read(fildes, buf, nbyte);
489     if res < 0 {
490         return res;
491     }
492 
493     if ::lseek(fildes, previous, SEEK_SET) == -1 {
494         return -1;
495     }
496 
497     res
498 }
499 
500 #[no_mangle]
501 pub extern "C" fn pthread_atfork(
502     prepare: Option<extern "C" fn()>,
503     parent: Option<extern "C" fn()>,
504     child: Option<extern "C" fn()>,
505 ) -> ::c_int {
506     let fork_hooks = unsafe { init_fork_hooks() };
507     if let Some(prepare) = prepare {
508         fork_hooks[0].push_back(prepare);
509     }
510     if let Some(parent) = parent {
511         fork_hooks[1].push_back(parent);
512     }
513     if let Some(child) = child {
514         fork_hooks[2].push_back(child);
515     }
516     0
517 }
518 
519 #[no_mangle]
520 pub unsafe extern "C" fn pwrite(
521     fildes: ::c_int,
522     buf: *const ::c_void,
523     nbyte: ::size_t,
524     offset: ::off_t,
525 ) -> ::ssize_t {
526     //TODO: better pwrite using system calls
527 
528     let previous = ::lseek(fildes, offset, SEEK_SET);
529     if previous == -1 {
530         return -1;
531     }
532 
533     let res = ::write(fildes, buf, nbyte);
534     if res < 0 {
535         return res;
536     }
537 
538     if ::lseek(fildes, previous, SEEK_SET) == -1 {
539         return -1;
540     }
541 
542     res
543 }
544 
545 // #[no_mangle]
546 // pub extern "C" fn read(fildes: ::c_int, buf: *const ::c_void, nbyte: ::size_t) -> ::ssize_t {
547 //     trace_expr!(
548 //         platform::pal::read(fildes, buf as *mut ::c_void,nbyte),
549 //         "read({}, {:p}, {})",
550 //         fildes,
551 //         buf,
552 //         nbyte
553 //     )
554 // }
555 
556 // #[no_mangle]
557 // pub unsafe extern "C" fn readlink(
558 //     path: *const ::c_char,
559 //     buf: *mut ::c_char,
560 //     bufsize: ::size_t,
561 // ) -> ::ssize_t {
562 //     platform::pal::readlink(path, buf,bufsize)
563 // }
564 
565 // #[no_mangle]
566 // pub unsafe extern "C" fn rmdir(path: *const ::c_char) -> ::c_int {
567 //     platform::pal::rmdir(path)
568 // }
569 
570 #[no_mangle]
571 pub extern "C" fn setgid(gid: ::gid_t) -> ::c_int {
572     platform::pal::setregid(gid, gid)
573 }
574 
575 // #[no_mangle]
576 // pub extern "C" fn setpgid(pid: ::pid_t, pgid: ::pid_t) -> ::c_int {
577 //     platform::pal::setpgid(pid, pgid)
578 // }
579 
580 #[no_mangle]
581 pub unsafe extern "C" fn setpgrp() -> ::pid_t {
582     ::setpgid(0, 0)
583 }
584 
585 // #[no_mangle]
586 // pub extern "C" fn setregid(rgid: ::gid_t, egid: ::gid_t) -> ::c_int {
587 //     platform::pal::setregid(rgid, egid)
588 // }
589 
590 // #[no_mangle]
591 // pub extern "C" fn setreuid(ruid: ::uid_t, euid: ::uid_t) -> ::c_int {
592 //     platform::pal::setreuid(ruid, euid)
593 // }
594 
595 // #[no_mangle]
596 // pub extern "C" fn setsid() -> ::pid_t {
597 //     unimplemented!();
598 // }
599 
600 // #[no_mangle]
601 // pub extern "C" fn setuid(uid: ::uid_t) -> ::c_int {
602 //     platform::pal::setreuid(uid, uid)
603 // }
604 
605 #[no_mangle]
606 pub extern "C" fn sleep(seconds: ::c_uint) -> ::c_uint {
607     let rqtp = ::timespec {
608         tv_sec: seconds as ::time_t,
609         tv_nsec: 0,
610     };
611     let rmtp = ptr::null_mut();
612     platform::pal::nanosleep(&rqtp, rmtp);
613     0
614 }
615 
616 #[no_mangle]
617 pub extern "C" fn swab(src: *const ::c_void, dest: *mut ::c_void, nbytes: ::ssize_t) {
618     if nbytes <= 0 {
619         return;
620     }
621     let number_of_swaps = nbytes / 2;
622     let mut offset = 0;
623     for _i in 0..number_of_swaps {
624         unsafe {
625             src.offset(offset).copy_to(dest.offset(offset + 1), 1);
626             src.offset(offset + 1).copy_to(dest.offset(offset), 1);
627         }
628         offset += 2;
629     }
630 }
631 
632 // #[no_mangle]
633 // pub unsafe extern "C" fn symlink(path1: *const ::c_char, path2: *const ::c_char) -> ::c_int {
634 //     platform::pal::symlink(path1, path2)
635 // }
636 
637 // #[no_mangle]
638 pub extern "C" fn sync() {
639     unimplemented!();
640 }
641 
642 #[no_mangle]
643 pub extern "C" fn tcgetpgrp(fd: ::c_int) -> ::pid_t {
644     let mut pgrp = 0;
645     if unsafe { ioctl(fd, TIOCGPGRP, &mut pgrp as *mut ::pid_t as *mut ::c_void) } < 0 {
646         return -1;
647     }
648     pgrp
649 }
650 
651 #[no_mangle]
652 pub extern "C" fn tcsetpgrp(fd: ::c_int, pgrp: ::pid_t) -> ::c_int {
653     if unsafe { ioctl(fd, TIOCSPGRP, &pgrp as *const ::pid_t as *mut ::c_void) } < 0 {
654         return -1;
655     }
656     pgrp
657 }
658 
659 #[no_mangle]
660 pub extern "C" fn truncate(path: *const ::c_char, length: ::off_t) -> ::c_int {
661     let fd = platform::pal::open(path, ::O_WRONLY, 0);
662     if fd < 0 {
663         return -1;
664     }
665 
666     let res = unsafe { ::ftruncate(fd, length) };
667 
668     platform::pal::close(fd);
669 
670     res
671 }
672 
673 #[no_mangle]
674 pub unsafe extern "C" fn ttyname(fildes: ::c_int) -> *mut ::c_char {
675     static mut TTYNAME: [::c_char; 4096] = [0; 4096];
676     if ttyname_r(fildes, TTYNAME.as_mut_ptr(), TTYNAME.len()) == 0 {
677         TTYNAME.as_mut_ptr()
678     } else {
679         ptr::null_mut()
680     }
681 }
682 
683 #[no_mangle]
684 pub extern "C" fn ttyname_r(fildes: ::c_int, name: *mut ::c_char, namesize: ::size_t) -> ::c_int {
685     let name = unsafe { slice::from_raw_parts_mut(name as *mut u8, namesize) };
686     if name.is_empty() {
687         return errno::ERANGE;
688     }
689 
690     let len = platform::pal::fpath(fildes, (&mut name[..namesize - 1]).as_ptr() as *const i8);
691     if len < 0 {
692         return unsafe { -platform::errno };
693     }
694     name[len as usize] = 0;
695 
696     0
697 }
698 
699 #[no_mangle]
700 pub extern "C" fn ualarm(usecs: ::useconds_t, interval: ::useconds_t) -> ::useconds_t {
701     let mut timer = sys_time::itimerval {
702         it_value: sys_time::timeval {
703             tv_sec: 0,
704             tv_usec: usecs as ::suseconds_t,
705         },
706         it_interval: sys_time::timeval {
707             tv_sec: 0,
708             tv_usec: interval as ::suseconds_t,
709         },
710     };
711     let errno_backup = unsafe { platform::errno };
712     let ret = if ::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) < 0 {
713         0
714     } else {
715         timer.it_value.tv_sec as ::useconds_t * 1_000_000 + timer.it_value.tv_usec as ::useconds_t
716     };
717     unsafe {
718         platform::errno = errno_backup;
719     }
720 
721     ret
722 }
723 
724 // #[no_mangle]
725 // pub unsafe extern "C" fn unlink(path: *const ::c_char) -> ::c_int {
726 //     platform::pal::unlink(path)
727 // }
728 
729 #[no_mangle]
730 pub extern "C" fn usleep(useconds: ::useconds_t) -> ::c_int {
731     let rqtp = ::timespec {
732         tv_sec: (useconds / 1_000_000) as ::time_t,
733         tv_nsec: ((useconds % 1_000_000) * 1000) as ::c_long,
734     };
735     let rmtp = ptr::null_mut();
736     platform::pal::nanosleep(&rqtp, rmtp)
737 }
738 
739 // #[no_mangle]
740 // pub extern "C" fn vfork() -> ::pid_t {
741 //     unimplemented!();
742 // }
743 
744 // #[no_mangle]
745 // pub extern "C" fn write(fildes: ::c_int, buf: *const ::c_void, nbyte: ::size_t) -> ::ssize_t {
746 //     platform::pal::write(fildes, buf, nbyte)
747 // }
748