1 use core::{arch::asm, ptr}; 2 use core_io::Write; 3 4 use super::{errno, types::*, Pal}; 5 use crate::{ 6 c_str::CStr, 7 header::{dirent::dirent, errno::ENOSYS, signal::SIGCHLD, sys_stat::S_IFIFO}, 8 }; 9 // use header::sys_resource::rusage; 10 use crate::header::{ 11 sys_resource::rlimit, 12 sys_stat::stat, 13 sys_statvfs::statvfs, 14 sys_time::{timeval, timezone}, 15 }; 16 // use header::sys_times::tms; 17 use crate::header::{sys_utsname::utsname, time::timespec}; 18 19 mod epoll; 20 mod ptrace; 21 mod signal; 22 mod socket; 23 24 const AT_FDCWD: c_int = -100; 25 const AT_EMPTY_PATH: c_int = 0x1000; 26 const AT_REMOVEDIR: c_int = 0x200; 27 28 const SYS_CLONE: usize = 56; 29 const CLONE_VM: usize = 0x0100; 30 const CLONE_FS: usize = 0x0200; 31 const CLONE_FILES: usize = 0x0400; 32 const CLONE_SIGHAND: usize = 0x0800; 33 const CLONE_THREAD: usize = 0x00010000; 34 35 #[repr(C)] 36 #[derive(Default)] 37 struct linux_statfs { 38 f_type: c_long, /* type of file system (see below) */ 39 f_bsize: c_long, /* optimal transfer block size */ 40 f_blocks: fsblkcnt_t, /* total data blocks in file system */ 41 f_bfree: fsblkcnt_t, /* free blocks in fs */ 42 f_bavail: fsblkcnt_t, /* free blocks available to unprivileged user */ 43 f_files: fsfilcnt_t, /* total file nodes in file system */ 44 f_ffree: fsfilcnt_t, /* free file nodes in fs */ 45 f_fsid: c_long, /* file system id */ 46 f_namelen: c_long, /* maximum length of filenames */ 47 f_frsize: c_long, /* fragment size (since Linux 2.6) */ 48 f_flags: c_long, 49 f_spare: [c_long; 4], 50 } 51 52 pub fn e(sys: usize) -> usize { 53 if (sys as isize) < 0 && (sys as isize) >= -256 { 54 unsafe { 55 errno = -(sys as isize) as c_int; 56 } 57 !0 58 } else { 59 sys 60 } 61 } 62 63 pub struct Sys; 64 65 impl Sys { 66 // fn getrusage(who: c_int, r_usage: *mut rusage) -> c_int { 67 // e(unsafe { syscall!(GETRUSAGE, who, r_usage) }) as c_int 68 // } 69 70 pub unsafe fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int { 71 // TODO: Somehow support varargs to syscall?? 72 // e(syscall!(IOCTL, fd, request, out)) as c_int 73 unimplemented!() 74 } 75 76 // fn times(out: *mut tms) -> clock_t { 77 // unsafe { syscall!(TIMES, out) as clock_t } 78 // } 79 } 80 81 impl Pal for Sys { 82 fn access(path: &CStr, mode: c_int) -> c_int { 83 // e(unsafe { syscall!(ACCESS, path.as_ptr(), mode) }) as c_int 84 unimplemented!() 85 } 86 87 fn brk(addr: *mut c_void) -> *mut c_void { 88 unsafe { syscall!(SYS_BRK, addr) as *mut c_void } 89 } 90 91 fn chdir(path: &CStr) -> c_int { 92 e(unsafe { syscall!(SYS_CHDIR, path.as_ptr()) }) as c_int 93 } 94 95 fn chmod(path: &CStr, mode: mode_t) -> c_int { 96 // e(unsafe { syscall!(FCHMODAT, AT_FDCWD, path.as_ptr(), mode, 0) }) as c_int 97 return 0; 98 } 99 100 fn chown(path: &CStr, owner: uid_t, group: gid_t) -> c_int { 101 // e(unsafe { 102 // syscall!( 103 // FCHOWNAT, 104 // AT_FDCWD, 105 // path.as_ptr(), 106 // owner as u32, 107 // group as u32 108 // ) 109 // }) as c_int 110 return 0; 111 } 112 113 fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int { 114 // e(unsafe { syscall!(CLOCK_GETTIME, clk_id, tp) }) as c_int 115 // unimplemented!() 116 return -ENOSYS; 117 } 118 119 fn close(fildes: c_int) -> c_int { 120 e(unsafe { syscall!(SYS_CLOSE, fildes) }) as c_int 121 } 122 123 fn dup(fildes: c_int) -> c_int { 124 e(unsafe { syscall!(SYS_DUP, fildes) }) as c_int 125 } 126 127 fn dup2(fildes: c_int, fildes2: c_int) -> c_int { 128 e(unsafe { syscall!(SYS_DUP2, fildes, fildes2) }) as c_int 129 } 130 131 unsafe fn execve(path: &CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int { 132 e(syscall!(SYS_EXECVE, path.as_ptr(), argv, envp)) as c_int 133 } 134 135 fn exit(status: c_int) -> ! { 136 unsafe { 137 syscall!(SYS_EXIT, status); 138 } 139 loop {} 140 } 141 142 fn fchdir(fildes: c_int) -> c_int { 143 // e(unsafe { syscall!(FCHDIR, fildes) }) as c_int 144 unimplemented!() 145 } 146 147 fn fchmod(fildes: c_int, mode: mode_t) -> c_int { 148 // e(unsafe { syscall!(FCHMOD, fildes, mode) }) as c_int 149 return 0; 150 } 151 152 fn fchown(fildes: c_int, owner: uid_t, group: gid_t) -> c_int { 153 // e(unsafe { syscall!(FCHOWN, fildes, owner, group) }) as c_int 154 return 0; 155 } 156 157 fn flock(fd: c_int, operation: c_int) -> c_int { 158 // e(unsafe { syscall!(FLOCK, fd, operation) }) as c_int 159 return 0; 160 } 161 162 fn fstat(fildes: c_int, buf: *mut stat) -> c_int { 163 // let empty = b"\0"; 164 // let empty_ptr = empty.as_ptr() as *const c_char; 165 // e(unsafe { syscall!(NEWFSTATAT, fildes, empty_ptr, buf, AT_EMPTY_PATH) }) as c_int 166 // unimplemented!() 167 e(unsafe { syscall!(SYS_FSTAT, fildes, buf) }) as c_int 168 } 169 170 fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int { 171 // let mut kbuf = linux_statfs::default(); 172 // let kbuf_ptr = &mut kbuf as *mut linux_statfs; 173 // let res = e(unsafe { syscall!(FSTATFS, fildes, kbuf_ptr) }) as c_int; 174 // if res == 0 { 175 // unsafe { 176 // if !buf.is_null() { 177 // (*buf).f_bsize = kbuf.f_bsize as c_ulong; 178 // (*buf).f_frsize = if kbuf.f_frsize != 0 { 179 // kbuf.f_frsize 180 // } else { 181 // kbuf.f_bsize 182 // } as c_ulong; 183 // (*buf).f_blocks = kbuf.f_blocks; 184 // (*buf).f_bfree = kbuf.f_bfree; 185 // (*buf).f_bavail = kbuf.f_bavail; 186 // (*buf).f_files = kbuf.f_files; 187 // (*buf).f_ffree = kbuf.f_ffree; 188 // (*buf).f_favail = kbuf.f_ffree; 189 // (*buf).f_fsid = kbuf.f_fsid as c_ulong; 190 // (*buf).f_flag = kbuf.f_flags as c_ulong; 191 // (*buf).f_namemax = kbuf.f_namelen as c_ulong; 192 // } 193 // } 194 // } 195 // res 196 197 unimplemented!() 198 } 199 200 fn fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int { 201 // e(unsafe { syscall!(FCNTL, fildes, cmd, arg) }) as c_int 202 unimplemented!() 203 } 204 205 fn fork() -> pid_t { 206 // e(unsafe { syscall!(CLONE, SIGCHLD, 0, 0, 0, 0) }) as pid_t 207 e(unsafe { syscall!(SYS_FORK) }) as pid_t 208 } 209 210 fn fpath(fildes: c_int, out: &mut [u8]) -> ssize_t { 211 // let mut proc_path = b"/proc/self/fd/".to_vec(); 212 // write!(proc_path, "{}", fildes).unwrap(); 213 // proc_path.push(0); 214 215 // Self::readlink(CStr::from_bytes_with_nul(&proc_path).unwrap(), out) 216 unimplemented!() 217 } 218 219 fn fsync(fildes: c_int) -> c_int { 220 // e(unsafe { syscall!(FSYNC, fildes) }) as c_int 221 return 0; 222 } 223 224 fn ftruncate(fildes: c_int, length: off_t) -> c_int { 225 // e(unsafe { syscall!(FTRUNCATE, fildes, length) }) as c_int 226 unimplemented!() 227 } 228 229 fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> c_int { 230 // unsafe { syscall!(FUTEX, addr, op, val, val2, 0, 0) as c_int } 231 unimplemented!() 232 } 233 234 fn futimens(fd: c_int, times: *const timespec) -> c_int { 235 // e(unsafe { syscall!(UTIMENSAT, fd, ptr::null::<c_char>(), times, 0) }) as c_int 236 unimplemented!() 237 } 238 239 fn utimens(path: &CStr, times: *const timespec) -> c_int { 240 // e(unsafe { syscall!(UTIMENSAT, AT_FDCWD, path.as_ptr(), times, 0) }) as c_int 241 unimplemented!() 242 } 243 244 fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char { 245 // if e(unsafe { syscall!(GETCWD, buf, size) }) == !0 { 246 // ptr::null_mut() 247 // } else { 248 // buf 249 // } 250 unimplemented!() 251 } 252 253 fn getdents(fd: c_int, dirents: *mut dirent, bytes: usize) -> c_int { 254 unsafe { syscall!(SYS_GET_DENTS, fd, dirents, bytes) as c_int } 255 } 256 257 fn getegid() -> gid_t { 258 // e(unsafe { syscall!(GETEGID) }) as gid_t 259 return 0; 260 } 261 262 fn geteuid() -> uid_t { 263 // e(unsafe { syscall!(GETEUID) }) as uid_t 264 return 0; 265 } 266 267 fn getgid() -> gid_t { 268 // e(unsafe { syscall!(GETGID) }) as gid_t 269 return 0; 270 } 271 272 fn getpagesize() -> usize { 273 // 4096 274 1024 * 1024 * 2 275 } 276 277 fn getpgid(pid: pid_t) -> pid_t { 278 // e(unsafe { syscall!(GETPGID, pid) }) as pid_t 279 return 0; 280 } 281 282 fn getpid() -> pid_t { 283 e(unsafe { syscall!(SYS_GETPID) }) as pid_t 284 } 285 286 fn getppid() -> pid_t { 287 // e(unsafe { syscall!(GETPPID) }) as pid_t 288 return 0; 289 } 290 291 fn getrandom(buf: &mut [u8], flags: c_uint) -> ssize_t { 292 // e(unsafe { syscall!(GETRANDOM, buf.as_mut_ptr(), buf.len(), flags) }) as ssize_t 293 unimplemented!() 294 } 295 296 unsafe fn getrlimit(resource: c_int, rlim: *mut rlimit) -> c_int { 297 // e(syscall!(GETRLIMIT, resource, rlim)) as c_int 298 unimplemented!() 299 } 300 301 fn getsid(pid: pid_t) -> pid_t { 302 // e(unsafe { syscall!(GETSID, pid) }) as pid_t 303 return 0; 304 } 305 306 fn gettid() -> pid_t { 307 // e(unsafe { syscall!(GETTID) }) as pid_t 308 return Self::getpid(); 309 } 310 311 fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int { 312 e(unsafe { syscall!(SYS_GETTIMEOFDAY, tp, tzp) }) as c_int 313 } 314 315 fn getuid() -> uid_t { 316 // e(unsafe { syscall!(GETUID) }) as uid_t 317 return 0; 318 } 319 320 fn lchown(path: &CStr, owner: uid_t, group: gid_t) -> c_int { 321 // e(unsafe { syscall!(LCHOWN, path.as_ptr(), owner, group) }) as c_int 322 return 0; 323 } 324 325 fn link(path1: &CStr, path2: &CStr) -> c_int { 326 // e(unsafe { 327 // syscall!( 328 // LINKAT, 329 // AT_FDCWD, 330 // path1.as_ptr(), 331 // AT_FDCWD, 332 // path2.as_ptr(), 333 // 0 334 // ) 335 // }) as c_int 336 unimplemented!() 337 } 338 339 fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> off_t { 340 e(unsafe { syscall!(SYS_LSEEK, fildes, offset, whence) }) as off_t 341 } 342 343 fn mkdir(path: &CStr, mode: mode_t) -> c_int { 344 // e(unsafe { syscall!(MKDIRAT, AT_FDCWD, path.as_ptr(), mode) }) as c_int 345 e(unsafe { syscall!(SYS_MKDIR, path.as_ptr(), mode) }) as c_int 346 } 347 348 fn mkfifo(path: &CStr, mode: mode_t) -> c_int { 349 // e(unsafe { syscall!(MKNODAT, AT_FDCWD, path.as_ptr(), mode | S_IFIFO, 0) }) as c_int 350 unimplemented!() 351 } 352 353 unsafe fn mlock(addr: *const c_void, len: usize) -> c_int { 354 // e(syscall!(MLOCK, addr, len)) as c_int 355 unimplemented!() 356 } 357 358 fn mlockall(flags: c_int) -> c_int { 359 // e(unsafe { syscall!(MLOCKALL, flags) }) as c_int 360 unimplemented!() 361 } 362 363 unsafe fn mmap( 364 addr: *mut c_void, 365 len: usize, 366 prot: c_int, 367 flags: c_int, 368 fildes: c_int, 369 off: off_t, 370 ) -> *mut c_void { 371 e(syscall!(SYS_MMAP, addr, len, prot, flags, fildes, off)) as *mut c_void 372 } 373 374 unsafe fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> c_int { 375 e(syscall!(SYS_MPROTECT, addr, len, prot)) as c_int 376 } 377 378 unsafe fn msync(addr: *mut c_void, len: usize, flags: c_int) -> c_int { 379 // e(syscall!(MSYNC, addr, len, flags)) as c_int 380 unimplemented!() 381 } 382 383 unsafe fn munlock(addr: *const c_void, len: usize) -> c_int { 384 // e(syscall!(MUNLOCK, addr, len)) as c_int 385 unimplemented!() 386 } 387 388 fn munlockall() -> c_int { 389 // e(unsafe { syscall!(MUNLOCKALL) }) as c_int 390 unimplemented!() 391 } 392 393 unsafe fn munmap(addr: *mut c_void, len: usize) -> c_int { 394 e(syscall!(SYS_MUNMAP, addr, len)) as c_int 395 } 396 397 fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int { 398 e(unsafe { syscall!(SYS_NANOSLEEP, rqtp, rmtp) }) as c_int 399 } 400 401 fn open(path: &CStr, oflag: c_int, mode: mode_t) -> c_int { 402 e(unsafe { syscall!(SYS_OPEN, path.as_ptr(), oflag, mode) }) as c_int 403 } 404 405 fn pipe2(fildes: &mut [c_int], flags: c_int) -> c_int { 406 // e(unsafe { syscall!(PIPE2, fildes.as_mut_ptr(), flags) }) as c_int 407 408 //since dragonos hasn't implemented pipe2 system call yet. We use a seperate pipe function instead of a special type of pipe2 function 409 if flags == 0 { 410 e(unsafe { syscall!(SYS_PIPE, fildes.as_mut_ptr()) }) as c_int 411 } else { 412 unimplemented!() 413 } 414 } 415 416 #[cfg(target_arch = "x86_64")] 417 unsafe fn pte_clone(stack: *mut usize) -> pid_t { 418 unimplemented!() 419 // let flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD; 420 // let pid; 421 // asm!(" 422 // # Call clone syscall 423 // syscall 424 425 // # Check if child or parent 426 // test rax, rax 427 // jnz 1f 428 429 // # Load registers 430 // pop rax 431 // pop rdi 432 // pop rsi 433 // pop rdx 434 // pop rcx 435 // pop r8 436 // pop r9 437 438 // # Call entry point 439 // call rax 440 441 // # Exit 442 // mov rax, 60 443 // xor rdi, rdi 444 // syscall 445 446 // # Invalid instruction on failure to exit 447 // ud2 448 449 // # Return PID if parent 450 // 1: 451 // ", 452 // inout("rax") SYS_CLONE => pid, 453 // inout("rdi") flags => _, 454 // inout("rsi") stack => _, 455 // inout("rdx") 0 => _, 456 // inout("r10") 0 => _, 457 // inout("r8") 0 => _, 458 // //TODO: out("rbx") _, 459 // out("rcx") _, 460 // out("r9") _, 461 // out("r11") _, 462 // out("r12") _, 463 // out("r13") _, 464 // out("r14") _, 465 // out("r15") _, 466 // ); 467 // e(pid) as pid_t 468 } 469 470 fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t { 471 e(unsafe { syscall!(SYS_READ, fildes, buf.as_mut_ptr(), buf.len()) }) as ssize_t 472 } 473 474 fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t { 475 unimplemented!() 476 // e(unsafe { 477 // syscall!( 478 // READLINKAT, 479 // AT_FDCWD, 480 // pathname.as_ptr(), 481 // out.as_mut_ptr(), 482 // out.len() 483 // ) 484 // }) as ssize_t 485 } 486 487 fn rename(old: &CStr, new: &CStr) -> c_int { 488 // e(unsafe { syscall!(RENAMEAT, AT_FDCWD, old.as_ptr(), AT_FDCWD, new.as_ptr()) }) as c_int 489 unimplemented!() 490 } 491 492 fn rmdir(path: &CStr) -> c_int { 493 e(unsafe { syscall!(SYS_UNLINK_AT, 0, path.as_ptr(), AT_REMOVEDIR) }) as c_int 494 } 495 496 fn sched_yield() -> c_int { 497 // e(unsafe { syscall!(SCHED_YIELD) }) as c_int 498 unimplemented!() 499 } 500 501 fn setpgid(pid: pid_t, pgid: pid_t) -> c_int { 502 // e(unsafe { syscall!(SETPGID, pid, pgid) }) as c_int 503 unimplemented!() 504 } 505 506 fn setregid(rgid: gid_t, egid: gid_t) -> c_int { 507 // e(unsafe { syscall!(SETREGID, rgid, egid) }) as c_int 508 unimplemented!() 509 } 510 511 fn setreuid(ruid: uid_t, euid: uid_t) -> c_int { 512 // e(unsafe { syscall!(SETREUID, ruid, euid) }) as c_int 513 unimplemented!() 514 } 515 516 fn symlink(path1: &CStr, path2: &CStr) -> c_int { 517 // e(unsafe { syscall!(SYMLINKAT, path1.as_ptr(), AT_FDCWD, path2.as_ptr()) }) as c_int 518 unimplemented!() 519 } 520 521 fn umask(mask: mode_t) -> mode_t { 522 // unsafe { syscall!(UMASK, mask) as mode_t } 523 unimplemented!() 524 } 525 526 fn uname(utsname: *mut utsname) -> c_int { 527 // e(unsafe { syscall!(UNAME, utsname, 0) }) as c_int 528 unimplemented!() 529 } 530 531 fn unlink(path: &CStr) -> c_int { 532 e(unsafe { syscall!(SYS_UNLINK_AT, AT_FDCWD, path.as_ptr(), 0) }) as c_int 533 } 534 535 fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t { 536 e(unsafe { syscall!(SYS_WAIT4, pid, stat_loc, options, 0) }) as pid_t 537 } 538 539 fn write(fildes: c_int, buf: &[u8]) -> ssize_t { 540 e(unsafe { syscall!(SYS_WRITE, fildes, buf.as_ptr(), buf.len()) }) as ssize_t 541 } 542 543 fn verify() -> bool { 544 // GETPID on Linux is 39, which does not exist on Redox 545 // e(unsafe { dsc::syscall5(dsc::nr::GETPID, !0, !0, !0, !0, !0) }) != !0 546 // unimplemented!() 547 return true; 548 } 549 } 550