#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); print("> open dummy\n"); 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, error_lseek := sys_lseek(fd, 0, SEEK_END); print("\r> dummy has size % with error %\n", size, error_lseek); 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_lseek :: (file_descriptor: s64, offset: s64, whence: s64) -> offset_location: s64, error: s64 { print("\r# sys_lseek\n"); #if OS == .WINDOWS { print("TODO Implement this\n"); // TODO Implement this. } else #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. } } } sys_open :: (path: string, flags: s64, mode: s64) -> file_descriptor: s64, error: s64 { print("\r# sys_open\n"); #if OS == .WINDOWS { print("TODO Implement this\n"); // TODO Implement this. } else #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. } } } sys_close :: (file_descriptor: s64) -> error: s64 { print("\r# sys_close\n"); #if OS == .WINDOWS { print("TODO Implement this\n"); // TODO Implement this. } else #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; } } }