mod.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. use core::{arch::asm, ptr};
  2. use core_io::Write;
  3. use super::{errno, types::*, Pal};
  4. use crate::{
  5. c_str::CStr,
  6. header::{dirent::dirent, signal::SIGCHLD, sys_stat::S_IFIFO},
  7. };
  8. // use header::sys_resource::rusage;
  9. use crate::header::{
  10. sys_resource::rlimit,
  11. sys_stat::stat,
  12. sys_statvfs::statvfs,
  13. sys_time::{timeval, timezone},
  14. };
  15. // use header::sys_times::tms;
  16. use crate::header::{sys_utsname::utsname, time::timespec};
  17. mod epoll;
  18. mod ptrace;
  19. mod signal;
  20. mod socket;
  21. const AT_FDCWD: c_int = -100;
  22. const AT_EMPTY_PATH: c_int = 0x1000;
  23. const AT_REMOVEDIR: c_int = 0x200;
  24. const SYS_CLONE: usize = 56;
  25. const CLONE_VM: usize = 0x0100;
  26. const CLONE_FS: usize = 0x0200;
  27. const CLONE_FILES: usize = 0x0400;
  28. const CLONE_SIGHAND: usize = 0x0800;
  29. const CLONE_THREAD: usize = 0x00010000;
  30. #[repr(C)]
  31. #[derive(Default)]
  32. struct linux_statfs {
  33. f_type: c_long, /* type of file system (see below) */
  34. f_bsize: c_long, /* optimal transfer block size */
  35. f_blocks: fsblkcnt_t, /* total data blocks in file system */
  36. f_bfree: fsblkcnt_t, /* free blocks in fs */
  37. f_bavail: fsblkcnt_t, /* free blocks available to unprivileged user */
  38. f_files: fsfilcnt_t, /* total file nodes in file system */
  39. f_ffree: fsfilcnt_t, /* free file nodes in fs */
  40. f_fsid: c_long, /* file system id */
  41. f_namelen: c_long, /* maximum length of filenames */
  42. f_frsize: c_long, /* fragment size (since Linux 2.6) */
  43. f_flags: c_long,
  44. f_spare: [c_long; 4],
  45. }
  46. pub fn e(sys: usize) -> usize {
  47. if (sys as isize) < 0 && (sys as isize) >= -256 {
  48. unsafe {
  49. errno = -(sys as isize) as c_int;
  50. }
  51. !0
  52. } else {
  53. sys
  54. }
  55. }
  56. pub struct Sys;
  57. impl Sys {
  58. // fn getrusage(who: c_int, r_usage: *mut rusage) -> c_int {
  59. // e(unsafe { syscall!(GETRUSAGE, who, r_usage) }) as c_int
  60. // }
  61. pub unsafe fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int {
  62. // TODO: Somehow support varargs to syscall??
  63. e(syscall!(IOCTL, fd, request, out)) as c_int
  64. }
  65. // fn times(out: *mut tms) -> clock_t {
  66. // unsafe { syscall!(TIMES, out) as clock_t }
  67. // }
  68. }
  69. impl Pal for Sys {
  70. fn access(path: &CStr, mode: c_int) -> c_int {
  71. e(unsafe { syscall!(ACCESS, path.as_ptr(), mode) }) as c_int
  72. }
  73. fn brk(addr: *mut c_void) -> *mut c_void {
  74. unsafe { syscall!(BRK, addr) as *mut c_void }
  75. }
  76. fn chdir(path: &CStr) -> c_int {
  77. e(unsafe { syscall!(CHDIR, path.as_ptr()) }) as c_int
  78. }
  79. fn chmod(path: &CStr, mode: mode_t) -> c_int {
  80. e(unsafe { syscall!(FCHMODAT, AT_FDCWD, path.as_ptr(), mode, 0) }) as c_int
  81. }
  82. fn chown(path: &CStr, owner: uid_t, group: gid_t) -> c_int {
  83. e(unsafe {
  84. syscall!(
  85. FCHOWNAT,
  86. AT_FDCWD,
  87. path.as_ptr(),
  88. owner as u32,
  89. group as u32
  90. )
  91. }) as c_int
  92. }
  93. fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int {
  94. e(unsafe { syscall!(CLOCK_GETTIME, clk_id, tp) }) as c_int
  95. }
  96. fn close(fildes: c_int) -> c_int {
  97. e(unsafe { syscall!(CLOSE, fildes) }) as c_int
  98. }
  99. fn dup(fildes: c_int) -> c_int {
  100. e(unsafe { syscall!(DUP, fildes) }) as c_int
  101. }
  102. fn dup2(fildes: c_int, fildes2: c_int) -> c_int {
  103. e(unsafe { syscall!(DUP3, fildes, fildes2, 0) }) as c_int
  104. }
  105. unsafe fn execve(path: &CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
  106. e(syscall!(EXECVE, path.as_ptr(), argv, envp)) as c_int
  107. }
  108. fn exit(status: c_int) -> ! {
  109. unsafe {
  110. syscall!(EXIT, status);
  111. }
  112. loop {}
  113. }
  114. fn fchdir(fildes: c_int) -> c_int {
  115. e(unsafe { syscall!(FCHDIR, fildes) }) as c_int
  116. }
  117. fn fchmod(fildes: c_int, mode: mode_t) -> c_int {
  118. e(unsafe { syscall!(FCHMOD, fildes, mode) }) as c_int
  119. }
  120. fn fchown(fildes: c_int, owner: uid_t, group: gid_t) -> c_int {
  121. e(unsafe { syscall!(FCHOWN, fildes, owner, group) }) as c_int
  122. }
  123. fn flock(fd: c_int, operation: c_int) -> c_int {
  124. e(unsafe { syscall!(FLOCK, fd, operation) }) as c_int
  125. }
  126. fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
  127. let empty = b"\0";
  128. let empty_ptr = empty.as_ptr() as *const c_char;
  129. e(unsafe { syscall!(NEWFSTATAT, fildes, empty_ptr, buf, AT_EMPTY_PATH) }) as c_int
  130. }
  131. fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int {
  132. let mut kbuf = linux_statfs::default();
  133. let kbuf_ptr = &mut kbuf as *mut linux_statfs;
  134. let res = e(unsafe { syscall!(FSTATFS, fildes, kbuf_ptr) }) as c_int;
  135. if res == 0 {
  136. unsafe {
  137. if !buf.is_null() {
  138. (*buf).f_bsize = kbuf.f_bsize as c_ulong;
  139. (*buf).f_frsize = if kbuf.f_frsize != 0 {
  140. kbuf.f_frsize
  141. } else {
  142. kbuf.f_bsize
  143. } as c_ulong;
  144. (*buf).f_blocks = kbuf.f_blocks;
  145. (*buf).f_bfree = kbuf.f_bfree;
  146. (*buf).f_bavail = kbuf.f_bavail;
  147. (*buf).f_files = kbuf.f_files;
  148. (*buf).f_ffree = kbuf.f_ffree;
  149. (*buf).f_favail = kbuf.f_ffree;
  150. (*buf).f_fsid = kbuf.f_fsid as c_ulong;
  151. (*buf).f_flag = kbuf.f_flags as c_ulong;
  152. (*buf).f_namemax = kbuf.f_namelen as c_ulong;
  153. }
  154. }
  155. }
  156. res
  157. }
  158. fn fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int {
  159. e(unsafe { syscall!(FCNTL, fildes, cmd, arg) }) as c_int
  160. }
  161. fn fork() -> pid_t {
  162. e(unsafe { syscall!(CLONE, SIGCHLD, 0, 0, 0, 0) }) as pid_t
  163. }
  164. fn fpath(fildes: c_int, out: &mut [u8]) -> ssize_t {
  165. let mut proc_path = b"/proc/self/fd/".to_vec();
  166. write!(proc_path, "{}", fildes).unwrap();
  167. proc_path.push(0);
  168. Self::readlink(CStr::from_bytes_with_nul(&proc_path).unwrap(), out)
  169. }
  170. fn fsync(fildes: c_int) -> c_int {
  171. e(unsafe { syscall!(FSYNC, fildes) }) as c_int
  172. }
  173. fn ftruncate(fildes: c_int, length: off_t) -> c_int {
  174. e(unsafe { syscall!(FTRUNCATE, fildes, length) }) as c_int
  175. }
  176. fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> c_int {
  177. unsafe { syscall!(FUTEX, addr, op, val, val2, 0, 0) as c_int }
  178. }
  179. fn futimens(fd: c_int, times: *const timespec) -> c_int {
  180. e(unsafe { syscall!(UTIMENSAT, fd, ptr::null::<c_char>(), times, 0) }) as c_int
  181. }
  182. fn utimens(path: &CStr, times: *const timespec) -> c_int {
  183. e(unsafe { syscall!(UTIMENSAT, AT_FDCWD, path.as_ptr(), times, 0) }) as c_int
  184. }
  185. fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char {
  186. if e(unsafe { syscall!(GETCWD, buf, size) }) == !0 {
  187. ptr::null_mut()
  188. } else {
  189. buf
  190. }
  191. }
  192. fn getdents(fd: c_int, dirents: *mut dirent, bytes: usize) -> c_int {
  193. unsafe { syscall!(GETDENTS64, fd, dirents, bytes) as c_int }
  194. }
  195. fn getegid() -> gid_t {
  196. e(unsafe { syscall!(GETEGID) }) as gid_t
  197. }
  198. fn geteuid() -> uid_t {
  199. e(unsafe { syscall!(GETEUID) }) as uid_t
  200. }
  201. fn getgid() -> gid_t {
  202. e(unsafe { syscall!(GETGID) }) as gid_t
  203. }
  204. fn getpagesize() -> usize {
  205. 4096
  206. }
  207. fn getpgid(pid: pid_t) -> pid_t {
  208. e(unsafe { syscall!(GETPGID, pid) }) as pid_t
  209. }
  210. fn getpid() -> pid_t {
  211. e(unsafe { syscall!(GETPID) }) as pid_t
  212. }
  213. fn getppid() -> pid_t {
  214. e(unsafe { syscall!(GETPPID) }) as pid_t
  215. }
  216. fn getrandom(buf: &mut [u8], flags: c_uint) -> ssize_t {
  217. e(unsafe { syscall!(GETRANDOM, buf.as_mut_ptr(), buf.len(), flags) }) as ssize_t
  218. }
  219. unsafe fn getrlimit(resource: c_int, rlim: *mut rlimit) -> c_int {
  220. e(syscall!(GETRLIMIT, resource, rlim)) as c_int
  221. }
  222. fn getsid(pid: pid_t) -> pid_t {
  223. e(unsafe { syscall!(GETSID, pid) }) as pid_t
  224. }
  225. fn gettid() -> pid_t {
  226. e(unsafe { syscall!(GETTID) }) as pid_t
  227. }
  228. fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int {
  229. e(unsafe { syscall!(GETTIMEOFDAY, tp, tzp) }) as c_int
  230. }
  231. fn getuid() -> uid_t {
  232. e(unsafe { syscall!(GETUID) }) as uid_t
  233. }
  234. fn lchown(path: &CStr, owner: uid_t, group: gid_t) -> c_int {
  235. e(unsafe { syscall!(LCHOWN, path.as_ptr(), owner, group) }) as c_int
  236. }
  237. fn link(path1: &CStr, path2: &CStr) -> c_int {
  238. e(unsafe {
  239. syscall!(
  240. LINKAT,
  241. AT_FDCWD,
  242. path1.as_ptr(),
  243. AT_FDCWD,
  244. path2.as_ptr(),
  245. 0
  246. )
  247. }) as c_int
  248. }
  249. fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> off_t {
  250. e(unsafe { syscall!(LSEEK, fildes, offset, whence) }) as off_t
  251. }
  252. fn mkdir(path: &CStr, mode: mode_t) -> c_int {
  253. e(unsafe { syscall!(MKDIRAT, AT_FDCWD, path.as_ptr(), mode) }) as c_int
  254. }
  255. fn mkfifo(path: &CStr, mode: mode_t) -> c_int {
  256. e(unsafe { syscall!(MKNODAT, AT_FDCWD, path.as_ptr(), mode | S_IFIFO, 0) }) as c_int
  257. }
  258. unsafe fn mlock(addr: *const c_void, len: usize) -> c_int {
  259. e(syscall!(MLOCK, addr, len)) as c_int
  260. }
  261. fn mlockall(flags: c_int) -> c_int {
  262. e(unsafe { syscall!(MLOCKALL, flags) }) as c_int
  263. }
  264. unsafe fn mmap(
  265. addr: *mut c_void,
  266. len: usize,
  267. prot: c_int,
  268. flags: c_int,
  269. fildes: c_int,
  270. off: off_t,
  271. ) -> *mut c_void {
  272. e(syscall!(MMAP, addr, len, prot, flags, fildes, off)) as *mut c_void
  273. }
  274. unsafe fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> c_int {
  275. e(syscall!(MPROTECT, addr, len, prot)) as c_int
  276. }
  277. unsafe fn msync(addr: *mut c_void, len: usize, flags: c_int) -> c_int {
  278. e(syscall!(MSYNC, addr, len, flags)) as c_int
  279. }
  280. unsafe fn munlock(addr: *const c_void, len: usize) -> c_int {
  281. e(syscall!(MUNLOCK, addr, len)) as c_int
  282. }
  283. fn munlockall() -> c_int {
  284. e(unsafe { syscall!(MUNLOCKALL) }) as c_int
  285. }
  286. unsafe fn munmap(addr: *mut c_void, len: usize) -> c_int {
  287. e(syscall!(MUNMAP, addr, len)) as c_int
  288. }
  289. fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
  290. e(unsafe { syscall!(NANOSLEEP, rqtp, rmtp) }) as c_int
  291. }
  292. fn open(path: &CStr, oflag: c_int, mode: mode_t) -> c_int {
  293. e(unsafe { syscall!(OPENAT, AT_FDCWD, path.as_ptr(), oflag, mode) }) as c_int
  294. }
  295. fn pipe2(fildes: &mut [c_int], flags: c_int) -> c_int {
  296. e(unsafe { syscall!(PIPE2, fildes.as_mut_ptr(), flags) }) as c_int
  297. }
  298. #[cfg(target_arch = "x86_64")]
  299. unsafe fn pte_clone(stack: *mut usize) -> pid_t {
  300. let flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD;
  301. let pid;
  302. asm!("
  303. # Call clone syscall
  304. syscall
  305. # Check if child or parent
  306. test rax, rax
  307. jnz 1f
  308. # Load registers
  309. pop rax
  310. pop rdi
  311. pop rsi
  312. pop rdx
  313. pop rcx
  314. pop r8
  315. pop r9
  316. # Call entry point
  317. call rax
  318. # Exit
  319. mov rax, 60
  320. xor rdi, rdi
  321. syscall
  322. # Invalid instruction on failure to exit
  323. ud2
  324. # Return PID if parent
  325. 1:
  326. ",
  327. inout("rax") SYS_CLONE => pid,
  328. inout("rdi") flags => _,
  329. inout("rsi") stack => _,
  330. inout("rdx") 0 => _,
  331. inout("r10") 0 => _,
  332. inout("r8") 0 => _,
  333. //TODO: out("rbx") _,
  334. out("rcx") _,
  335. out("r9") _,
  336. out("r11") _,
  337. out("r12") _,
  338. out("r13") _,
  339. out("r14") _,
  340. out("r15") _,
  341. );
  342. e(pid) as pid_t
  343. }
  344. fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t {
  345. e(unsafe { syscall!(READ, fildes, buf.as_mut_ptr(), buf.len()) }) as ssize_t
  346. }
  347. fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t {
  348. e(unsafe {
  349. syscall!(
  350. READLINKAT,
  351. AT_FDCWD,
  352. pathname.as_ptr(),
  353. out.as_mut_ptr(),
  354. out.len()
  355. )
  356. }) as ssize_t
  357. }
  358. fn rename(old: &CStr, new: &CStr) -> c_int {
  359. e(unsafe { syscall!(RENAMEAT, AT_FDCWD, old.as_ptr(), AT_FDCWD, new.as_ptr()) }) as c_int
  360. }
  361. fn rmdir(path: &CStr) -> c_int {
  362. e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path.as_ptr(), AT_REMOVEDIR) }) as c_int
  363. }
  364. fn sched_yield() -> c_int {
  365. e(unsafe { syscall!(SCHED_YIELD) }) as c_int
  366. }
  367. fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
  368. e(unsafe { syscall!(SETPGID, pid, pgid) }) as c_int
  369. }
  370. fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
  371. e(unsafe { syscall!(SETREGID, rgid, egid) }) as c_int
  372. }
  373. fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
  374. e(unsafe { syscall!(SETREUID, ruid, euid) }) as c_int
  375. }
  376. fn symlink(path1: &CStr, path2: &CStr) -> c_int {
  377. e(unsafe { syscall!(SYMLINKAT, path1.as_ptr(), AT_FDCWD, path2.as_ptr()) }) as c_int
  378. }
  379. fn umask(mask: mode_t) -> mode_t {
  380. unsafe { syscall!(UMASK, mask) as mode_t }
  381. }
  382. fn uname(utsname: *mut utsname) -> c_int {
  383. e(unsafe { syscall!(UNAME, utsname, 0) }) as c_int
  384. }
  385. fn unlink(path: &CStr) -> c_int {
  386. e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path.as_ptr(), 0) }) as c_int
  387. }
  388. fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
  389. e(unsafe { syscall!(WAIT4, pid, stat_loc, options, 0) }) as pid_t
  390. }
  391. fn write(fildes: c_int, buf: &[u8]) -> ssize_t {
  392. e(unsafe { syscall!(WRITE, fildes, buf.as_ptr(), buf.len()) }) as ssize_t
  393. }
  394. fn verify() -> bool {
  395. // GETPID on Linux is 39, which does not exist on Redox
  396. e(unsafe { dsc::syscall5(dsc::nr::GETPID, !0, !0, !0, !0, !0) }) != !0
  397. }
  398. }