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