mod.rs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. //! unistd implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/unistd.h.html
  2. use core::{mem, ptr, slice};
  3. use c_str::CStr;
  4. use header::errno;
  5. use header::limits;
  6. use header::stdlib::getenv;
  7. use header::sys_ioctl;
  8. use header::sys_time;
  9. use header::termios;
  10. use header::time::timespec;
  11. use platform;
  12. use platform::types::*;
  13. use platform::{Pal, Sys};
  14. pub use self::brk::*;
  15. pub use self::getopt::*;
  16. pub use self::pathconf::*;
  17. pub use self::sysconf::*;
  18. mod brk;
  19. mod getopt;
  20. mod pathconf;
  21. mod sysconf;
  22. pub const F_OK: c_int = 0;
  23. pub const R_OK: c_int = 4;
  24. pub const W_OK: c_int = 2;
  25. pub const X_OK: c_int = 1;
  26. pub const SEEK_SET: c_int = 0;
  27. pub const SEEK_CUR: c_int = 1;
  28. pub const SEEK_END: c_int = 2;
  29. pub const F_ULOCK: c_int = 0;
  30. pub const F_LOCK: c_int = 1;
  31. pub const F_TLOCK: c_int = 2;
  32. pub const F_TEST: c_int = 3;
  33. pub const STDIN_FILENO: c_int = 0;
  34. pub const STDOUT_FILENO: c_int = 1;
  35. pub const STDERR_FILENO: c_int = 2;
  36. #[no_mangle]
  37. pub extern "C" fn _exit(status: c_int) {
  38. Sys::exit(status)
  39. }
  40. #[no_mangle]
  41. pub unsafe extern "C" fn access(path: *const c_char, mode: c_int) -> c_int {
  42. let path = CStr::from_ptr(path);
  43. Sys::access(path, mode)
  44. }
  45. #[no_mangle]
  46. pub extern "C" fn alarm(seconds: c_uint) -> c_uint {
  47. let mut timer = sys_time::itimerval {
  48. it_value: sys_time::timeval {
  49. tv_sec: seconds as time_t,
  50. tv_usec: 0,
  51. },
  52. ..Default::default()
  53. };
  54. let errno_backup = unsafe { platform::errno };
  55. let secs = if sys_time::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) < 0 {
  56. 0
  57. } else {
  58. timer.it_value.tv_sec as c_uint + if timer.it_value.tv_usec > 0 { 1 } else { 0 }
  59. };
  60. unsafe {
  61. platform::errno = errno_backup;
  62. }
  63. secs
  64. }
  65. #[no_mangle]
  66. pub unsafe extern "C" fn chdir(path: *const c_char) -> c_int {
  67. let path = CStr::from_ptr(path);
  68. Sys::chdir(path)
  69. }
  70. // #[no_mangle]
  71. pub extern "C" fn chroot(path: *const c_char) -> c_int {
  72. unimplemented!();
  73. }
  74. #[no_mangle]
  75. pub unsafe extern "C" fn chown(path: *const c_char, owner: uid_t, group: gid_t) -> c_int {
  76. let path = CStr::from_ptr(path);
  77. Sys::chown(path, owner, group)
  78. }
  79. #[no_mangle]
  80. pub extern "C" fn close(fildes: c_int) -> c_int {
  81. Sys::close(fildes)
  82. }
  83. // #[no_mangle]
  84. pub extern "C" fn confstr(name: c_int, buf: *mut c_char, len: size_t) -> size_t {
  85. unimplemented!();
  86. }
  87. // #[no_mangle]
  88. pub extern "C" fn crypt(key: *const c_char, salt: *const c_char) -> *mut c_char {
  89. unimplemented!();
  90. }
  91. #[no_mangle]
  92. pub extern "C" fn dup(fildes: c_int) -> c_int {
  93. Sys::dup(fildes)
  94. }
  95. #[no_mangle]
  96. pub extern "C" fn dup2(fildes: c_int, fildes2: c_int) -> c_int {
  97. Sys::dup2(fildes, fildes2)
  98. }
  99. // #[no_mangle]
  100. pub extern "C" fn encrypt(block: [c_char; 64], edflag: c_int) {
  101. unimplemented!();
  102. }
  103. // #[no_mangle]
  104. // pub extern "C" fn execl(path: *const c_char, args: *const *mut c_char) -> c_int {
  105. // unimplemented!();
  106. // }
  107. // #[no_mangle]
  108. // pub extern "C" fn execle(
  109. // path: *const c_char,
  110. // args: *const *mut c_char,
  111. // envp: *const *mut c_char,
  112. // ) -> c_int {
  113. // unimplemented!();
  114. // }
  115. // #[no_mangle]
  116. // pub extern "C" fn execlp(file: *const c_char, args: *const *mut c_char) -> c_int {
  117. // unimplemented!();
  118. // }
  119. #[no_mangle]
  120. pub unsafe extern "C" fn execv(path: *const c_char, argv: *const *mut c_char) -> c_int {
  121. execve(path, argv, platform::environ)
  122. }
  123. #[no_mangle]
  124. pub unsafe extern "C" fn execve(
  125. path: *const c_char,
  126. argv: *const *mut c_char,
  127. envp: *const *mut c_char,
  128. ) -> c_int {
  129. let path = CStr::from_ptr(path);
  130. Sys::execve(path, argv, envp)
  131. }
  132. #[cfg(target_os = "linux")]
  133. const PATH_SEPARATOR: u8 = b':';
  134. #[cfg(target_os = "redox")]
  135. const PATH_SEPARATOR: u8 = b';';
  136. #[no_mangle]
  137. pub unsafe extern "C" fn execvp(file: *const c_char, argv: *const *mut c_char) -> c_int {
  138. let file = CStr::from_ptr(file);
  139. if file.to_bytes().contains(&b'/')
  140. || (cfg!(target_os = "redox") && file.to_bytes().contains(&b':'))
  141. {
  142. execv(file.as_ptr(), argv)
  143. } else {
  144. let mut error = errno::ENOENT;
  145. let path_env = getenv(c_str!("PATH\0").as_ptr());
  146. if !path_env.is_null() {
  147. let path_env = CStr::from_ptr(path_env);
  148. for path in path_env.to_bytes().split(|&b| b == PATH_SEPARATOR) {
  149. let mut program = path.to_vec();
  150. program.push(b'/');
  151. program.extend_from_slice(file.to_bytes());
  152. program.push(b'\0');
  153. let program_c = CStr::from_bytes_with_nul(&program).unwrap();
  154. execv(program_c.as_ptr(), argv);
  155. match platform::errno {
  156. errno::ENOENT => (),
  157. other => error = other,
  158. }
  159. }
  160. }
  161. platform::errno = error;
  162. -1
  163. }
  164. }
  165. #[no_mangle]
  166. pub extern "C" fn fchown(fildes: c_int, owner: uid_t, group: gid_t) -> c_int {
  167. Sys::fchown(fildes, owner, group)
  168. }
  169. #[no_mangle]
  170. pub extern "C" fn fchdir(fildes: c_int) -> c_int {
  171. Sys::fchdir(fildes)
  172. }
  173. // #[no_mangle]
  174. pub extern "C" fn fdatasync(fildes: c_int) -> c_int {
  175. unimplemented!();
  176. }
  177. #[no_mangle]
  178. pub extern "C" fn fork() -> pid_t {
  179. Sys::fork()
  180. }
  181. #[no_mangle]
  182. pub extern "C" fn fsync(fildes: c_int) -> c_int {
  183. Sys::fsync(fildes)
  184. }
  185. #[no_mangle]
  186. pub extern "C" fn ftruncate(fildes: c_int, length: off_t) -> c_int {
  187. Sys::ftruncate(fildes, length)
  188. }
  189. #[no_mangle]
  190. pub extern "C" fn getcwd(mut buf: *mut c_char, mut size: size_t) -> *mut c_char {
  191. let alloc = buf.is_null();
  192. let mut stack_buf = [0; limits::PATH_MAX];
  193. if alloc {
  194. buf = stack_buf.as_mut_ptr();
  195. size = stack_buf.len();
  196. }
  197. let ret = Sys::getcwd(buf, size);
  198. if ret.is_null() {
  199. return ptr::null_mut();
  200. }
  201. if alloc {
  202. let len = stack_buf
  203. .iter()
  204. .position(|b| *b == 0)
  205. .expect("no nul-byte in getcwd string")
  206. + 1;
  207. let heap_buf = unsafe { platform::alloc(len) as *mut c_char };
  208. for i in 0..len {
  209. unsafe {
  210. *heap_buf.add(i) = stack_buf[i];
  211. }
  212. }
  213. heap_buf
  214. } else {
  215. ret
  216. }
  217. }
  218. // #[no_mangle]
  219. pub extern "C" fn getdtablesize() -> c_int {
  220. unimplemented!();
  221. }
  222. #[no_mangle]
  223. pub extern "C" fn getegid() -> gid_t {
  224. Sys::getegid()
  225. }
  226. #[no_mangle]
  227. pub extern "C" fn geteuid() -> uid_t {
  228. Sys::geteuid()
  229. }
  230. #[no_mangle]
  231. pub extern "C" fn getgid() -> gid_t {
  232. Sys::getgid()
  233. }
  234. // #[no_mangle]
  235. pub extern "C" fn getgroups(gidsetsize: c_int, grouplist: *mut gid_t) -> c_int {
  236. unimplemented!();
  237. }
  238. // #[no_mangle]
  239. pub extern "C" fn gethostid() -> c_long {
  240. unimplemented!();
  241. }
  242. #[no_mangle]
  243. pub unsafe extern "C" fn gethostname(mut name: *mut c_char, mut len: size_t) -> c_int {
  244. let mut uts = mem::uninitialized();
  245. let err = Sys::uname(&mut uts);
  246. if err < 0 {
  247. mem::forget(uts);
  248. return err;
  249. }
  250. for c in uts.nodename.iter() {
  251. if len == 0 {
  252. break;
  253. }
  254. len -= 1;
  255. *name = *c;
  256. if *name == 0 {
  257. // We do want to copy the zero also, so we check this after the copying.
  258. break;
  259. }
  260. name = name.offset(1);
  261. }
  262. 0
  263. }
  264. #[no_mangle]
  265. pub unsafe extern "C" fn getlogin() -> *mut c_char {
  266. static mut LOGIN: [c_char; 256] = [0; 256];
  267. if getlogin_r(LOGIN.as_mut_ptr(), LOGIN.len()) == 0 {
  268. LOGIN.as_mut_ptr()
  269. } else {
  270. ptr::null_mut()
  271. }
  272. }
  273. #[no_mangle]
  274. pub extern "C" fn getlogin_r(name: *mut c_char, namesize: size_t) -> c_int {
  275. //TODO: Determine correct getlogin result on Redox
  276. unsafe { platform::errno = errno::ENOENT };
  277. -1
  278. }
  279. #[no_mangle]
  280. pub extern "C" fn getpagesize() -> c_int {
  281. sysconf(_SC_PAGESIZE) as c_int
  282. }
  283. // #[no_mangle]
  284. pub extern "C" fn getpass(prompt: *const c_char) -> *mut c_char {
  285. unimplemented!();
  286. }
  287. #[no_mangle]
  288. pub extern "C" fn getpgid(pid: pid_t) -> pid_t {
  289. Sys::getpgid(pid)
  290. }
  291. #[no_mangle]
  292. pub extern "C" fn getpgrp() -> pid_t {
  293. Sys::getpgid(Sys::getpid())
  294. }
  295. #[no_mangle]
  296. pub extern "C" fn getpid() -> pid_t {
  297. Sys::getpid()
  298. }
  299. #[no_mangle]
  300. pub extern "C" fn getppid() -> pid_t {
  301. Sys::getppid()
  302. }
  303. // #[no_mangle]
  304. pub extern "C" fn getsid(pid: pid_t) -> pid_t {
  305. unimplemented!();
  306. }
  307. #[no_mangle]
  308. pub extern "C" fn getuid() -> uid_t {
  309. Sys::getuid()
  310. }
  311. #[no_mangle]
  312. pub extern "C" fn getwd(path_name: *mut c_char) -> *mut c_char {
  313. getcwd(path_name, limits::PATH_MAX)
  314. }
  315. #[no_mangle]
  316. pub extern "C" fn isatty(fd: c_int) -> c_int {
  317. let mut t = termios::termios::default();
  318. if unsafe { termios::tcgetattr(fd, &mut t as *mut termios::termios) == 0 } {
  319. 1
  320. } else {
  321. 0
  322. }
  323. }
  324. // #[no_mangle]
  325. pub extern "C" fn lchown(path: *const c_char, owner: uid_t, group: gid_t) -> c_int {
  326. unimplemented!();
  327. }
  328. #[no_mangle]
  329. pub unsafe extern "C" fn link(path1: *const c_char, path2: *const c_char) -> c_int {
  330. let path1 = CStr::from_ptr(path1);
  331. let path2 = CStr::from_ptr(path2);
  332. Sys::link(path1, path2)
  333. }
  334. // #[no_mangle]
  335. pub extern "C" fn lockf(fildes: c_int, function: c_int, size: off_t) -> c_int {
  336. unimplemented!();
  337. }
  338. #[no_mangle]
  339. pub extern "C" fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> off_t {
  340. Sys::lseek(fildes, offset, whence)
  341. }
  342. // #[no_mangle]
  343. pub extern "C" fn nice(incr: c_int) -> c_int {
  344. unimplemented!();
  345. }
  346. // #[no_mangle]
  347. pub extern "C" fn pause() -> c_int {
  348. unimplemented!();
  349. }
  350. #[no_mangle]
  351. pub unsafe extern "C" fn pipe(fildes: *mut c_int) -> c_int {
  352. pipe2(fildes, 0)
  353. }
  354. #[no_mangle]
  355. pub unsafe extern "C" fn pipe2(fildes: *mut c_int, flags: c_int) -> c_int {
  356. Sys::pipe2(slice::from_raw_parts_mut(fildes, 2), flags)
  357. }
  358. #[no_mangle]
  359. pub extern "C" fn pread(fildes: c_int, buf: *mut c_void, nbyte: size_t, offset: off_t) -> ssize_t {
  360. //TODO: better pread using system calls
  361. let previous = lseek(fildes, offset, SEEK_SET);
  362. if previous == -1 {
  363. return -1;
  364. }
  365. let res = read(fildes, buf, nbyte);
  366. if res < 0 {
  367. return res;
  368. }
  369. if lseek(fildes, previous, SEEK_SET) == -1 {
  370. return -1;
  371. }
  372. res
  373. }
  374. #[no_mangle]
  375. pub extern "C" fn pthread_atfork(
  376. prepare: Option<extern "C" fn()>,
  377. parent: Option<extern "C" fn()>,
  378. child: Option<extern "C" fn()>,
  379. ) -> c_int {
  380. // TODO: WIP implementation available in "atfork" branch. It's
  381. // segfaulting at the thread-local stuff, both in Unix and Redox.
  382. // unimplemented!();
  383. 0
  384. }
  385. #[no_mangle]
  386. pub extern "C" fn pwrite(
  387. fildes: c_int,
  388. buf: *const c_void,
  389. nbyte: size_t,
  390. offset: off_t,
  391. ) -> ssize_t {
  392. //TODO: better pwrite using system calls
  393. let previous = lseek(fildes, offset, SEEK_SET);
  394. if previous == -1 {
  395. return -1;
  396. }
  397. let res = write(fildes, buf, nbyte);
  398. if res < 0 {
  399. return res;
  400. }
  401. if lseek(fildes, previous, SEEK_SET) == -1 {
  402. return -1;
  403. }
  404. res
  405. }
  406. #[no_mangle]
  407. pub extern "C" fn read(fildes: c_int, buf: *const c_void, nbyte: size_t) -> ssize_t {
  408. let buf = unsafe { slice::from_raw_parts_mut(buf as *mut u8, nbyte as usize) };
  409. trace_expr!(
  410. Sys::read(fildes, buf),
  411. "read({}, {:p}, {})",
  412. fildes,
  413. buf,
  414. nbyte
  415. )
  416. }
  417. #[no_mangle]
  418. pub unsafe extern "C" fn readlink(
  419. path: *const c_char,
  420. buf: *mut c_char,
  421. bufsize: size_t,
  422. ) -> ssize_t {
  423. let path = CStr::from_ptr(path);
  424. let buf = slice::from_raw_parts_mut(buf as *mut u8, bufsize as usize);
  425. Sys::readlink(path, buf)
  426. }
  427. #[no_mangle]
  428. pub unsafe extern "C" fn rmdir(path: *const c_char) -> c_int {
  429. let path = CStr::from_ptr(path);
  430. Sys::rmdir(path)
  431. }
  432. #[no_mangle]
  433. pub extern "C" fn setgid(gid: gid_t) -> c_int {
  434. Sys::setregid(gid, gid)
  435. }
  436. #[no_mangle]
  437. pub extern "C" fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
  438. Sys::setpgid(pid, pgid)
  439. }
  440. #[no_mangle]
  441. pub extern "C" fn setpgrp() -> pid_t {
  442. setpgid(0, 0)
  443. }
  444. #[no_mangle]
  445. pub extern "C" fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
  446. Sys::setregid(rgid, egid)
  447. }
  448. #[no_mangle]
  449. pub extern "C" fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
  450. Sys::setreuid(ruid, euid)
  451. }
  452. // #[no_mangle]
  453. pub extern "C" fn setsid() -> pid_t {
  454. unimplemented!();
  455. }
  456. #[no_mangle]
  457. pub extern "C" fn setuid(uid: uid_t) -> c_int {
  458. Sys::setreuid(uid, uid)
  459. }
  460. #[no_mangle]
  461. pub extern "C" fn sleep(seconds: c_uint) -> c_uint {
  462. let rqtp = timespec {
  463. tv_sec: seconds as i64,
  464. tv_nsec: 0,
  465. };
  466. let rmtp = ptr::null_mut();
  467. Sys::nanosleep(&rqtp, rmtp);
  468. 0
  469. }
  470. #[no_mangle]
  471. pub extern "C" fn swab(src: *const c_void, dest: *mut c_void, nbytes: ssize_t) {
  472. if nbytes <= 0 {
  473. return;
  474. }
  475. let number_of_swaps = nbytes / 2;
  476. let mut offset = 0;
  477. for i in 0..number_of_swaps {
  478. unsafe {
  479. src.offset(offset).copy_to(dest.offset(offset + 1), 1);
  480. src.offset(offset + 1).copy_to(dest.offset(offset), 1);
  481. }
  482. offset += 2;
  483. }
  484. }
  485. #[no_mangle]
  486. pub unsafe extern "C" fn symlink(path1: *const c_char, path2: *const c_char) -> c_int {
  487. let path1 = CStr::from_ptr(path1);
  488. let path2 = CStr::from_ptr(path2);
  489. Sys::symlink(path1, path2)
  490. }
  491. // #[no_mangle]
  492. pub extern "C" fn sync() {
  493. unimplemented!();
  494. }
  495. #[no_mangle]
  496. pub extern "C" fn tcgetpgrp(fd: c_int) -> pid_t {
  497. let mut pgrp = 0;
  498. if unsafe { sys_ioctl::ioctl(fd, sys_ioctl::TIOCGPGRP, &mut pgrp as *mut pid_t as _) } < 0 {
  499. return -1;
  500. }
  501. pgrp
  502. }
  503. #[no_mangle]
  504. pub extern "C" fn tcsetpgrp(fd: c_int, pgrp: pid_t) -> c_int {
  505. if unsafe { sys_ioctl::ioctl(fd, sys_ioctl::TIOCSPGRP, &pgrp as *const pid_t as _) } < 0 {
  506. return -1;
  507. }
  508. pgrp
  509. }
  510. // #[no_mangle]
  511. pub extern "C" fn truncate(path: *const c_char, length: off_t) -> c_int {
  512. unimplemented!();
  513. }
  514. #[no_mangle]
  515. pub unsafe extern "C" fn ttyname(fildes: c_int) -> *mut c_char {
  516. static mut TTYNAME: [c_char; 4096] = [0; 4096];
  517. if ttyname_r(fildes, TTYNAME.as_mut_ptr(), TTYNAME.len()) == 0 {
  518. TTYNAME.as_mut_ptr()
  519. } else {
  520. ptr::null_mut()
  521. }
  522. }
  523. #[no_mangle]
  524. pub extern "C" fn ttyname_r(fildes: c_int, name: *mut c_char, namesize: size_t) -> c_int {
  525. let name = unsafe { slice::from_raw_parts_mut(name as *mut u8, namesize) };
  526. if name.is_empty() {
  527. return errno::ERANGE;
  528. }
  529. let len = Sys::fpath(fildes, &mut name[..namesize - 1]);
  530. if len < 0 {
  531. return unsafe { -platform::errno };
  532. }
  533. name[len as usize] = 0;
  534. 0
  535. }
  536. #[no_mangle]
  537. pub extern "C" fn ualarm(usecs: useconds_t, interval: useconds_t) -> useconds_t {
  538. let mut timer = sys_time::itimerval {
  539. it_value: sys_time::timeval {
  540. tv_sec: 0,
  541. tv_usec: usecs as suseconds_t,
  542. },
  543. it_interval: sys_time::timeval {
  544. tv_sec: 0,
  545. tv_usec: interval as suseconds_t,
  546. },
  547. };
  548. let errno_backup = unsafe { platform::errno };
  549. let ret = if sys_time::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) < 0 {
  550. 0
  551. } else {
  552. timer.it_value.tv_sec as useconds_t * 1_000_000 + timer.it_value.tv_usec as useconds_t
  553. };
  554. unsafe {
  555. platform::errno = errno_backup;
  556. }
  557. ret
  558. }
  559. #[no_mangle]
  560. pub unsafe extern "C" fn unlink(path: *const c_char) -> c_int {
  561. let path = CStr::from_ptr(path);
  562. Sys::unlink(path)
  563. }
  564. #[no_mangle]
  565. pub extern "C" fn usleep(useconds: useconds_t) -> c_int {
  566. let rqtp = timespec {
  567. tv_sec: (useconds / 1_000_000) as i64,
  568. tv_nsec: ((useconds % 1_000_000) * 1000) as i64,
  569. };
  570. let rmtp = ptr::null_mut();
  571. Sys::nanosleep(&rqtp, rmtp)
  572. }
  573. // #[no_mangle]
  574. pub extern "C" fn vfork() -> pid_t {
  575. unimplemented!();
  576. }
  577. #[no_mangle]
  578. pub extern "C" fn write(fildes: c_int, buf: *const c_void, nbyte: size_t) -> ssize_t {
  579. let buf = unsafe { slice::from_raw_parts(buf as *const u8, nbyte as usize) };
  580. Sys::write(fildes, buf)
  581. }