mod.rs 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046
  1. use core::{mem, ptr, result::Result as CoreResult, slice};
  2. use syscall::{
  3. self,
  4. data::{Map, Stat as redox_stat, StatVfs as redox_statvfs, TimeSpec as redox_timespec},
  5. PtraceEvent, Result,
  6. };
  7. use crate::{
  8. c_str::{CStr, CString},
  9. fs::File,
  10. header::{
  11. dirent::dirent,
  12. errno::{EINVAL, EIO, EPERM, ERANGE},
  13. fcntl,
  14. sys_mman::MAP_ANON,
  15. sys_random,
  16. sys_resource::{rlimit, RLIM_INFINITY},
  17. sys_stat::stat,
  18. sys_statvfs::statvfs,
  19. sys_time::{timeval, timezone},
  20. sys_utsname::{utsname, UTSLENGTH},
  21. sys_wait,
  22. time::timespec,
  23. unistd::{F_OK, R_OK, W_OK, X_OK},
  24. },
  25. io::{self, prelude::*, BufReader, SeekFrom},
  26. };
  27. use super::{errno, types::*, Pal, Read};
  28. mod epoll;
  29. mod extra;
  30. mod ptrace;
  31. mod signal;
  32. mod socket;
  33. pub fn e(sys: Result<usize>) -> usize {
  34. match sys {
  35. Ok(ok) => ok,
  36. Err(err) => {
  37. unsafe {
  38. errno = err.errno as c_int;
  39. }
  40. !0
  41. }
  42. }
  43. }
  44. pub struct Sys;
  45. impl Pal for Sys {
  46. fn access(path: &CStr, mode: c_int) -> c_int {
  47. let fd = match File::open(path, fcntl::O_PATH | fcntl::O_CLOEXEC) {
  48. Ok(fd) => fd,
  49. Err(_) => return -1,
  50. };
  51. if mode == F_OK {
  52. return 0;
  53. }
  54. let mut stat = syscall::Stat::default();
  55. if e(syscall::fstat(*fd as usize, &mut stat)) == !0 {
  56. return -1;
  57. }
  58. let uid = e(syscall::getuid());
  59. if uid == !0 {
  60. return -1;
  61. }
  62. let gid = e(syscall::getgid());
  63. if gid == !0 {
  64. return -1;
  65. }
  66. let perms = if stat.st_uid as usize == uid {
  67. stat.st_mode >> (3 * 2 & 0o7)
  68. } else if stat.st_gid as usize == gid {
  69. stat.st_mode >> (3 * 1 & 0o7)
  70. } else {
  71. stat.st_mode & 0o7
  72. };
  73. if (mode & R_OK == R_OK && perms & 0o4 != 0o4)
  74. || (mode & W_OK == W_OK && perms & 0o2 != 0o2)
  75. || (mode & X_OK == X_OK && perms & 0o1 != 0o1)
  76. {
  77. unsafe {
  78. errno = EINVAL;
  79. }
  80. return -1;
  81. }
  82. 0
  83. }
  84. fn brk(addr: *mut c_void) -> *mut c_void {
  85. unsafe { syscall::brk(addr as usize).unwrap_or(0) as *mut c_void }
  86. }
  87. fn chdir(path: &CStr) -> c_int {
  88. e(syscall::chdir(path.to_bytes())) as c_int
  89. }
  90. fn chmod(path: &CStr, mode: mode_t) -> c_int {
  91. match File::open(path, fcntl::O_PATH | fcntl::O_CLOEXEC) {
  92. Ok(file) => Self::fchmod(*file, mode),
  93. Err(_) => -1,
  94. }
  95. }
  96. fn chown(path: &CStr, owner: uid_t, group: gid_t) -> c_int {
  97. match File::open(path, fcntl::O_PATH | fcntl::O_CLOEXEC) {
  98. Ok(file) => Self::fchown(*file, owner, group),
  99. Err(_) => -1,
  100. }
  101. }
  102. fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int {
  103. let mut redox_tp = unsafe { redox_timespec::from(&*tp) };
  104. match e(syscall::clock_gettime(clk_id as usize, &mut redox_tp)) as c_int {
  105. -1 => -1,
  106. _ => {
  107. unsafe {
  108. (*tp).tv_sec = redox_tp.tv_sec;
  109. (*tp).tv_nsec = redox_tp.tv_nsec as i64;
  110. };
  111. 0
  112. }
  113. }
  114. }
  115. fn close(fd: c_int) -> c_int {
  116. e(syscall::close(fd as usize)) as c_int
  117. }
  118. fn dup(fd: c_int) -> c_int {
  119. e(syscall::dup(fd as usize, &[])) as c_int
  120. }
  121. fn dup2(fd1: c_int, fd2: c_int) -> c_int {
  122. e(syscall::dup2(fd1 as usize, fd2 as usize, &[])) as c_int
  123. }
  124. fn exit(status: c_int) -> ! {
  125. let _ = syscall::exit(status as usize);
  126. loop {}
  127. }
  128. unsafe fn execve(
  129. path: &CStr,
  130. mut argv: *const *mut c_char,
  131. mut envp: *const *mut c_char,
  132. ) -> c_int {
  133. let mut file = match File::open(path, fcntl::O_RDONLY | fcntl::O_CLOEXEC) {
  134. Ok(file) => file,
  135. Err(_) => return -1,
  136. };
  137. let fd = *file as usize;
  138. // Count arguments
  139. let mut len = 0;
  140. while !(*argv.offset(len)).is_null() {
  141. len += 1;
  142. }
  143. let mut args: Vec<[usize; 2]> = Vec::with_capacity(len as usize);
  144. // Read shebang (for example #!/bin/sh)
  145. let interpreter = {
  146. let mut reader = BufReader::new(&mut file);
  147. let mut shebang = [0; 2];
  148. let mut read = 0;
  149. while read < 2 {
  150. match reader.read(&mut shebang) {
  151. Ok(0) => break,
  152. Ok(i) => read += i,
  153. Err(_) => return -1,
  154. }
  155. }
  156. if &shebang == b"#!" {
  157. // So, this file is interpreted.
  158. // That means the actual file descriptor passed to `fexec` won't be this file.
  159. // So we need to check ourselves that this file is actually be executable.
  160. let mut stat = redox_stat::default();
  161. if e(syscall::fstat(fd, &mut stat)) == !0 {
  162. return -1;
  163. }
  164. let uid = e(syscall::getuid());
  165. if uid == !0 {
  166. return -1;
  167. }
  168. let gid = e(syscall::getuid());
  169. if gid == !0 {
  170. return -1;
  171. }
  172. let mode = if uid == stat.st_uid as usize {
  173. (stat.st_mode >> 3 * 2) & 0o7
  174. } else if gid == stat.st_gid as usize {
  175. (stat.st_mode >> 3 * 1) & 0o7
  176. } else {
  177. stat.st_mode & 0o7
  178. };
  179. if mode & 0o1 == 0o0 {
  180. errno = EPERM;
  181. return -1;
  182. }
  183. // Then, read the actual interpreter:
  184. let mut interpreter = Vec::new();
  185. match reader.read_until(b'\n', &mut interpreter) {
  186. Err(_) => return -1,
  187. Ok(_) => {
  188. if interpreter.ends_with(&[b'\n']) {
  189. interpreter.pop().unwrap();
  190. }
  191. // TODO: Returning the interpreter here is actually a
  192. // hack. Preferrably we should reassign `file =`
  193. // directly from here. Just wait until NLL comes
  194. // around...
  195. Some(interpreter)
  196. }
  197. }
  198. } else {
  199. None
  200. }
  201. };
  202. let mut _interpreter_path = None;
  203. if let Some(interpreter) = interpreter {
  204. let cstring = match CString::new(interpreter) {
  205. Ok(cstring) => cstring,
  206. Err(_) => return -1,
  207. };
  208. file = match File::open(&cstring, fcntl::O_RDONLY | fcntl::O_CLOEXEC) {
  209. Ok(file) => file,
  210. Err(_) => return -1,
  211. };
  212. // Make sure path is kept alive long enough, and push it to the arguments
  213. _interpreter_path = Some(cstring);
  214. let path_ref = _interpreter_path.as_ref().unwrap();
  215. args.push([path_ref.as_ptr() as usize, path_ref.to_bytes().len()]);
  216. } else {
  217. if file.seek(SeekFrom::Start(0)).is_err() {
  218. return -1;
  219. }
  220. }
  221. // Arguments
  222. while !(*argv).is_null() {
  223. let arg = *argv;
  224. let mut len = 0;
  225. while *arg.offset(len) != 0 {
  226. len += 1;
  227. }
  228. args.push([arg as usize, len as usize]);
  229. argv = argv.offset(1);
  230. }
  231. // Environment variables
  232. let mut len = 0;
  233. while !(*envp.offset(len)).is_null() {
  234. len += 1;
  235. }
  236. let mut envs: Vec<[usize; 2]> = Vec::with_capacity(len as usize);
  237. while !(*envp).is_null() {
  238. let env = *envp;
  239. let mut len = 0;
  240. while *env.offset(len) != 0 {
  241. len += 1;
  242. }
  243. envs.push([env as usize, len as usize]);
  244. envp = envp.offset(1);
  245. }
  246. e(syscall::fexec(*file as usize, &args, &envs)) as c_int
  247. }
  248. fn fchdir(fd: c_int) -> c_int {
  249. let mut buf = [0; 4096];
  250. let res = e(syscall::fpath(fd as usize, &mut buf));
  251. if res == !0 {
  252. !0
  253. } else {
  254. e(syscall::chdir(&buf[..res])) as c_int
  255. }
  256. }
  257. fn fchmod(fd: c_int, mode: mode_t) -> c_int {
  258. e(syscall::fchmod(fd as usize, mode as u16)) as c_int
  259. }
  260. fn fchown(fd: c_int, owner: uid_t, group: gid_t) -> c_int {
  261. e(syscall::fchown(fd as usize, owner as u32, group as u32)) as c_int
  262. }
  263. fn fcntl(fd: c_int, cmd: c_int, args: c_int) -> c_int {
  264. e(syscall::fcntl(fd as usize, cmd as usize, args as usize)) as c_int
  265. }
  266. fn flock(_fd: c_int, _operation: c_int) -> c_int {
  267. // TODO: Redox does not have file locking yet
  268. 0
  269. }
  270. fn fork() -> pid_t {
  271. e(unsafe { syscall::clone(syscall::CloneFlags::empty()) }) as pid_t
  272. }
  273. fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
  274. let mut redox_buf: redox_stat = redox_stat::default();
  275. match e(syscall::fstat(fildes as usize, &mut redox_buf)) {
  276. 0 => {
  277. if let Some(buf) = unsafe { buf.as_mut() } {
  278. buf.st_dev = redox_buf.st_dev as dev_t;
  279. buf.st_ino = redox_buf.st_ino as ino_t;
  280. buf.st_nlink = redox_buf.st_nlink as nlink_t;
  281. buf.st_mode = redox_buf.st_mode as mode_t;
  282. buf.st_uid = redox_buf.st_uid as uid_t;
  283. buf.st_gid = redox_buf.st_gid as gid_t;
  284. // TODO st_rdev
  285. buf.st_rdev = 0;
  286. buf.st_size = redox_buf.st_size as off_t;
  287. buf.st_blksize = redox_buf.st_blksize as blksize_t;
  288. buf.st_atim = timespec {
  289. tv_sec: redox_buf.st_atime as time_t,
  290. tv_nsec: redox_buf.st_atime_nsec as c_long,
  291. };
  292. buf.st_mtim = timespec {
  293. tv_sec: redox_buf.st_mtime as time_t,
  294. tv_nsec: redox_buf.st_mtime_nsec as c_long,
  295. };
  296. buf.st_ctim = timespec {
  297. tv_sec: redox_buf.st_ctime as time_t,
  298. tv_nsec: redox_buf.st_ctime_nsec as c_long,
  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) };
  365. if !buf_slice.is_empty() {
  366. let nonnull_size = buf_slice.len() - 1;
  367. let read = e(syscall::getcwd(&mut buf_slice[..nonnull_size]));
  368. if read == !0 {
  369. ptr::null_mut()
  370. } else if read == nonnull_size {
  371. unsafe {
  372. errno = ERANGE;
  373. }
  374. ptr::null_mut()
  375. } else {
  376. for b in &mut buf_slice[read..] {
  377. *b = 0;
  378. }
  379. buf
  380. }
  381. } else {
  382. unsafe {
  383. errno = EINVAL;
  384. }
  385. ptr::null_mut()
  386. }
  387. }
  388. fn getdents(fd: c_int, mut dirents: *mut dirent, max_bytes: usize) -> c_int {
  389. //TODO: rewrite this code. Originally the *dirents = dirent { ... } stuff below caused
  390. // massive issues. This has been hacked around, but it still isn't perfect
  391. // Get initial reading position
  392. let mut read = match syscall::lseek(fd as usize, 0, syscall::SEEK_CUR) {
  393. Ok(pos) => pos as isize,
  394. Err(err) => return -err.errno,
  395. };
  396. let mut written = 0;
  397. let mut buf = [0; 1024];
  398. let mut name = [0; 256];
  399. let mut i = 0;
  400. let mut flush = |written: &mut usize, i: &mut usize, name: &mut [c_char; 256]| {
  401. if *i < name.len() {
  402. // Set NUL byte
  403. name[*i] = 0;
  404. }
  405. // Get size: full size - unused bytes
  406. if *written + mem::size_of::<dirent>() > max_bytes {
  407. // Seek back to after last read entry and return
  408. match syscall::lseek(fd as usize, read, syscall::SEEK_SET) {
  409. Ok(_) => return Some(*written as c_int),
  410. Err(err) => return Some(-err.errno),
  411. }
  412. }
  413. let size = mem::size_of::<dirent>() - name.len().saturating_sub(*i + 1);
  414. unsafe {
  415. //This is the offending code mentioned above
  416. *dirents = dirent {
  417. d_ino: 0,
  418. d_off: read as off_t,
  419. d_reclen: size as c_ushort,
  420. d_type: 0,
  421. d_name: *name,
  422. };
  423. dirents = (dirents as *mut u8).offset(size as isize) as *mut dirent;
  424. }
  425. read += *i as isize + /* newline */ 1;
  426. *written += size;
  427. *i = 0;
  428. None
  429. };
  430. loop {
  431. // Read a chunk from the directory
  432. let len = match syscall::read(fd as usize, &mut buf) {
  433. Ok(0) => {
  434. if i > 0 {
  435. if let Some(value) = flush(&mut written, &mut i, &mut name) {
  436. return value;
  437. }
  438. }
  439. return written as c_int;
  440. }
  441. Ok(n) => n,
  442. Err(err) => return -err.errno,
  443. };
  444. // Handle everything
  445. let mut start = 0;
  446. while start < len {
  447. let buf = &buf[start..len];
  448. // Copy everything up until a newline
  449. let newline = buf.iter().position(|&c| c == b'\n');
  450. let pre_len = newline.unwrap_or(buf.len());
  451. let post_len = newline.map(|i| i + 1).unwrap_or(buf.len());
  452. if i < pre_len {
  453. // Reserve space for NUL byte
  454. let name_len = name.len() - 1;
  455. let name = &mut name[i..name_len];
  456. let copy = pre_len.min(name.len());
  457. let buf = unsafe { slice::from_raw_parts(buf.as_ptr() as *const c_char, copy) };
  458. name[..copy].copy_from_slice(buf);
  459. }
  460. i += pre_len;
  461. start += post_len;
  462. // Write the directory entry
  463. if newline.is_some() {
  464. if let Some(value) = flush(&mut written, &mut i, &mut name) {
  465. return value;
  466. }
  467. }
  468. }
  469. }
  470. }
  471. fn getegid() -> gid_t {
  472. e(syscall::getegid()) as gid_t
  473. }
  474. fn geteuid() -> uid_t {
  475. e(syscall::geteuid()) as uid_t
  476. }
  477. fn getgid() -> gid_t {
  478. e(syscall::getgid()) as gid_t
  479. }
  480. fn getpgid(pid: pid_t) -> pid_t {
  481. e(syscall::getpgid(pid as usize)) as pid_t
  482. }
  483. fn getpid() -> pid_t {
  484. e(syscall::getpid()) as pid_t
  485. }
  486. fn getppid() -> pid_t {
  487. e(syscall::getppid()) as pid_t
  488. }
  489. fn getrandom(buf: &mut [u8], flags: c_uint) -> ssize_t {
  490. //TODO: make this a system call?
  491. let path = if flags & sys_random::GRND_RANDOM != 0 {
  492. //TODO: /dev/random equivalent
  493. "rand:"
  494. } else {
  495. "rand:"
  496. };
  497. let mut open_flags = syscall::O_RDONLY | syscall::O_CLOEXEC;
  498. if flags & sys_random::GRND_NONBLOCK != 0 {
  499. open_flags |= syscall::O_NONBLOCK;
  500. }
  501. let fd = e(syscall::open(path, open_flags));
  502. if fd == !0 {
  503. return -1;
  504. }
  505. let res = e(syscall::read(fd, buf)) as ssize_t;
  506. let _ = syscall::close(fd);
  507. res
  508. }
  509. unsafe fn getrlimit(resource: c_int, rlim: *mut rlimit) -> c_int {
  510. //TODO
  511. if !rlim.is_null() {
  512. (*rlim).rlim_cur = RLIM_INFINITY;
  513. (*rlim).rlim_max = RLIM_INFINITY;
  514. }
  515. 0
  516. }
  517. fn gettid() -> pid_t {
  518. //TODO
  519. Self::getpid()
  520. }
  521. fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int {
  522. let mut redox_tp = redox_timespec::default();
  523. let err = e(syscall::clock_gettime(
  524. syscall::CLOCK_REALTIME,
  525. &mut redox_tp,
  526. )) as c_int;
  527. if err < 0 {
  528. return err;
  529. }
  530. unsafe {
  531. (*tp).tv_sec = redox_tp.tv_sec as time_t;
  532. (*tp).tv_usec = (redox_tp.tv_nsec / 1000) as suseconds_t;
  533. if !tzp.is_null() {
  534. (*tzp).tz_minuteswest = 0;
  535. (*tzp).tz_dsttime = 0;
  536. }
  537. }
  538. 0
  539. }
  540. fn getuid() -> uid_t {
  541. e(syscall::getuid()) as pid_t
  542. }
  543. fn link(path1: &CStr, path2: &CStr) -> c_int {
  544. e(unsafe { syscall::link(path1.as_ptr() as *const u8, path2.as_ptr() as *const u8) })
  545. as c_int
  546. }
  547. fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t {
  548. e(syscall::lseek(
  549. fd as usize,
  550. offset as isize,
  551. whence as usize,
  552. )) as off_t
  553. }
  554. fn mkdir(path: &CStr, mode: mode_t) -> c_int {
  555. match File::create(
  556. path,
  557. fcntl::O_DIRECTORY | fcntl::O_EXCL | fcntl::O_CLOEXEC,
  558. 0o777,
  559. ) {
  560. Ok(_fd) => 0,
  561. Err(_) => -1,
  562. }
  563. }
  564. fn mkfifo(path: &CStr, mode: mode_t) -> c_int {
  565. match File::create(
  566. path,
  567. fcntl::O_CREAT | fcntl::O_CLOEXEC,
  568. syscall::MODE_FIFO as mode_t | (mode & 0o777),
  569. ) {
  570. Ok(fd) => 0,
  571. Err(_) => -1,
  572. }
  573. }
  574. unsafe fn mmap(
  575. addr: *mut c_void,
  576. len: usize,
  577. prot: c_int,
  578. flags: c_int,
  579. fildes: c_int,
  580. off: off_t,
  581. ) -> *mut c_void {
  582. let map = Map {
  583. offset: off as usize,
  584. size: len,
  585. flags: syscall::MapFlags::from_bits_truncate(
  586. ((prot as usize) << 16) | ((flags as usize) & 0xFFFF),
  587. ),
  588. address: addr as usize,
  589. };
  590. if flags & MAP_ANON == MAP_ANON {
  591. let fd = e(syscall::open(
  592. "memory:",
  593. syscall::O_STAT | syscall::O_CLOEXEC,
  594. )); // flags don't matter currently
  595. if fd == !0 {
  596. return !0 as *mut c_void;
  597. }
  598. let addr = e(syscall::fmap(fd, &map)) as *mut c_void;
  599. let _ = syscall::close(fd);
  600. addr
  601. } else {
  602. e(syscall::fmap(fildes as usize, &map)) as *mut c_void
  603. }
  604. }
  605. unsafe fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> c_int {
  606. e(syscall::mprotect(
  607. addr as usize,
  608. len,
  609. syscall::MapFlags::from_bits((prot as usize) << 16)
  610. .expect("mprotect: invalid bit pattern"),
  611. )) as c_int
  612. }
  613. unsafe fn msync(addr: *mut c_void, len: usize, flags: c_int) -> c_int {
  614. eprintln!("msync {:p} {:x} {:x}", addr, len, flags);
  615. e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int
  616. /* TODO
  617. e(syscall::msync(
  618. addr as usize,
  619. len,
  620. flags
  621. )) as c_int
  622. */
  623. }
  624. unsafe fn munmap(addr: *mut c_void, len: usize) -> c_int {
  625. if e(syscall::funmap(addr as usize, len)) == !0 {
  626. return !0;
  627. }
  628. 0
  629. }
  630. fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
  631. let redox_rqtp = unsafe { redox_timespec::from(&*rqtp) };
  632. let mut redox_rmtp: redox_timespec;
  633. if rmtp.is_null() {
  634. redox_rmtp = redox_timespec::default();
  635. } else {
  636. redox_rmtp = unsafe { redox_timespec::from(&*rmtp) };
  637. }
  638. match e(syscall::nanosleep(&redox_rqtp, &mut redox_rmtp)) as c_int {
  639. -1 => -1,
  640. _ => {
  641. unsafe {
  642. if !rmtp.is_null() {
  643. (*rmtp).tv_sec = redox_rmtp.tv_sec;
  644. (*rmtp).tv_nsec = redox_rmtp.tv_nsec as i64;
  645. }
  646. }
  647. 0
  648. }
  649. }
  650. }
  651. fn open(path: &CStr, oflag: c_int, mode: mode_t) -> c_int {
  652. e(syscall::open(
  653. path.to_bytes(),
  654. ((oflag as usize) & 0xFFFF_0000) | ((mode as usize) & 0xFFFF),
  655. )) as c_int
  656. }
  657. fn pipe2(fds: &mut [c_int], flags: c_int) -> c_int {
  658. let mut usize_fds: [usize; 2] = [0; 2];
  659. let res = e(syscall::pipe2(&mut usize_fds, flags as usize));
  660. fds[0] = usize_fds[0] as c_int;
  661. fds[1] = usize_fds[1] as c_int;
  662. res as c_int
  663. }
  664. #[cfg(target_arch = "x86_64")]
  665. unsafe fn pte_clone(stack: *mut usize) -> pid_t {
  666. let flags = syscall::CLONE_VM
  667. | syscall::CLONE_FS
  668. | syscall::CLONE_FILES
  669. | syscall::CLONE_SIGHAND
  670. | syscall::CLONE_STACK;
  671. let pid;
  672. llvm_asm!("
  673. # Call clone syscall
  674. syscall
  675. # Check if child or parent
  676. test rax, rax
  677. jnz .parent
  678. # Load registers
  679. pop rax
  680. pop rdi
  681. pop rsi
  682. pop rdx
  683. pop rcx
  684. pop r8
  685. pop r9
  686. # Call entry point
  687. call rax
  688. # Exit
  689. mov rax, 1
  690. xor rdi, rdi
  691. syscall
  692. # Invalid instruction on failure to exit
  693. ud2
  694. # Return PID if parent
  695. .parent:
  696. "
  697. : "={rax}"(pid)
  698. : "{rax}"(syscall::SYS_CLONE), "{rdi}"(flags), "{rsi}"(stack)
  699. : "memory", "rbx", "rcx", "rdx", "rsi", "rdi", "r8",
  700. "r9", "r10", "r11", "r12", "r13", "r14", "r15"
  701. : "intel", "volatile"
  702. );
  703. e(syscall::Error::demux(pid)) as pid_t
  704. }
  705. fn read(fd: c_int, buf: &mut [u8]) -> ssize_t {
  706. e(syscall::read(fd as usize, buf)) as ssize_t
  707. }
  708. fn fpath(fildes: c_int, out: &mut [u8]) -> ssize_t {
  709. e(syscall::fpath(fildes as usize, out)) as ssize_t
  710. }
  711. fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t {
  712. let file = match File::open(
  713. pathname,
  714. fcntl::O_PATH | fcntl::O_SYMLINK | fcntl::O_CLOEXEC,
  715. ) {
  716. Ok(ok) => ok,
  717. Err(_) => return -1,
  718. };
  719. if out.is_empty() {
  720. return 0;
  721. }
  722. let len = out.len();
  723. let read = e(syscall::fpath(*file as usize, &mut out[..len - 1]));
  724. if (read as c_int) < 0 {
  725. return -1;
  726. }
  727. out[read as usize] = 0;
  728. 0
  729. }
  730. fn rename(oldpath: &CStr, newpath: &CStr) -> c_int {
  731. match File::open(oldpath, fcntl::O_PATH | fcntl::O_CLOEXEC) {
  732. Ok(file) => e(syscall::frename(*file as usize, newpath.to_bytes())) as c_int,
  733. Err(_) => -1,
  734. }
  735. }
  736. fn rmdir(path: &CStr) -> c_int {
  737. e(syscall::rmdir(path.to_bytes())) as c_int
  738. }
  739. fn sched_yield() -> c_int {
  740. e(syscall::sched_yield()) as c_int
  741. }
  742. fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
  743. e(syscall::setpgid(pid as usize, pgid as usize)) as c_int
  744. }
  745. fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
  746. e(syscall::setregid(rgid as usize, egid as usize)) as c_int
  747. }
  748. fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
  749. e(syscall::setreuid(ruid as usize, euid as usize)) as c_int
  750. }
  751. fn symlink(path1: &CStr, path2: &CStr) -> c_int {
  752. let mut file = match File::create(
  753. path2,
  754. fcntl::O_WRONLY | fcntl::O_SYMLINK | fcntl::O_CLOEXEC,
  755. 0o777,
  756. ) {
  757. Ok(ok) => ok,
  758. Err(_) => return -1,
  759. };
  760. if file.write(path1.to_bytes()).is_err() {
  761. return -1;
  762. }
  763. 0
  764. }
  765. fn umask(mask: mode_t) -> mode_t {
  766. e(syscall::umask(mask as usize)) as mode_t
  767. }
  768. fn uname(utsname: *mut utsname) -> c_int {
  769. fn gethostname(name: &mut [u8]) -> io::Result<()> {
  770. if name.is_empty() {
  771. return Ok(());
  772. }
  773. let mut file = File::open(
  774. &CString::new("/etc/hostname").unwrap(),
  775. fcntl::O_RDONLY | fcntl::O_CLOEXEC,
  776. )?;
  777. let mut read = 0;
  778. let name_len = name.len();
  779. loop {
  780. match file.read(&mut name[read..name_len - 1])? {
  781. 0 => break,
  782. n => read += n,
  783. }
  784. }
  785. name[read] = 0;
  786. Ok(())
  787. }
  788. fn inner(utsname: *mut utsname) -> CoreResult<(), i32> {
  789. match gethostname(unsafe {
  790. slice::from_raw_parts_mut(
  791. (*utsname).nodename.as_mut_ptr() as *mut u8,
  792. (*utsname).nodename.len(),
  793. )
  794. }) {
  795. Ok(_) => (),
  796. Err(_) => return Err(EIO),
  797. }
  798. let file_path = c_str!("sys:uname");
  799. let mut file = match File::open(file_path, fcntl::O_RDONLY | fcntl::O_CLOEXEC) {
  800. Ok(ok) => ok,
  801. Err(_) => return Err(EIO),
  802. };
  803. let mut lines = BufReader::new(&mut file).lines();
  804. let mut read_line = |dst: &mut [c_char]| {
  805. let line = match lines.next() {
  806. Some(Ok(l)) => match CString::new(l) {
  807. Ok(l) => l,
  808. Err(_) => return Err(EIO),
  809. },
  810. None | Some(Err(_)) => return Err(EIO),
  811. };
  812. let line_slice: &[c_char] = unsafe { mem::transmute(line.as_bytes_with_nul()) };
  813. if line_slice.len() <= UTSLENGTH {
  814. dst[..line_slice.len()].copy_from_slice(line_slice);
  815. Ok(())
  816. } else {
  817. Err(EIO)
  818. }
  819. };
  820. unsafe {
  821. read_line(&mut (*utsname).sysname)?;
  822. read_line(&mut (*utsname).release)?;
  823. read_line(&mut (*utsname).machine)?;
  824. // Version is not provided
  825. ptr::write_bytes((*utsname).version.as_mut_ptr(), 0, UTSLENGTH);
  826. // Redox doesn't provide domainname in sys:uname
  827. //read_line(&mut (*utsname).domainname)?;
  828. ptr::write_bytes((*utsname).domainname.as_mut_ptr(), 0, UTSLENGTH);
  829. }
  830. Ok(())
  831. }
  832. match inner(utsname) {
  833. Ok(()) => 0,
  834. Err(err) => unsafe {
  835. errno = err;
  836. -1
  837. },
  838. }
  839. }
  840. fn unlink(path: &CStr) -> c_int {
  841. e(syscall::unlink(path.to_bytes())) as c_int
  842. }
  843. fn waitpid(mut pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
  844. if pid == !0 {
  845. pid = 0;
  846. }
  847. let mut res = None;
  848. let mut status = 0;
  849. let inner = |status: &mut usize, flags| {
  850. syscall::waitpid(
  851. pid as usize,
  852. status,
  853. syscall::WaitFlags::from_bits(flags as usize)
  854. .expect("waitpid: invalid bit pattern"),
  855. )
  856. };
  857. // First, allow ptrace to handle waitpid
  858. // TODO: Handle special PIDs here (such as -1)
  859. let state = ptrace::init_state();
  860. let mut sessions = state.sessions.lock();
  861. if let Ok(session) = ptrace::get_session(&mut sessions, pid) {
  862. if options & sys_wait::WNOHANG != sys_wait::WNOHANG {
  863. let mut _event = PtraceEvent::default();
  864. let _ = (&mut &session.tracer).read(&mut _event);
  865. res = Some(e(inner(
  866. &mut status,
  867. options | sys_wait::WNOHANG | sys_wait::WUNTRACED,
  868. )));
  869. if res == Some(0) {
  870. // WNOHANG, just pretend ptrace SIGSTOP:ped this
  871. status = (syscall::SIGSTOP << 8) | 0x7f;
  872. assert!(syscall::wifstopped(status));
  873. assert_eq!(syscall::wstopsig(status), syscall::SIGSTOP);
  874. res = Some(pid as usize);
  875. }
  876. }
  877. }
  878. // If ptrace didn't impact this waitpid, proceed *almost* as
  879. // normal: We still need to add WUNTRACED, but we only return
  880. // it if (and only if) a ptrace traceme was activated during
  881. // the wait.
  882. let res = res.unwrap_or_else(|| loop {
  883. let res = e(inner(&mut status, options | sys_wait::WUNTRACED));
  884. // TODO: Also handle special PIDs here
  885. if !syscall::wifstopped(res) || ptrace::is_traceme(pid) {
  886. break res;
  887. }
  888. });
  889. // If stat_loc is non-null, set that and the return
  890. unsafe {
  891. if !stat_loc.is_null() {
  892. *stat_loc = status as c_int;
  893. }
  894. }
  895. res as pid_t
  896. }
  897. fn write(fd: c_int, buf: &[u8]) -> ssize_t {
  898. e(syscall::write(fd as usize, buf)) as ssize_t
  899. }
  900. fn verify() -> bool {
  901. // GETPID on Redox is 20, which is WRITEV on Linux
  902. e(unsafe { syscall::syscall5(syscall::number::SYS_GETPID, !0, !0, !0, !0, !0) }) != !0
  903. }
  904. }