liblinux++

A hosted C++ runtime without any libc.
git clone git://henryandlizzy.uk/liblinux++
Log | Files | Refs

commit 01f91fef9e95f76fa044f6fe4a92bcd8a5fb61dc
parent d9b07a955ad27b4143c3f34b18b1130957718d50
Author: Henry Wilson <henry@henryandlizzy.uk>
Date:   Fri,  9 Jan 2026 00:38:14 +0000

ls: fix repeated output

Diffstat:
Mlinux.hpp | 7+++++++
Mls.cpp | 38++++++++++++++++++++++++++------------
2 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/linux.hpp b/linux.hpp @@ -75,6 +75,10 @@ struct span { return begin() + size(); } + T& operator[](size_t n) + { + return ptr[n]; + } private: T* ptr = nullptr; size_t len = 0; @@ -172,6 +176,9 @@ struct [[gnu::packed]] linux_dirent64 { off64_t d_off; /* Not an offset; see getdents() */ unsigned short d_reclen; /* Size of this dirent */ unsigned char d_type; /* File type */ + + linux_dirent64* next() noexcept { return reinterpret_cast<linux_dirent64*>(reinterpret_cast<char*>(this) + d_reclen); } + char* name() noexcept { return reinterpret_cast<char*>(this) + sizeof(*this); } }; extern syscall_result<size_t> getdents64(file dir, span<char> buffer) noexcept; diff --git a/ls.cpp b/ls.cpp @@ -1,31 +1,45 @@ #include "linux.hpp" +template <typename T> +struct spanstack +{ + spanstack(span<T> st) : storage{st} {} + + bool empty() const noexcept { return not n; } + bool full() const noexcept { return n == storage.size(); } + span<T const> data() noexcept { return {(T const*)storage.begin(), n}; } + void push_back(T const& v) noexcept + { + assert(not full()); + storage[n++] = v; + } +private: + span<T> storage; + size_t n = 0; +}; + int main() { auto dir = openat(AT_FDCWD, ".", O_RDONLY, 0); assert(dir); alignas(linux_dirent64) char buf[256]; - span<char const> ios[sizeof(buf)/sizeof(linux_dirent64)]; + span<char const> ios_storage[sizeof(buf)/sizeof(linux_dirent64)]; for (;;) { - unsigned n_io = 0; + spanstack ios{span{ios_storage}}; auto res = getdents64(*dir, buf); - size_t n = *res; - - if (!n) + void* const end = buf + *res; + if (end == buf) break; - for (size_t i = 0; i + sizeof(linux_dirent64) < n;) + for (auto ent = reinterpret_cast<linux_dirent64*>(buf); ent != end; ent = ent->next()) { - auto e = reinterpret_cast<linux_dirent64*>(buf + i); - char* const name = buf + i + sizeof(linux_dirent64); + char* const name = ent->name(); size_t len = c_str{name}.length(); name[len++] = '\n'; - ios[n_io++] = span<char const>{name, len}; - i += e->d_reclen; - break; + ios.push_back({name, len}); } - *write(stdout, ios); + *write(stdout, ios.data()); } }