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