#import "Basic"; #import "POSIX"; // This prototype is suposed to allow me to use the "open" posix syscall // that returns a file-descriptor (fd) that can then be used by the mmap // syscall that allows to map a file to memory. // // Syscall info: https://filippo.io/linux-syscall-table/ main :: () { //sys_exit(-1); size_stat, error_stat := sys_stat("./dummy"); print("> dymmy has stat size % widh error %\n", size_stat.st_size, error_stat); fd, error_open := sys_open("./dummy", O_RDONLY, O_RDONLY); print("> opened dummy with fd % and errno %\n", fd, error_open); if fd < 0 return; //LOOPER :: "\\|/-"; //idx := 0; //loop: string; //loop.count = 1; //for 0..3 { //sleep_milliseconds(1000); //loop.data = *LOOPER.data[idx]; //idx = (idx + 1) % LOOPER.count; //print("\rlooping %", loop); //} size_lseek, error_lseek := sys_lseek(fd, 0, SEEK_END); print("\r> dummy has lseek size % with error %\n", size_lseek, error_lseek); size_fstat, error_fstat := sys_fstat(fd); print("\r> dummy has fstat size % with error %\n", size_fstat.st_size, error_fstat); error_close := sys_close(fd); print("\r> close(%) with errno %\n", fd, error_close); print("---\n"); error :s64; fd, error = sys_open("./fail", O_RDONLY, O_RDONLY); print("$ open(fail) returned fd % and error %\n", fd, error); error = sys_close(456); print("$ close(456) returned error %\n", error); } sys_stat :: (path: string) -> result: stat_t, error: s64{ print("\r# sys_stat\n"); #if OS == .LINUX { SYS_STAT :: 4; stats: stat_t = ---; result: s64 = ---; #if CPU == .X64 { print("\r# LINUX:ASM\n"); path_p: *s8 = xx path.data; stats_p := *stats; #asm SYSCALL_SYSRET { mov rax: gpr === a, SYS_STAT; mov rdi: gpr === di, path_p; mov rsi: gpr === si, stats_p; syscall rcx: gpr === c, // Implicitly used by syscall to store RIP r11: gpr === 11, // Implicitly used by syscall to store RFLAGS rax, rdi, rsi; mov result, rax; } if result < 0 return .{}, -result; // Error. else return stats, 0; // OK. } else { print("\r# LINUX:LIBC\n"); path_p: *s8 = xx path.data; error := syscall(SYS_STAT, path_p, *stats); if error < 0 return .{}, errno(); // Error. else return stats, 0; // OK. } } else { print("TODO Implement this\n"); // TODO Implement this. } } sys_fstat :: (file_descriptor: s64) -> result: stat_t, error: s64{ print("\r# sys_fstat\n"); #if OS == .LINUX { SYS_FSTAT :: 5; stats: stat_t = ---; stats_p := *stats; result: s64 = ---; #if CPU == .X64 { print("\r# LINUX:ASM\n"); #asm SYSCALL_SYSRET { mov rax: gpr === a, SYS_FSTAT; mov rdi: gpr === di, file_descriptor; mov rsi: gpr === si, stats_p; syscall rcx: gpr === c, // Implicitly used by syscall to store RIP r11: gpr === 11, // Implicitly used by syscall to store RFLAGS rax, rdi, rsi; mov result, rax; } if result < 0 return .{}, -result; // Error. else return stats, 0; // OK. } else { print("\r# LINUX:LIBC\n"); error := syscall(SYS_FSTAT, file_descriptor, *result); if error < 0 return .{}, errno(); // Error. else return stats, 0; // OK. } } else { print("TODO Implement this\n"); // TODO Implement this. } } sys_lseek :: (file_descriptor: s64, offset: s64, whence: s64) -> offset_location: s64, error: s64 { print("\r# sys_lseek\n"); #if OS == .LINUX { SYS_LSEEK :: 8; result: s64 = ---; #if CPU == .X64 { print("\r# LINUX:ASM\n"); #asm SYSCALL_SYSRET { mov rax: gpr === a, SYS_LSEEK; mov rdi: gpr === di, file_descriptor; mov rsi: gpr === si, offset; mov rdx: gpr === d, whence; //syscall rcx, r11, rax, rdi, rsi, rdx; // TODO Cleanup? syscall rcx: gpr === c, // Implicitly used by syscall to store RIP r11: gpr === 11, // Implicitly used by syscall to store RFLAGS rax, rdi, rsi, rdx; mov result, rax; } if result < 0 return -1, -result; // Error. else return result, 0; // OK. } else { print("\r# LINUX:LIBC\n"); result = syscall(SYS_LSEEK, file_descriptor, offset, whence); if result < 0 return -1, errno(); // Error. else return result, 0; // OK. } } else { print("TODO Implement this\n"); // TODO Implement this. } } sys_open :: (path: string, flags: s64, mode: s64) -> file_descriptor: s64, error: s64 { print("\r# sys_open\n"); #if OS == .LINUX { SYS_OPEN :: 2; data: *s8 = xx path.data; result: s64 = ---; #if CPU == .X64 { print("\r# LINUX:ASM\n"); #asm SYSCALL_SYSRET { mov rax: gpr === a, SYS_OPEN; mov rdi: gpr === di, data; mov rsi: gpr === si, flags; mov rdx: gpr === d, mode; // TODO Is this really used? //syscall rcx, r11, rax, rdi, rsi, rdx; // TODO Cleanup? syscall rcx: gpr === c, // Implicitly used by syscall to store RIP r11: gpr === 11, // Implicitly used by syscall to store RFLAGS rax, rdi, rsi, rdx; mov result, rax; } if result < 0 return -1, -result; // Error. else return result, 0; // OK. } else { print("\r# LINUX:LIBC\n"); result = syscall(SYS_OPEN, data, flags, mode); if result < 0 return -1, errno(); // Error. else return result, 0; // OK. } } else { print("TODO Implement this\n"); // TODO Implement this. } } sys_close :: (file_descriptor: s64) -> error: s64 { print("\r# sys_close\n"); #if OS == .LINUX { SYS_CLOSE :: 3; result: s64 = ---; #if CPU == .X64 { print("\r# LINUX:ASM\n"); #asm SYSCALL_SYSRET { mov rax: gpr === a, SYS_CLOSE; mov rdi: gpr === di, file_descriptor; syscall rcx: gpr === c, // Implicitly used by syscall to store RIP r11: gpr === 11, // Implicitly used by syscall to store RFLAGS rax, rdi; mov result, rax; } return ifx result < 0 then -result else 0; } else { print("\r# LINUX:LIBC\n"); result = syscall(SYS_CLOSE, file_descriptor); return ifx result < 0 then errno() else 0; } } else { print("TODO Implement this\n"); // TODO Implement this. } }