commit 47b5c18d7c9d1e8f8872a16d4bb92e7cb994fff2
parent 41570a8a6d7d842b810b049cb067283df23bc050
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Tue, 23 Dec 2025 00:09:32 +0000
strongly type syscall results
Diffstat:
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