liblinux++

Log | Files | Refs

commit 47b5c18d7c9d1e8f8872a16d4bb92e7cb994fff2
parent 41570a8a6d7d842b810b049cb067283df23bc050
Author: Henry Wilson <henry@henryandlizzy.uk>
Date:   Tue, 23 Dec 2025 00:09:32 +0000

strongly type syscall results

Diffstat:
Mcat.cpp | 15+++++++++------
Mlinux.hpp | 67+++++++++++++++++++++++++++++++++++++++++++++----------------------
Msleep.cpp | 2+-
Mx86_64.s | 10+++++-----
4 files changed, 60 insertions(+), 34 deletions(-)

diff --git a/cat.cpp b/cat.cpp @@ -1,17 +1,19 @@ #include "linux.hpp" -static void cat(filedesc fd) +static void cat(file fd) { static char buf[0x1000]; for (;;) { - int n = read(fd, buf, sizeof(buf)); - if (get_errno(n)) + auto res = read(fd, buf, sizeof(buf)); + if (!res) exit(2); + auto n = *res; if (n == 0) return; - if (write(stdout, buf, n) != n) + res = write(stdout, buf, n); + if (!res or *res != n) exit(3); } } @@ -20,9 +22,10 @@ int main(int argc, char* argv[]) { for (int i = 1; i < argc; ++i) { - filedesc fd = openat(AT_FDCWD, argv[i], 0, O_RDONLY); - if (!fd) + auto res = openat(AT_FDCWD, argv[i], 0, O_RDONLY); + if (!res) return 1; + auto fd = *res; cat(fd); close(fd); } diff --git a/linux.hpp b/linux.hpp @@ -60,29 +60,59 @@ struct span {} }; -struct filedesc +struct file { int num = -1; inline operator bool() const { return num >= 0; } }; -filedesc const stdin{0}; -filedesc const stdout{1}; -filedesc const stderr{2}; +file const stdin{0}; +file const stdout{1}; +file const stderr{2}; -__attribute__((noreturn)) +enum class errno_t : int16_t +{ + EPERM = -1, /* Operation not permitted */ + ENOENT = -2, /* No such file or directory */ + ESRCH = -3, /* No such process */ + EINTR = -4, /* Interrupted system call */ + + EINVAL = -22, /* Invalid argument */ +}; + +template <typename T> +struct syscall_result +{ + explicit operator bool() const { return val >= 0; } + T operator*() const + { + if (!*this) + __builtin_trap(); + return *reinterpret_cast<T const*>(&val); + } + errno_t err() const + { + if (*this) + __builtin_trap(); + return reinterpret_cast<errno_t>(static_cast<int16_t>(val)); + } +private: + int64_t val; +}; + +[[noreturn]] extern void exit(int error_code); -extern ssize_t read(filedesc fd, char* data, size_t count); -extern ssize_t read(filedesc fd, span<char> data); +extern syscall_result<size_t> read(file fd, char* data, size_t count); +extern syscall_result<size_t> read(file fd, span<char> data); -extern ssize_t write(filedesc fd, char const* data, size_t count); -extern ssize_t write(filedesc fd, span<char const> data); -extern ssize_t write(filedesc fd, span<span<char const> const> data); +extern syscall_result<size_t> write(file fd, char const* data, size_t count); +extern syscall_result<size_t> write(file fd, span<char const> data); +extern syscall_result<size_t> write(file fd, span<span<char const> const> data); -extern filedesc openat(int fd, char const* name, int flags, int mode); +extern syscall_result<file> openat(int fd, char const* name, int flags, int mode); -extern int close(filedesc fd); +extern syscall_result<void> close(file fd); struct linux_dirent64 { ino64_t d_ino; /* 64-bit inode number */ @@ -91,20 +121,13 @@ struct linux_dirent64 { unsigned char d_type; /* File type */ char d_name[]; /* Filename (null-terminated) */ }; -extern ssize_t getdents64(int fd, linux_dirent64 dirp[], size_t count); +extern syscall_result<ssize_t> getdents64(int fd, linux_dirent64 dirp[], size_t count); -extern intptr_t mmap(void* addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off); +extern syscall_result<void*> mmap(void* addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off); struct timespec { time_t tv_sec; /* Seconds */ uint32_t tv_nsec; /* Nanoseconds [0, 999'999'999] */ }; -extern int nanosleep(const timespec *duration, timespec */*_Nullable*/ rem); - -static unsigned get_errno(ssize_t ret) -{ - if (0 > ret && ret >= -0xFFFF) - return -ret; - return 0; -} +extern syscall_result<void> nanosleep(const timespec &duration, timespec */*_Nullable*/ rem); diff --git a/sleep.cpp b/sleep.cpp @@ -3,5 +3,5 @@ int main() { timespec duration{1, 0}; - nanosleep(&duration, nullptr); + nanosleep(duration, nullptr); } diff --git a/x86_64.s b/x86_64.s @@ -45,16 +45,16 @@ syscall6: ret extern read -extern_alias _Z4read8filedescPcy +extern_alias _Z4read4filePcy _syscall 0 syscall3 extern write -extern_alias _Z5write8filedescPKcy -extern_alias _Z5write8filedesc4spanIKcE +extern_alias _Z5write4filePKcy +extern_alias _Z5write4file4spanIKcE _syscall 1 syscall3 extern close -extern_alias _Z5close8filedesc +extern_alias _Z5close4file _syscall 3 syscall3 extern mmap @@ -65,7 +65,7 @@ extern_alias _Z5writei4spanIKS_IKcEE _syscall 20 syscall3 extern nanosleep -extern_alias _Z9nanosleepPK8timespecPS_ +extern_alias _Z9nanosleepRK8timespecPS_ _syscall 35 syscall3 extern exit