xref: /relibc/src/platform/dragonos/mod.rs (revision fd22fbbabfdcb99dacbd9e8317399ad91050d6cd)
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