mod.rs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. //! sys/socket implementation, following http://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/socket.h.html
  2. use alloc::btree_map::BTreeMap;
  3. use core::fmt::Write;
  4. use core::{mem, ptr, slice};
  5. use spin::{Mutex, MutexGuard, Once};
  6. use syscall::data::Stat as redox_stat;
  7. use syscall::data::TimeSpec as redox_timespec;
  8. use syscall::flag::*;
  9. use syscall::{self, Result};
  10. use c_str::{CStr, CString};
  11. use header::dirent::dirent;
  12. use header::errno::{EINVAL, ENOSYS};
  13. const MAP_ANON: c_int = 1;
  14. //use header::sys_mman::MAP_ANON;
  15. //use header::sys_resource::rusage;
  16. use header::sys_select::fd_set;
  17. use header::sys_stat::stat;
  18. use header::sys_time::{itimerval, timeval, timezone};
  19. //use header::sys_times::tms;
  20. use header::sys_utsname::utsname;
  21. use header::termios::termios;
  22. use header::time::timespec;
  23. use header::unistd::{F_OK, R_OK, SEEK_SET, W_OK, X_OK};
  24. use super::types::*;
  25. use super::{errno, FileReader, FileWriter, Line, Pal, RawFile, RawLineBuffer, Read};
  26. mod signal;
  27. mod socket;
  28. static ANONYMOUS_MAPS: Once<Mutex<BTreeMap<usize, usize>>> = Once::new();
  29. fn anonymous_maps() -> MutexGuard<'static, BTreeMap<usize, usize>> {
  30. ANONYMOUS_MAPS
  31. .call_once(|| Mutex::new(BTreeMap::new()))
  32. .lock()
  33. }
  34. fn e(sys: Result<usize>) -> usize {
  35. match sys {
  36. Ok(ok) => ok,
  37. Err(err) => {
  38. unsafe {
  39. errno = err.errno as c_int;
  40. }
  41. !0
  42. }
  43. }
  44. }
  45. pub struct Sys;
  46. impl Pal for Sys {
  47. fn access(path: &CStr, mode: c_int) -> c_int {
  48. let fd = match RawFile::open(path, 0, 0) {
  49. Ok(fd) => fd,
  50. Err(_) => return -1,
  51. };
  52. if mode == F_OK {
  53. return 0;
  54. }
  55. let mut stat = syscall::Stat::default();
  56. if e(syscall::fstat(*fd as usize, &mut stat)) == !0 {
  57. return -1;
  58. }
  59. let uid = e(syscall::getuid());
  60. if uid == !0 {
  61. return -1;
  62. }
  63. let gid = e(syscall::getgid());
  64. if gid == !0 {
  65. return -1;
  66. }
  67. let perms = if stat.st_uid as usize == uid {
  68. // octal has max 7 characters, binary has max two. And we're interested
  69. // in the 3rd digit
  70. stat.st_mode >> ((7 / 2) * 2 & 0o7)
  71. } else if stat.st_gid as usize == gid {
  72. stat.st_mode >> ((7 / 2) & 0o7)
  73. } else {
  74. stat.st_mode & 0o7
  75. };
  76. if (mode & R_OK == R_OK && perms & 0o4 != 0o4)
  77. || (mode & W_OK == W_OK && perms & 0o2 != 0o2)
  78. || (mode & X_OK == X_OK && perms & 0o1 != 0o1)
  79. {
  80. unsafe {
  81. errno = EINVAL;
  82. }
  83. return -1;
  84. }
  85. 0
  86. }
  87. fn brk(addr: *mut c_void) -> *mut c_void {
  88. unsafe { syscall::brk(addr as usize).unwrap_or(0) as *mut c_void }
  89. }
  90. fn chdir(path: &CStr) -> c_int {
  91. e(syscall::chdir(path.to_bytes())) as c_int
  92. }
  93. fn chmod(path: &CStr, mode: mode_t) -> c_int {
  94. match syscall::open(path.to_bytes(), O_WRONLY) {
  95. Err(err) => e(Err(err)) as c_int,
  96. Ok(fd) => {
  97. let res = syscall::fchmod(fd as usize, mode as u16);
  98. let _ = syscall::close(fd);
  99. e(res) as c_int
  100. }
  101. }
  102. }
  103. fn chown(path: &CStr, owner: uid_t, group: gid_t) -> c_int {
  104. match syscall::open(path.to_bytes(), O_WRONLY) {
  105. Err(err) => e(Err(err)) as c_int,
  106. Ok(fd) => {
  107. let res = syscall::fchown(fd as usize, owner as u32, group as u32);
  108. let _ = syscall::close(fd);
  109. e(res) as c_int
  110. }
  111. }
  112. }
  113. fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int {
  114. let mut redox_tp = unsafe { redox_timespec::from(&*tp) };
  115. match e(syscall::clock_gettime(clk_id as usize, &mut redox_tp)) as c_int {
  116. -1 => -1,
  117. _ => {
  118. unsafe {
  119. (*tp).tv_sec = redox_tp.tv_sec;
  120. (*tp).tv_nsec = redox_tp.tv_nsec as i64;
  121. };
  122. 0
  123. }
  124. }
  125. }
  126. fn close(fd: c_int) -> c_int {
  127. e(syscall::close(fd as usize)) as c_int
  128. }
  129. fn dup(fd: c_int) -> c_int {
  130. e(syscall::dup(fd as usize, &[])) as c_int
  131. }
  132. fn dup2(fd1: c_int, fd2: c_int) -> c_int {
  133. e(syscall::dup2(fd1 as usize, fd2 as usize, &[])) as c_int
  134. }
  135. fn exit(status: c_int) -> ! {
  136. let _ = syscall::exit(status as usize);
  137. loop {}
  138. }
  139. unsafe fn execve(
  140. path: &CStr,
  141. mut argv: *const *mut c_char,
  142. mut envp: *const *mut c_char,
  143. ) -> c_int {
  144. use alloc::Vec;
  145. let fd = match RawFile::open(path, O_RDONLY as c_int, 0) {
  146. Ok(fd) => fd,
  147. Err(_) => return -1,
  148. };
  149. // Count arguments
  150. let mut len = 0;
  151. while !(*argv.offset(len)).is_null() {
  152. len += 1;
  153. }
  154. let mut args: Vec<[usize; 2]> = Vec::with_capacity(len as usize);
  155. // Read shebang (for example #!/bin/sh)
  156. let mut shebang = [0; 2];
  157. let mut read = 0;
  158. while read < 2 {
  159. match Self::read(*fd, &mut shebang) {
  160. 0 => break,
  161. i if i < 0 => return -1,
  162. i => read += i,
  163. }
  164. }
  165. let mut _interpreter_path = None;
  166. let mut _interpreter_file = None;
  167. let mut interpreter_fd = *fd;
  168. if &shebang == b"#!" {
  169. match RawLineBuffer::new(*fd).next() {
  170. Line::Error => return -1,
  171. Line::EOF => (),
  172. Line::Some(line) => {
  173. let mut path = match CString::new(line) {
  174. Ok(path) => path,
  175. Err(_) => return -1,
  176. };
  177. match RawFile::open(&path, O_RDONLY as c_int, 0) {
  178. Ok(file) => {
  179. interpreter_fd = *file;
  180. _interpreter_path = Some(path);
  181. _interpreter_file = Some(file);
  182. let path_ref = _interpreter_path.as_ref().unwrap();
  183. args.push([path_ref.as_ptr() as usize, path_ref.to_bytes().len()]);
  184. }
  185. Err(_) => return -1,
  186. }
  187. }
  188. }
  189. }
  190. if Self::lseek(*fd, 0, SEEK_SET) < 0 {
  191. return -1;
  192. }
  193. // Arguments
  194. while !(*argv).is_null() {
  195. let arg = *argv;
  196. let mut len = 0;
  197. while *arg.offset(len) != 0 {
  198. len += 1;
  199. }
  200. args.push([arg as usize, len as usize]);
  201. argv = argv.offset(1);
  202. }
  203. // Environment variables
  204. let mut len = 0;
  205. while !(*envp.offset(len)).is_null() {
  206. len += 1;
  207. }
  208. let mut envs: Vec<[usize; 2]> = Vec::with_capacity(len as usize);
  209. while !(*envp).is_null() {
  210. let env = *envp;
  211. let mut len = 0;
  212. while *env.offset(len) != 0 {
  213. len += 1;
  214. }
  215. envs.push([env as usize, len as usize]);
  216. envp = envp.offset(1);
  217. }
  218. e(syscall::fexec(interpreter_fd as usize, &args, &envs)) as c_int
  219. }
  220. fn fchdir(fd: c_int) -> c_int {
  221. let path: &mut [u8] = &mut [0; 4096];
  222. if e(syscall::fpath(fd as usize, path)) == !0 {
  223. !0
  224. } else {
  225. e(syscall::chdir(path)) as c_int
  226. }
  227. }
  228. fn fchmod(fd: c_int, mode: mode_t) -> c_int {
  229. e(syscall::fchmod(fd as usize, mode as u16)) as c_int
  230. }
  231. fn fchown(fd: c_int, owner: uid_t, group: gid_t) -> c_int {
  232. e(syscall::fchown(fd as usize, owner as u32, group as u32)) as c_int
  233. }
  234. fn fcntl(fd: c_int, cmd: c_int, args: c_int) -> c_int {
  235. e(syscall::fcntl(fd as usize, cmd as usize, args as usize)) as c_int
  236. }
  237. fn flock(_fd: c_int, _operation: c_int) -> c_int {
  238. // TODO: Redox does not have file locking yet
  239. 0
  240. }
  241. fn fork() -> pid_t {
  242. e(unsafe { syscall::clone(0) }) as pid_t
  243. }
  244. fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
  245. let mut redox_buf: redox_stat = redox_stat::default();
  246. match e(syscall::fstat(fildes as usize, &mut redox_buf)) {
  247. 0 => {
  248. unsafe {
  249. if !buf.is_null() {
  250. (*buf).st_dev = redox_buf.st_dev as dev_t;
  251. (*buf).st_ino = redox_buf.st_ino as ino_t;
  252. (*buf).st_nlink = redox_buf.st_nlink as nlink_t;
  253. (*buf).st_mode = redox_buf.st_mode as mode_t;
  254. (*buf).st_uid = redox_buf.st_uid as uid_t;
  255. (*buf).st_gid = redox_buf.st_gid as gid_t;
  256. // TODO st_rdev
  257. (*buf).st_rdev = 0;
  258. (*buf).st_size = redox_buf.st_size as off_t;
  259. (*buf).st_blksize = redox_buf.st_blksize as blksize_t;
  260. (*buf).st_atim = timespec {
  261. tv_sec: redox_buf.st_atime as time_t,
  262. tv_nsec: redox_buf.st_atime_nsec as c_long,
  263. };
  264. (*buf).st_mtim = timespec {
  265. tv_sec: redox_buf.st_mtime as time_t,
  266. tv_nsec: redox_buf.st_mtime_nsec as c_long,
  267. };
  268. (*buf).st_ctim = timespec {
  269. tv_sec: redox_buf.st_ctime as time_t,
  270. tv_nsec: redox_buf.st_ctime_nsec as c_long,
  271. };
  272. }
  273. }
  274. 0
  275. }
  276. _ => -1,
  277. }
  278. }
  279. fn fsync(fd: c_int) -> c_int {
  280. e(syscall::fsync(fd as usize)) as c_int
  281. }
  282. fn ftruncate(fd: c_int, len: off_t) -> c_int {
  283. e(syscall::ftruncate(fd as usize, len as usize)) as c_int
  284. }
  285. fn futimens(fd: c_int, times: *const timespec) -> c_int {
  286. let times = [unsafe { redox_timespec::from(&*times) }, unsafe {
  287. redox_timespec::from(&*times.offset(1))
  288. }];
  289. e(syscall::futimens(fd as usize, &times)) as c_int
  290. }
  291. fn utimens(path: &CStr, times: *const timespec) -> c_int {
  292. match syscall::open(path.to_bytes(), O_STAT) {
  293. Err(err) => e(Err(err)) as c_int,
  294. Ok(fd) => {
  295. let res = Self::futimens(fd as c_int, times);
  296. let _ = syscall::close(fd);
  297. res
  298. }
  299. }
  300. }
  301. fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char {
  302. let buf_slice = unsafe { slice::from_raw_parts_mut(buf as *mut u8, size as usize - 1) };
  303. let read = e(syscall::getcwd(buf_slice));
  304. if read == !0 {
  305. ptr::null_mut()
  306. } else {
  307. unsafe {
  308. *buf.offset(read as isize + 1) = 0;
  309. }
  310. buf
  311. }
  312. }
  313. fn getdents(fd: c_int, mut dirents: *mut dirent, mut bytes: usize) -> c_int {
  314. let mut amount = 0;
  315. let mut buf = [0; 1024];
  316. let mut bindex = 0;
  317. let mut blen = 0;
  318. let mut name = [0; 256];
  319. let mut nindex = 0;
  320. loop {
  321. if bindex >= blen {
  322. bindex = 0;
  323. blen = match syscall::read(fd as usize, &mut buf) {
  324. Ok(0) => return amount,
  325. Ok(n) => n,
  326. Err(err) => return -err.errno,
  327. };
  328. }
  329. if buf[bindex] == b'\n' {
  330. // Put a NUL byte either at the end, or if it's too big, at where it's truncated.
  331. name[nindex.min(name.len() - 1)] = 0;
  332. unsafe {
  333. *dirents = dirent {
  334. d_ino: 0,
  335. d_off: 0,
  336. d_reclen: mem::size_of::<dirent>() as c_ushort,
  337. d_type: 0,
  338. d_name: name,
  339. };
  340. dirents = dirents.offset(1);
  341. }
  342. amount += 1;
  343. if bytes <= mem::size_of::<dirent>() {
  344. return amount;
  345. }
  346. bytes -= mem::size_of::<dirent>();
  347. } else {
  348. if nindex < name.len() {
  349. name[nindex] = buf[bindex] as c_char;
  350. }
  351. nindex += 1;
  352. bindex += 1;
  353. }
  354. }
  355. }
  356. fn getegid() -> gid_t {
  357. e(syscall::getegid()) as gid_t
  358. }
  359. fn geteuid() -> uid_t {
  360. e(syscall::geteuid()) as uid_t
  361. }
  362. fn getgid() -> gid_t {
  363. e(syscall::getgid()) as gid_t
  364. }
  365. unsafe fn gethostname(mut name: *mut c_char, len: size_t) -> c_int {
  366. let fd = e(syscall::open("/etc/hostname", O_RDONLY)) as i32;
  367. if fd < 0 {
  368. return fd;
  369. }
  370. let mut reader = FileReader(fd);
  371. for _ in 0..len {
  372. match reader.read_u8() {
  373. Ok(Some(b)) => {
  374. *name = b as c_char;
  375. name = name.offset(1);
  376. }
  377. Ok(None) => {
  378. *name = 0;
  379. break;
  380. }
  381. Err(()) => return -1,
  382. }
  383. }
  384. 0
  385. }
  386. fn getpgid(pid: pid_t) -> pid_t {
  387. e(syscall::getpgid(pid as usize)) as pid_t
  388. }
  389. fn getpid() -> pid_t {
  390. e(syscall::getpid()) as pid_t
  391. }
  392. fn getppid() -> pid_t {
  393. e(syscall::getppid()) as pid_t
  394. }
  395. fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int {
  396. let mut redox_tp = redox_timespec::default();
  397. let err = e(syscall::clock_gettime(
  398. syscall::CLOCK_REALTIME,
  399. &mut redox_tp,
  400. )) as c_int;
  401. if err < 0 {
  402. return err;
  403. }
  404. unsafe {
  405. (*tp).tv_sec = redox_tp.tv_sec as time_t;
  406. (*tp).tv_usec = (redox_tp.tv_nsec / 1000) as suseconds_t;
  407. if !tzp.is_null() {
  408. (*tzp).tz_minuteswest = 0;
  409. (*tzp).tz_dsttime = 0;
  410. }
  411. }
  412. 0
  413. }
  414. fn getuid() -> uid_t {
  415. e(syscall::getuid()) as pid_t
  416. }
  417. fn isatty(fd: c_int) -> c_int {
  418. syscall::dup(fd as usize, b"termios")
  419. .map(|fd| {
  420. let _ = syscall::close(fd);
  421. 1
  422. })
  423. .unwrap_or(0)
  424. }
  425. fn link(path1: &CStr, path2: &CStr) -> c_int {
  426. e(unsafe { syscall::link(path1.as_ptr() as *const u8, path2.as_ptr() as *const u8) })
  427. as c_int
  428. }
  429. fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t {
  430. e(syscall::lseek(
  431. fd as usize,
  432. offset as isize,
  433. whence as usize,
  434. )) as off_t
  435. }
  436. fn mkdir(path: &CStr, mode: mode_t) -> c_int {
  437. let flags = O_CREAT | O_EXCL | O_CLOEXEC | O_DIRECTORY | mode as usize & 0o777;
  438. match syscall::open(path.to_bytes(), flags) {
  439. Ok(fd) => {
  440. let _ = syscall::close(fd);
  441. 0
  442. }
  443. Err(err) => e(Err(err)) as c_int,
  444. }
  445. }
  446. fn mkfifo(path: &CStr, mode: mode_t) -> c_int {
  447. let flags = O_CREAT | MODE_FIFO as usize | mode as usize & 0o777;
  448. match syscall::open(path.to_bytes(), flags) {
  449. Ok(fd) => {
  450. let _ = syscall::close(fd);
  451. 0
  452. }
  453. Err(err) => e(Err(err)) as c_int,
  454. }
  455. }
  456. unsafe fn mmap(
  457. _addr: *mut c_void,
  458. len: usize,
  459. _prot: c_int,
  460. flags: c_int,
  461. fildes: c_int,
  462. off: off_t,
  463. ) -> *mut c_void {
  464. if flags & MAP_ANON == MAP_ANON {
  465. let fd = e(syscall::open("memory:", 0)); // flags don't matter currently
  466. if fd == !0 {
  467. return !0 as *mut c_void;
  468. }
  469. let addr = e(syscall::fmap(fd, off as usize, len as usize));
  470. if addr == !0 {
  471. let _ = syscall::close(fd);
  472. return !0 as *mut c_void;
  473. }
  474. anonymous_maps().insert(addr as usize, fd);
  475. addr as *mut c_void
  476. } else {
  477. e(syscall::fmap(fildes as usize, off as usize, len as usize)) as *mut c_void
  478. }
  479. }
  480. unsafe fn munmap(addr: *mut c_void, _len: usize) -> c_int {
  481. if e(syscall::funmap(addr as usize)) == !0 {
  482. return !0;
  483. }
  484. if let Some(fd) = anonymous_maps().remove(&(addr as usize)) {
  485. let _ = syscall::close(fd);
  486. }
  487. 0
  488. }
  489. fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
  490. let redox_rqtp = unsafe { redox_timespec::from(&*rqtp) };
  491. let mut redox_rmtp: redox_timespec;
  492. if rmtp.is_null() {
  493. redox_rmtp = redox_timespec::default();
  494. } else {
  495. redox_rmtp = unsafe { redox_timespec::from(&*rmtp) };
  496. }
  497. match e(syscall::nanosleep(&redox_rqtp, &mut redox_rmtp)) as c_int {
  498. -1 => -1,
  499. _ => {
  500. unsafe {
  501. if !rmtp.is_null() {
  502. (*rmtp).tv_sec = redox_rmtp.tv_sec;
  503. (*rmtp).tv_nsec = redox_rmtp.tv_nsec as i64;
  504. }
  505. }
  506. 0
  507. }
  508. }
  509. }
  510. fn open(path: &CStr, oflag: c_int, mode: mode_t) -> c_int {
  511. e(syscall::open(
  512. path.to_bytes(),
  513. (oflag as usize) | (mode as usize),
  514. )) as c_int
  515. }
  516. fn pipe(fds: &mut [c_int]) -> c_int {
  517. let mut usize_fds: [usize; 2] = [0; 2];
  518. let res = e(syscall::pipe2(&mut usize_fds, 0));
  519. fds[0] = usize_fds[0] as c_int;
  520. fds[1] = usize_fds[1] as c_int;
  521. res as c_int
  522. }
  523. fn read(fd: c_int, buf: &mut [u8]) -> ssize_t {
  524. e(syscall::read(fd as usize, buf)) as ssize_t
  525. }
  526. fn rename(oldpath: &CStr, newpath: &CStr) -> c_int {
  527. match syscall::open(oldpath.to_bytes(), O_WRONLY) {
  528. Ok(fd) => {
  529. let retval = syscall::frename(fd, newpath.to_bytes());
  530. let _ = syscall::close(fd);
  531. e(retval) as c_int
  532. }
  533. err => e(err) as c_int,
  534. }
  535. }
  536. fn rmdir(path: &CStr) -> c_int {
  537. e(syscall::rmdir(path.to_bytes())) as c_int
  538. }
  539. fn select(
  540. nfds: c_int,
  541. readfds: *mut fd_set,
  542. writefds: *mut fd_set,
  543. exceptfds: *mut fd_set,
  544. timeout: *mut timeval,
  545. ) -> c_int {
  546. fn isset(set: *mut fd_set, fd: usize) -> bool {
  547. if set.is_null() {
  548. return false;
  549. }
  550. let mask = 1 << (fd & (8 * mem::size_of::<c_ulong>() - 1));
  551. unsafe { (*set).fds_bits[fd / (8 * mem::size_of::<c_ulong>())] & mask == mask }
  552. }
  553. let event_path = unsafe { CStr::from_bytes_with_nul_unchecked(b"event:\0") };
  554. let event_file = match RawFile::open(event_path, 0, 0) {
  555. Ok(file) => file,
  556. Err(_) => return -1,
  557. };
  558. let mut total = 0;
  559. for fd in 0..nfds as usize {
  560. macro_rules! register {
  561. ($fd:expr, $flags:expr) => {
  562. if Self::write(
  563. *event_file,
  564. &syscall::Event {
  565. id: $fd,
  566. flags: $flags,
  567. data: 0,
  568. },
  569. ) < 0
  570. {
  571. return -1;
  572. }
  573. };
  574. }
  575. if isset(readfds, fd) {
  576. register!(fd, syscall::EVENT_READ);
  577. total += 1;
  578. }
  579. if isset(writefds, fd) {
  580. register!(fd, syscall::EVENT_WRITE);
  581. total += 1;
  582. }
  583. if isset(exceptfds, fd) {
  584. total += 1;
  585. }
  586. }
  587. const TIMEOUT_TOKEN: usize = 1;
  588. let timeout_file = if timeout.is_null() {
  589. None
  590. } else {
  591. let timeout = unsafe { &*timeout };
  592. let timeout_path = unsafe {
  593. CString::from_vec_unchecked(
  594. format!("time:{}\0", syscall::CLOCK_MONOTONIC).into_bytes(),
  595. )
  596. };
  597. let timeout_file = match RawFile::open(&timeout_path, 0, 0) {
  598. Ok(file) => file,
  599. Err(_) => return -1,
  600. };
  601. if Self::write(
  602. *event_file,
  603. &syscall::Event {
  604. id: *timeout_file as usize,
  605. flags: syscall::EVENT_READ,
  606. data: TIMEOUT_TOKEN,
  607. },
  608. ) < 0
  609. {
  610. return -1;
  611. }
  612. let mut time = syscall::TimeSpec::default();
  613. if Self::read(*timeout_file, &mut time) < 0 {
  614. return -1;
  615. }
  616. time.tv_sec += timeout.tv_sec;
  617. time.tv_nsec += timeout.tv_usec * 1000;
  618. while time.tv_nsec >= 1000000000 {
  619. time.tv_sec += 1;
  620. time.tv_nsec -= 1000000000;
  621. }
  622. if Self::write(*timeout_file, &time) < 0 {
  623. return -1;
  624. }
  625. Some(timeout_file)
  626. };
  627. let mut event = syscall::Event::default();
  628. if Self::read(*event_file, &mut event) < 0 {
  629. return -1;
  630. }
  631. if timeout_file.is_some() && event.data == TIMEOUT_TOKEN {
  632. return 0;
  633. }
  634. // I really don't get why, but select wants me to return the total number
  635. // of file descriptors that was inputted. I'm confused.
  636. total
  637. }
  638. fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
  639. e(syscall::setpgid(pid as usize, pgid as usize)) as c_int
  640. }
  641. fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
  642. e(syscall::setregid(rgid as usize, egid as usize)) as c_int
  643. }
  644. fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
  645. e(syscall::setreuid(ruid as usize, euid as usize)) as c_int
  646. }
  647. fn tcgetattr(fd: c_int, out: *mut termios) -> c_int {
  648. let dup = e(syscall::dup(fd as usize, b"termios"));
  649. if dup == !0 {
  650. return -1;
  651. }
  652. let read = e(syscall::read(dup, unsafe {
  653. slice::from_raw_parts_mut(out as *mut u8, mem::size_of::<termios>())
  654. }));
  655. let _ = syscall::close(dup);
  656. if read == !0 {
  657. return -1;
  658. }
  659. 0
  660. }
  661. fn tcsetattr(fd: c_int, _act: c_int, value: *const termios) -> c_int {
  662. let dup = e(syscall::dup(fd as usize, b"termios"));
  663. if dup == !0 {
  664. return -1;
  665. }
  666. let write = e(syscall::write(dup, unsafe {
  667. slice::from_raw_parts(value as *const u8, mem::size_of::<termios>())
  668. }));
  669. let _ = syscall::close(dup);
  670. if write == !0 {
  671. return -1;
  672. }
  673. 0
  674. }
  675. fn unlink(path: &CStr) -> c_int {
  676. e(syscall::unlink(path.to_bytes())) as c_int
  677. }
  678. fn waitpid(mut pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
  679. if pid == !0 {
  680. pid = 0;
  681. }
  682. unsafe {
  683. let mut temp: usize = 0;
  684. let res = e(syscall::waitpid(pid as usize, &mut temp, options as usize));
  685. if !stat_loc.is_null() {
  686. *stat_loc = temp as c_int;
  687. }
  688. res as pid_t
  689. }
  690. }
  691. fn write(fd: c_int, buf: &[u8]) -> ssize_t {
  692. e(syscall::write(fd as usize, buf)) as ssize_t
  693. }
  694. }