mod.rs 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156
  1. //! sys/socket implementation, following http://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/socket.h.html
  2. use cbitset::BitSet;
  3. use core::result::Result as CoreResult;
  4. use core::{mem, ptr, slice};
  5. use syscall::data::Map;
  6. use syscall::data::Stat as redox_stat;
  7. use syscall::data::StatVfs as redox_statvfs;
  8. use syscall::data::TimeSpec as redox_timespec;
  9. use syscall::{self, Result};
  10. use c_str::{CStr, CString};
  11. use fs::File;
  12. use header::dirent::dirent;
  13. use header::errno::{EINVAL, EIO, EPERM};
  14. use header::fcntl;
  15. use header::poll::{self, nfds_t, pollfd};
  16. use header::sys_mman::MAP_ANON;
  17. use header::sys_select::fd_set;
  18. use header::sys_stat::stat;
  19. use header::sys_statvfs::statvfs;
  20. use header::sys_time::{timeval, timezone};
  21. use header::sys_utsname::{utsname, UTSLENGTH};
  22. use header::time::timespec;
  23. use header::unistd::{F_OK, R_OK, W_OK, X_OK};
  24. use io::prelude::*;
  25. use io::{self, BufReader, SeekFrom};
  26. use super::types::*;
  27. use super::{errno, Pal, Read};
  28. mod extra;
  29. mod signal;
  30. mod socket;
  31. pub fn e(sys: Result<usize>) -> usize {
  32. match sys {
  33. Ok(ok) => ok,
  34. Err(err) => {
  35. unsafe {
  36. errno = err.errno as c_int;
  37. }
  38. !0
  39. }
  40. }
  41. }
  42. pub struct Sys;
  43. impl Pal for Sys {
  44. fn access(path: &CStr, mode: c_int) -> c_int {
  45. let fd = match File::open(path, fcntl::O_PATH | fcntl::O_CLOEXEC) {
  46. Ok(fd) => fd,
  47. Err(_) => return -1,
  48. };
  49. if mode == F_OK {
  50. return 0;
  51. }
  52. let mut stat = syscall::Stat::default();
  53. if e(syscall::fstat(*fd as usize, &mut stat)) == !0 {
  54. return -1;
  55. }
  56. let uid = e(syscall::getuid());
  57. if uid == !0 {
  58. return -1;
  59. }
  60. let gid = e(syscall::getgid());
  61. if gid == !0 {
  62. return -1;
  63. }
  64. let perms = if stat.st_uid as usize == uid {
  65. stat.st_mode >> (3 * 2 & 0o7)
  66. } else if stat.st_gid as usize == gid {
  67. stat.st_mode >> (3 * 1 & 0o7)
  68. } else {
  69. stat.st_mode & 0o7
  70. };
  71. if (mode & R_OK == R_OK && perms & 0o4 != 0o4)
  72. || (mode & W_OK == W_OK && perms & 0o2 != 0o2)
  73. || (mode & X_OK == X_OK && perms & 0o1 != 0o1)
  74. {
  75. unsafe {
  76. errno = EINVAL;
  77. }
  78. return -1;
  79. }
  80. 0
  81. }
  82. fn brk(addr: *mut c_void) -> *mut c_void {
  83. unsafe { syscall::brk(addr as usize).unwrap_or(0) as *mut c_void }
  84. }
  85. fn chdir(path: &CStr) -> c_int {
  86. e(syscall::chdir(path.to_bytes())) as c_int
  87. }
  88. fn chmod(path: &CStr, mode: mode_t) -> c_int {
  89. match File::open(path, fcntl::O_PATH | fcntl::O_CLOEXEC) {
  90. Ok(file) => Self::fchmod(*file, mode),
  91. Err(_) => -1,
  92. }
  93. }
  94. fn chown(path: &CStr, owner: uid_t, group: gid_t) -> c_int {
  95. match File::open(path, fcntl::O_PATH | fcntl::O_CLOEXEC) {
  96. Ok(file) => Self::fchown(*file, owner, group),
  97. Err(_) => -1,
  98. }
  99. }
  100. fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int {
  101. let mut redox_tp = unsafe { redox_timespec::from(&*tp) };
  102. match e(syscall::clock_gettime(clk_id as usize, &mut redox_tp)) as c_int {
  103. -1 => -1,
  104. _ => {
  105. unsafe {
  106. (*tp).tv_sec = redox_tp.tv_sec;
  107. (*tp).tv_nsec = redox_tp.tv_nsec as i64;
  108. };
  109. 0
  110. }
  111. }
  112. }
  113. fn close(fd: c_int) -> c_int {
  114. e(syscall::close(fd as usize)) as c_int
  115. }
  116. fn dup(fd: c_int) -> c_int {
  117. e(syscall::dup(fd as usize, &[])) as c_int
  118. }
  119. fn dup2(fd1: c_int, fd2: c_int) -> c_int {
  120. e(syscall::dup2(fd1 as usize, fd2 as usize, &[])) as c_int
  121. }
  122. fn exit(status: c_int) -> ! {
  123. let _ = syscall::exit(status as usize);
  124. loop {}
  125. }
  126. unsafe fn execve(
  127. path: &CStr,
  128. mut argv: *const *mut c_char,
  129. mut envp: *const *mut c_char,
  130. ) -> c_int {
  131. use alloc::vec::Vec;
  132. let mut file = match File::open(path, fcntl::O_RDONLY | fcntl::O_CLOEXEC) {
  133. Ok(file) => file,
  134. Err(_) => return -1,
  135. };
  136. let fd = *file as usize;
  137. // Count arguments
  138. let mut len = 0;
  139. while !(*argv.offset(len)).is_null() {
  140. len += 1;
  141. }
  142. let mut args: Vec<[usize; 2]> = Vec::with_capacity(len as usize);
  143. // Read shebang (for example #!/bin/sh)
  144. let interpreter = {
  145. let mut reader = BufReader::new(&mut file);
  146. let mut shebang = [0; 2];
  147. let mut read = 0;
  148. while read < 2 {
  149. match reader.read(&mut shebang) {
  150. Ok(0) => break,
  151. Ok(i) => read += i,
  152. Err(_) => return -1,
  153. }
  154. }
  155. if &shebang == b"#!" {
  156. // So, this file is interpreted.
  157. // That means the actual file descriptor passed to `fexec` won't be this file.
  158. // So we need to check ourselves that this file is actually be executable.
  159. let mut stat = redox_stat::default();
  160. if e(syscall::fstat(fd, &mut stat)) == !0 {
  161. return -1;
  162. }
  163. let uid = e(syscall::getuid());
  164. if uid == !0 {
  165. return -1;
  166. }
  167. let gid = e(syscall::getuid());
  168. if gid == !0 {
  169. return -1;
  170. }
  171. let mode = if uid == stat.st_uid as usize {
  172. (stat.st_mode >> 3 * 2) & 0o7
  173. } else if gid == stat.st_gid as usize {
  174. (stat.st_mode >> 3 * 1) & 0o7
  175. } else {
  176. stat.st_mode & 0o7
  177. };
  178. if mode & 0o1 == 0o0 {
  179. errno = EPERM;
  180. return -1;
  181. }
  182. // Then, read the actual interpreter:
  183. let mut interpreter = Vec::new();
  184. match reader.read_until(b'\n', &mut interpreter) {
  185. Err(_) => return -1,
  186. Ok(_) => {
  187. if interpreter.ends_with(&[b'\n']) {
  188. interpreter.pop().unwrap();
  189. }
  190. // TODO: Returning the interpreter here is actually a
  191. // hack. Preferrably we should reassign `file =`
  192. // directly from here. Just wait until NLL comes
  193. // around...
  194. Some(interpreter)
  195. }
  196. }
  197. } else {
  198. None
  199. }
  200. };
  201. let mut _interpreter_path = None;
  202. if let Some(interpreter) = interpreter {
  203. let mut cstring = match CString::new(interpreter) {
  204. Ok(cstring) => cstring,
  205. Err(_) => return -1,
  206. };
  207. file = match File::open(&cstring, fcntl::O_RDONLY | fcntl::O_CLOEXEC) {
  208. Ok(file) => file,
  209. Err(_) => return -1,
  210. };
  211. // Make sure path is kept alive long enough, and push it to the arguments
  212. _interpreter_path = Some(cstring);
  213. let path_ref = _interpreter_path.as_ref().unwrap();
  214. args.push([path_ref.as_ptr() as usize, path_ref.to_bytes().len()]);
  215. } else {
  216. if file.seek(SeekFrom::Start(0)).is_err() {
  217. return -1;
  218. }
  219. }
  220. // Arguments
  221. while !(*argv).is_null() {
  222. let arg = *argv;
  223. let mut len = 0;
  224. while *arg.offset(len) != 0 {
  225. len += 1;
  226. }
  227. args.push([arg as usize, len as usize]);
  228. argv = argv.offset(1);
  229. }
  230. // Environment variables
  231. let mut len = 0;
  232. while !(*envp.offset(len)).is_null() {
  233. len += 1;
  234. }
  235. let mut envs: Vec<[usize; 2]> = Vec::with_capacity(len as usize);
  236. while !(*envp).is_null() {
  237. let env = *envp;
  238. let mut len = 0;
  239. while *env.offset(len) != 0 {
  240. len += 1;
  241. }
  242. envs.push([env as usize, len as usize]);
  243. envp = envp.offset(1);
  244. }
  245. e(syscall::fexec(*file as usize, &args, &envs)) as c_int
  246. }
  247. fn fchdir(fd: c_int) -> c_int {
  248. let path: &mut [u8] = &mut [0; 4096];
  249. if e(syscall::fpath(fd as usize, path)) == !0 {
  250. !0
  251. } else {
  252. e(syscall::chdir(path)) as c_int
  253. }
  254. }
  255. fn fchmod(fd: c_int, mode: mode_t) -> c_int {
  256. e(syscall::fchmod(fd as usize, mode as u16)) as c_int
  257. }
  258. fn fchown(fd: c_int, owner: uid_t, group: gid_t) -> c_int {
  259. e(syscall::fchown(fd as usize, owner as u32, group as u32)) as c_int
  260. }
  261. fn fcntl(fd: c_int, cmd: c_int, args: c_int) -> c_int {
  262. e(syscall::fcntl(fd as usize, cmd as usize, args as usize)) as c_int
  263. }
  264. fn flock(_fd: c_int, _operation: c_int) -> c_int {
  265. // TODO: Redox does not have file locking yet
  266. 0
  267. }
  268. fn fork() -> pid_t {
  269. e(unsafe { syscall::clone(0) }) as pid_t
  270. }
  271. fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
  272. let mut redox_buf: redox_stat = redox_stat::default();
  273. match e(syscall::fstat(fildes as usize, &mut redox_buf)) {
  274. 0 => {
  275. unsafe {
  276. if !buf.is_null() {
  277. (*buf).st_dev = redox_buf.st_dev as dev_t;
  278. (*buf).st_ino = redox_buf.st_ino as ino_t;
  279. (*buf).st_nlink = redox_buf.st_nlink as nlink_t;
  280. (*buf).st_mode = redox_buf.st_mode as mode_t;
  281. (*buf).st_uid = redox_buf.st_uid as uid_t;
  282. (*buf).st_gid = redox_buf.st_gid as gid_t;
  283. // TODO st_rdev
  284. (*buf).st_rdev = 0;
  285. (*buf).st_size = redox_buf.st_size as off_t;
  286. (*buf).st_blksize = redox_buf.st_blksize as blksize_t;
  287. (*buf).st_atim = timespec {
  288. tv_sec: redox_buf.st_atime as time_t,
  289. tv_nsec: redox_buf.st_atime_nsec as c_long,
  290. };
  291. (*buf).st_mtim = timespec {
  292. tv_sec: redox_buf.st_mtime as time_t,
  293. tv_nsec: redox_buf.st_mtime_nsec as c_long,
  294. };
  295. (*buf).st_ctim = timespec {
  296. tv_sec: redox_buf.st_ctime as time_t,
  297. tv_nsec: redox_buf.st_ctime_nsec as c_long,
  298. };
  299. }
  300. }
  301. 0
  302. }
  303. _ => -1,
  304. }
  305. }
  306. fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int {
  307. let mut kbuf: redox_statvfs = redox_statvfs::default();
  308. match e(syscall::fstatvfs(fildes as usize, &mut kbuf)) {
  309. 0 => {
  310. unsafe {
  311. if !buf.is_null() {
  312. (*buf).f_bsize = kbuf.f_bsize as c_ulong;
  313. (*buf).f_frsize = kbuf.f_bsize as c_ulong;
  314. (*buf).f_blocks = kbuf.f_blocks;
  315. (*buf).f_bfree = kbuf.f_bfree;
  316. (*buf).f_bavail = kbuf.f_bavail;
  317. //TODO
  318. (*buf).f_files = 0;
  319. (*buf).f_ffree = 0;
  320. (*buf).f_favail = 0;
  321. (*buf).f_fsid = 0;
  322. (*buf).f_flag = 0;
  323. (*buf).f_namemax = 0;
  324. }
  325. }
  326. 0
  327. }
  328. _ => -1,
  329. }
  330. }
  331. fn fsync(fd: c_int) -> c_int {
  332. e(syscall::fsync(fd as usize)) as c_int
  333. }
  334. fn ftruncate(fd: c_int, len: off_t) -> c_int {
  335. e(syscall::ftruncate(fd as usize, len as usize)) as c_int
  336. }
  337. fn futex(addr: *mut c_int, op: c_int, val: c_int) -> c_int {
  338. match unsafe {
  339. syscall::futex(
  340. addr as *mut i32,
  341. op as usize,
  342. val as i32,
  343. 0,
  344. ptr::null_mut(),
  345. )
  346. } {
  347. Ok(success) => success as c_int,
  348. Err(err) => -(err.errno as c_int),
  349. }
  350. }
  351. fn futimens(fd: c_int, times: *const timespec) -> c_int {
  352. let times = [unsafe { redox_timespec::from(&*times) }, unsafe {
  353. redox_timespec::from(&*times.offset(1))
  354. }];
  355. e(syscall::futimens(fd as usize, &times)) as c_int
  356. }
  357. fn utimens(path: &CStr, times: *const timespec) -> c_int {
  358. match File::open(path, fcntl::O_PATH | fcntl::O_CLOEXEC) {
  359. Ok(file) => Self::futimens(*file, times),
  360. Err(_) => -1,
  361. }
  362. }
  363. fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char {
  364. let buf_slice = unsafe { slice::from_raw_parts_mut(buf as *mut u8, size as usize - 1) };
  365. let read = e(syscall::getcwd(buf_slice));
  366. if read == !0 {
  367. ptr::null_mut()
  368. } else {
  369. unsafe {
  370. *buf.offset(read as isize + 1) = 0;
  371. }
  372. buf
  373. }
  374. }
  375. fn getdents(fd: c_int, mut dirents: *mut dirent, max_bytes: usize) -> c_int {
  376. //TODO: rewrite this code. Originally the *dirents = dirent { ... } stuff below caused
  377. // massive issues. This has been hacked around, but it still isn't perfect
  378. // Get initial reading position
  379. let mut read = match syscall::lseek(fd as usize, 0, syscall::SEEK_CUR) {
  380. Ok(pos) => pos as isize,
  381. Err(err) => return -err.errno,
  382. };
  383. let mut written = 0;
  384. let mut buf = [0; 1024];
  385. let mut name = [0; 256];
  386. let mut i = 0;
  387. let mut flush = |written: &mut usize, i: &mut usize, name: &mut [c_char; 256]| {
  388. if *i < name.len() {
  389. // Set NUL byte
  390. name[*i] = 0;
  391. }
  392. // Get size: full size - unused bytes
  393. if *written + mem::size_of::<dirent>() > max_bytes {
  394. // Seek back to after last read entry and return
  395. match syscall::lseek(fd as usize, read, syscall::SEEK_SET) {
  396. Ok(_) => return Some(*written as c_int),
  397. Err(err) => return Some(-err.errno),
  398. }
  399. }
  400. let size = mem::size_of::<dirent>() - name.len().saturating_sub(*i + 1);
  401. unsafe {
  402. //This is the offending code mentioned above
  403. *dirents = dirent {
  404. d_ino: 0,
  405. d_off: read as off_t,
  406. d_reclen: size as c_ushort,
  407. d_type: 0,
  408. d_name: *name,
  409. };
  410. dirents = (dirents as *mut u8).offset(size as isize) as *mut dirent;
  411. }
  412. read += *i as isize + /* newline */ 1;
  413. *written += size;
  414. *i = 0;
  415. None
  416. };
  417. loop {
  418. // Read a chunk from the directory
  419. let len = match syscall::read(fd as usize, &mut buf) {
  420. Ok(0) => {
  421. if i > 0 {
  422. if let Some(value) = flush(&mut written, &mut i, &mut name) {
  423. return value;
  424. }
  425. }
  426. return written as c_int;
  427. }
  428. Ok(n) => n,
  429. Err(err) => return -err.errno,
  430. };
  431. // Handle everything
  432. let mut start = 0;
  433. while start < len {
  434. let buf = &buf[start..len];
  435. // Copy everything up until a newline
  436. let newline = buf.iter().position(|&c| c == b'\n');
  437. let pre_len = newline.unwrap_or(buf.len());
  438. let post_len = newline.map(|i| i + 1).unwrap_or(buf.len());
  439. if i < pre_len {
  440. // Reserve space for NUL byte
  441. let name_len = name.len() - 1;
  442. let name = &mut name[i..name_len];
  443. let copy = pre_len.min(name.len());
  444. let buf = unsafe { slice::from_raw_parts(buf.as_ptr() as *const c_char, copy) };
  445. name[..copy].copy_from_slice(buf);
  446. }
  447. i += pre_len;
  448. start += post_len;
  449. // Write the directory entry
  450. if newline.is_some() {
  451. if let Some(value) = flush(&mut written, &mut i, &mut name) {
  452. return value;
  453. }
  454. }
  455. }
  456. }
  457. }
  458. fn getegid() -> gid_t {
  459. e(syscall::getegid()) as gid_t
  460. }
  461. fn geteuid() -> uid_t {
  462. e(syscall::geteuid()) as uid_t
  463. }
  464. fn getgid() -> gid_t {
  465. e(syscall::getgid()) as gid_t
  466. }
  467. fn getpgid(pid: pid_t) -> pid_t {
  468. e(syscall::getpgid(pid as usize)) as pid_t
  469. }
  470. fn getpid() -> pid_t {
  471. e(syscall::getpid()) as pid_t
  472. }
  473. fn getppid() -> pid_t {
  474. e(syscall::getppid()) as pid_t
  475. }
  476. fn gettid() -> pid_t {
  477. //TODO
  478. Self::getpid()
  479. }
  480. fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int {
  481. let mut redox_tp = redox_timespec::default();
  482. let err = e(syscall::clock_gettime(
  483. syscall::CLOCK_REALTIME,
  484. &mut redox_tp,
  485. )) as c_int;
  486. if err < 0 {
  487. return err;
  488. }
  489. unsafe {
  490. (*tp).tv_sec = redox_tp.tv_sec as time_t;
  491. (*tp).tv_usec = (redox_tp.tv_nsec / 1000) as suseconds_t;
  492. if !tzp.is_null() {
  493. (*tzp).tz_minuteswest = 0;
  494. (*tzp).tz_dsttime = 0;
  495. }
  496. }
  497. 0
  498. }
  499. fn getuid() -> uid_t {
  500. e(syscall::getuid()) as pid_t
  501. }
  502. fn link(path1: &CStr, path2: &CStr) -> c_int {
  503. e(unsafe { syscall::link(path1.as_ptr() as *const u8, path2.as_ptr() as *const u8) })
  504. as c_int
  505. }
  506. fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t {
  507. e(syscall::lseek(
  508. fd as usize,
  509. offset as isize,
  510. whence as usize,
  511. )) as off_t
  512. }
  513. fn mkdir(path: &CStr, mode: mode_t) -> c_int {
  514. match File::create(
  515. path,
  516. fcntl::O_DIRECTORY | fcntl::O_EXCL | fcntl::O_CLOEXEC,
  517. 0o777,
  518. ) {
  519. Ok(_fd) => 0,
  520. Err(_) => -1,
  521. }
  522. }
  523. fn mkfifo(path: &CStr, mode: mode_t) -> c_int {
  524. match File::create(
  525. path,
  526. fcntl::O_CREAT | fcntl::O_CLOEXEC,
  527. syscall::MODE_FIFO as mode_t | (mode & 0o777),
  528. ) {
  529. Ok(fd) => 0,
  530. Err(_) => -1,
  531. }
  532. }
  533. unsafe fn mmap(
  534. _addr: *mut c_void,
  535. len: usize,
  536. prot: c_int,
  537. flags: c_int,
  538. fildes: c_int,
  539. off: off_t,
  540. ) -> *mut c_void {
  541. let map = Map {
  542. offset: off as usize,
  543. size: len,
  544. flags: ((prot as usize) << 16) | ((flags as usize) & 0xFFFF),
  545. };
  546. if flags & MAP_ANON == MAP_ANON {
  547. let fd = e(syscall::open(
  548. "memory:",
  549. syscall::O_STAT | syscall::O_CLOEXEC,
  550. )); // flags don't matter currently
  551. if fd == !0 {
  552. return !0 as *mut c_void;
  553. }
  554. let addr = e(syscall::fmap(fd, &map)) as *mut c_void;
  555. let _ = syscall::close(fd);
  556. addr
  557. } else {
  558. e(syscall::fmap(fildes as usize, &map)) as *mut c_void
  559. }
  560. }
  561. unsafe fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> c_int {
  562. e(syscall::mprotect(addr as usize, len, (prot as usize) << 16)) as c_int
  563. }
  564. unsafe fn munmap(addr: *mut c_void, _len: usize) -> c_int {
  565. if e(syscall::funmap(addr as usize)) == !0 {
  566. return !0;
  567. }
  568. 0
  569. }
  570. fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
  571. let redox_rqtp = unsafe { redox_timespec::from(&*rqtp) };
  572. let mut redox_rmtp: redox_timespec;
  573. if rmtp.is_null() {
  574. redox_rmtp = redox_timespec::default();
  575. } else {
  576. redox_rmtp = unsafe { redox_timespec::from(&*rmtp) };
  577. }
  578. match e(syscall::nanosleep(&redox_rqtp, &mut redox_rmtp)) as c_int {
  579. -1 => -1,
  580. _ => {
  581. unsafe {
  582. if !rmtp.is_null() {
  583. (*rmtp).tv_sec = redox_rmtp.tv_sec;
  584. (*rmtp).tv_nsec = redox_rmtp.tv_nsec as i64;
  585. }
  586. }
  587. 0
  588. }
  589. }
  590. }
  591. fn open(path: &CStr, oflag: c_int, mode: mode_t) -> c_int {
  592. e(syscall::open(
  593. path.to_bytes(),
  594. ((oflag as usize) & 0xFFFF_0000) | ((mode as usize) & 0xFFFF),
  595. )) as c_int
  596. }
  597. fn pipe(fds: &mut [c_int]) -> c_int {
  598. let mut usize_fds: [usize; 2] = [0; 2];
  599. let res = e(syscall::pipe2(&mut usize_fds, 0));
  600. fds[0] = usize_fds[0] as c_int;
  601. fds[1] = usize_fds[1] as c_int;
  602. res as c_int
  603. }
  604. fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int {
  605. let fds = unsafe { slice::from_raw_parts_mut(fds, nfds as usize) };
  606. let event_path = c_str!("event:");
  607. let mut event_file = match File::open(event_path, fcntl::O_RDWR | fcntl::O_CLOEXEC) {
  608. Ok(file) => file,
  609. Err(_) => return -1,
  610. };
  611. for fd in fds.iter_mut() {
  612. let mut flags = 0;
  613. if fd.events & poll::POLLIN > 0 {
  614. flags |= syscall::EVENT_READ;
  615. }
  616. if fd.events & poll::POLLOUT > 0 {
  617. flags |= syscall::EVENT_WRITE;
  618. }
  619. fd.revents = 0;
  620. if fd.fd >= 0 && flags > 0 {
  621. if event_file
  622. .write(&syscall::Event {
  623. id: fd.fd as usize,
  624. flags: flags,
  625. data: 0,
  626. })
  627. .is_err()
  628. {
  629. return -1;
  630. }
  631. }
  632. }
  633. const TIMEOUT_TOKEN: usize = 1;
  634. let timeout_file = if timeout < 0 {
  635. None
  636. } else {
  637. let timeout_path = unsafe {
  638. CString::from_vec_unchecked(
  639. format!("time:{}", syscall::CLOCK_MONOTONIC).into_bytes(),
  640. )
  641. };
  642. let mut timeout_file = match File::open(&timeout_path, fcntl::O_RDWR | fcntl::O_CLOEXEC)
  643. {
  644. Ok(file) => file,
  645. Err(_) => return -1,
  646. };
  647. if event_file
  648. .write(&syscall::Event {
  649. id: *timeout_file as usize,
  650. flags: syscall::EVENT_READ,
  651. data: TIMEOUT_TOKEN,
  652. })
  653. .is_err()
  654. {
  655. return -1;
  656. }
  657. let mut time = syscall::TimeSpec::default();
  658. if timeout_file.read(&mut time).is_err() {
  659. return -1;
  660. }
  661. time.tv_nsec += timeout * 1000000;
  662. while time.tv_nsec >= 1000000000 {
  663. time.tv_sec += 1;
  664. time.tv_nsec -= 1000000000;
  665. }
  666. if timeout_file.write(&time).is_err() {
  667. return -1;
  668. }
  669. Some(timeout_file)
  670. };
  671. let mut events = [syscall::Event::default(); 32];
  672. let read = {
  673. let mut events = unsafe {
  674. slice::from_raw_parts_mut(
  675. &mut events as *mut _ as *mut u8,
  676. mem::size_of::<syscall::Event>() * events.len(),
  677. )
  678. };
  679. match event_file.read(&mut events) {
  680. Ok(i) => i / mem::size_of::<syscall::Event>(),
  681. Err(_) => return -1,
  682. }
  683. };
  684. for event in &events[..read] {
  685. if event.data == TIMEOUT_TOKEN {
  686. continue;
  687. }
  688. for fd in fds.iter_mut() {
  689. if event.id == fd.fd as usize {
  690. if event.flags & syscall::EVENT_READ > 0 {
  691. fd.revents |= poll::POLLIN;
  692. }
  693. if event.flags & syscall::EVENT_WRITE > 0 {
  694. fd.revents |= poll::POLLOUT;
  695. }
  696. }
  697. }
  698. }
  699. let mut total = 0;
  700. for fd in fds.iter_mut() {
  701. if fd.revents > 0 {
  702. total += 1;
  703. }
  704. }
  705. total
  706. }
  707. fn pte_clone() -> pid_t {
  708. e(unsafe {
  709. syscall::clone(
  710. syscall::CLONE_VM
  711. | syscall::CLONE_FS
  712. | syscall::CLONE_FILES
  713. | syscall::CLONE_SIGHAND,
  714. )
  715. }) as pid_t
  716. }
  717. fn read(fd: c_int, buf: &mut [u8]) -> ssize_t {
  718. e(syscall::read(fd as usize, buf)) as ssize_t
  719. }
  720. fn fpath(fildes: c_int, out: &mut [u8]) -> ssize_t {
  721. e(syscall::fpath(fildes as usize, out)) as ssize_t
  722. }
  723. fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t {
  724. let file = match File::open(
  725. pathname,
  726. fcntl::O_PATH | fcntl::O_SYMLINK | fcntl::O_CLOEXEC,
  727. ) {
  728. Ok(ok) => ok,
  729. Err(_) => return -1,
  730. };
  731. if out.is_empty() {
  732. return 0;
  733. }
  734. let len = out.len();
  735. let read = e(syscall::fpath(*file as usize, &mut out[..len - 1]));
  736. if (read as c_int) < 0 {
  737. return -1;
  738. }
  739. out[read as usize] = 0;
  740. 0
  741. }
  742. fn rename(oldpath: &CStr, newpath: &CStr) -> c_int {
  743. match File::open(oldpath, fcntl::O_WRONLY | fcntl::O_CLOEXEC) {
  744. Ok(file) => e(syscall::frename(*file as usize, newpath.to_bytes())) as c_int,
  745. Err(_) => -1,
  746. }
  747. }
  748. fn rmdir(path: &CStr) -> c_int {
  749. e(syscall::rmdir(path.to_bytes())) as c_int
  750. }
  751. fn sched_yield() -> c_int {
  752. e(syscall::sched_yield()) as c_int
  753. }
  754. fn select(
  755. nfds: c_int,
  756. readfds: *mut fd_set,
  757. writefds: *mut fd_set,
  758. exceptfds: *mut fd_set,
  759. timeout: *mut timeval,
  760. ) -> c_int {
  761. let mut readfds = unsafe { readfds.as_mut() }.map(|s| BitSet::from_ref(&mut s.fds_bits));
  762. let mut writefds = unsafe { writefds.as_mut() }.map(|s| BitSet::from_ref(&mut s.fds_bits));
  763. let mut exceptfds =
  764. unsafe { exceptfds.as_mut() }.map(|s| BitSet::from_ref(&mut s.fds_bits));
  765. let event_path = c_str!("event:");
  766. let mut event_file = match File::open(event_path, fcntl::O_RDWR | fcntl::O_CLOEXEC) {
  767. Ok(file) => file,
  768. Err(_) => return -1,
  769. };
  770. for fd in 0..nfds as usize {
  771. macro_rules! register {
  772. ($fd:expr, $flags:expr) => {
  773. if event_file
  774. .write(&syscall::Event {
  775. id: $fd,
  776. flags: $flags,
  777. data: 0,
  778. })
  779. .is_err()
  780. {
  781. return -1;
  782. }
  783. };
  784. }
  785. if readfds.as_mut().map(|s| s.contains(fd)).unwrap_or(false) {
  786. register!(fd, syscall::EVENT_READ);
  787. }
  788. if writefds.as_mut().map(|s| s.contains(fd)).unwrap_or(false) {
  789. register!(fd, syscall::EVENT_WRITE);
  790. }
  791. }
  792. const TIMEOUT_TOKEN: usize = 1;
  793. let timeout_file = if timeout.is_null() {
  794. None
  795. } else {
  796. let timeout = unsafe { &*timeout };
  797. let timeout_path = unsafe {
  798. CString::from_vec_unchecked(
  799. format!("time:{}", syscall::CLOCK_MONOTONIC).into_bytes(),
  800. )
  801. };
  802. let mut timeout_file = match File::open(&timeout_path, fcntl::O_RDWR | fcntl::O_CLOEXEC)
  803. {
  804. Ok(file) => file,
  805. Err(_) => return -1,
  806. };
  807. if event_file
  808. .write(&syscall::Event {
  809. id: *timeout_file as usize,
  810. flags: syscall::EVENT_READ,
  811. data: TIMEOUT_TOKEN,
  812. })
  813. .is_err()
  814. {
  815. return -1;
  816. }
  817. let mut time = syscall::TimeSpec::default();
  818. if timeout_file.read(&mut time).is_err() {
  819. return -1;
  820. }
  821. time.tv_sec += timeout.tv_sec;
  822. time.tv_nsec += timeout.tv_usec * 1000;
  823. while time.tv_nsec >= 1000000000 {
  824. time.tv_sec += 1;
  825. time.tv_nsec -= 1000000000;
  826. }
  827. if timeout_file.write(&time).is_err() {
  828. return -1;
  829. }
  830. Some(timeout_file)
  831. };
  832. let mut events = [syscall::Event::default(); 32];
  833. let read = {
  834. let mut events = unsafe {
  835. slice::from_raw_parts_mut(
  836. &mut events as *mut _ as *mut u8,
  837. mem::size_of::<syscall::Event>() * events.len(),
  838. )
  839. };
  840. match event_file.read(&mut events) {
  841. Ok(i) => i / mem::size_of::<syscall::Event>(),
  842. Err(_) => return -1,
  843. }
  844. };
  845. let mut total = 0;
  846. if let Some(ref mut set) = readfds {
  847. set.clear();
  848. }
  849. if let Some(ref mut set) = writefds {
  850. set.clear();
  851. }
  852. if let Some(ref mut set) = exceptfds {
  853. set.clear();
  854. }
  855. for event in &events[..read] {
  856. if event.data == TIMEOUT_TOKEN {
  857. continue;
  858. }
  859. if event.flags & syscall::EVENT_READ == syscall::EVENT_READ {
  860. if let Some(ref mut set) = readfds {
  861. set.insert(event.id);
  862. }
  863. total += 1;
  864. }
  865. if event.flags & syscall::EVENT_WRITE == syscall::EVENT_WRITE {
  866. if let Some(ref mut set) = writefds {
  867. set.insert(event.id);
  868. }
  869. total += 1;
  870. }
  871. }
  872. total
  873. }
  874. fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
  875. e(syscall::setpgid(pid as usize, pgid as usize)) as c_int
  876. }
  877. fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
  878. e(syscall::setregid(rgid as usize, egid as usize)) as c_int
  879. }
  880. fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
  881. e(syscall::setreuid(ruid as usize, euid as usize)) as c_int
  882. }
  883. fn symlink(path1: &CStr, path2: &CStr) -> c_int {
  884. let mut file = match File::create(
  885. path2,
  886. fcntl::O_WRONLY | fcntl::O_SYMLINK | fcntl::O_CLOEXEC,
  887. 0o777,
  888. ) {
  889. Ok(ok) => ok,
  890. Err(_) => return -1,
  891. };
  892. if file.write(path1.to_bytes()).is_err() {
  893. return -1;
  894. }
  895. 0
  896. }
  897. fn umask(mask: mode_t) -> mode_t {
  898. e(syscall::umask(mask as usize)) as mode_t
  899. }
  900. fn uname(utsname: *mut utsname) -> c_int {
  901. fn gethostname(name: &mut [u8]) -> io::Result<()> {
  902. if name.is_empty() {
  903. return Ok(());
  904. }
  905. let mut file = File::open(
  906. &CString::new("/etc/hostname").unwrap(),
  907. fcntl::O_RDONLY | fcntl::O_CLOEXEC,
  908. )?;
  909. let mut read = 0;
  910. let name_len = name.len();
  911. loop {
  912. match file.read(&mut name[read..name_len - 1])? {
  913. 0 => break,
  914. n => read += n,
  915. }
  916. }
  917. name[read] = 0;
  918. Ok(())
  919. }
  920. fn inner(utsname: *mut utsname) -> CoreResult<(), i32> {
  921. match gethostname(unsafe {
  922. slice::from_raw_parts_mut(
  923. (*utsname).nodename.as_mut_ptr() as *mut u8,
  924. (*utsname).nodename.len(),
  925. )
  926. }) {
  927. Ok(_) => (),
  928. Err(_) => return Err(EIO),
  929. }
  930. let file_path = c_str!("sys:uname");
  931. let mut file = match File::open(file_path, fcntl::O_RDONLY | fcntl::O_CLOEXEC) {
  932. Ok(ok) => ok,
  933. Err(_) => return Err(EIO),
  934. };
  935. let mut lines = BufReader::new(&mut file).lines();
  936. let mut read_line = |dst: &mut [c_char]| {
  937. let line = match lines.next() {
  938. Some(Ok(l)) => match CString::new(l) {
  939. Ok(l) => l,
  940. Err(_) => return Err(EIO),
  941. },
  942. None | Some(Err(_)) => return Err(EIO),
  943. };
  944. let line_slice: &[c_char] = unsafe { mem::transmute(line.as_bytes_with_nul()) };
  945. if line_slice.len() <= UTSLENGTH {
  946. dst[..line_slice.len()].copy_from_slice(line_slice);
  947. Ok(())
  948. } else {
  949. Err(EIO)
  950. }
  951. };
  952. unsafe {
  953. read_line(&mut (*utsname).sysname)?;
  954. read_line(&mut (*utsname).release)?;
  955. read_line(&mut (*utsname).machine)?;
  956. // Version is not provided
  957. ptr::write_bytes((*utsname).version.as_mut_ptr(), 0, UTSLENGTH);
  958. // Redox doesn't provide domainname in sys:uname
  959. //read_line(&mut (*utsname).domainname)?;
  960. ptr::write_bytes((*utsname).domainname.as_mut_ptr(), 0, UTSLENGTH);
  961. }
  962. Ok(())
  963. }
  964. match inner(utsname) {
  965. Ok(()) => 0,
  966. Err(err) => unsafe {
  967. errno = err;
  968. -1
  969. },
  970. }
  971. }
  972. fn unlink(path: &CStr) -> c_int {
  973. e(syscall::unlink(path.to_bytes())) as c_int
  974. }
  975. fn waitpid(mut pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
  976. if pid == !0 {
  977. pid = 0;
  978. }
  979. unsafe {
  980. let mut temp: usize = 0;
  981. let res = e(syscall::waitpid(pid as usize, &mut temp, options as usize));
  982. if !stat_loc.is_null() {
  983. *stat_loc = temp as c_int;
  984. }
  985. res as pid_t
  986. }
  987. }
  988. fn write(fd: c_int, buf: &[u8]) -> ssize_t {
  989. e(syscall::write(fd as usize, buf)) as ssize_t
  990. }
  991. fn verify() -> bool {
  992. // GETPID on Redox is 20, which is WRITEV on Linux
  993. e(unsafe { syscall::syscall5(syscall::number::SYS_GETPID, !0, !0, !0, !0, !0) }) != !0
  994. }
  995. }