diff --git a/options/ansi/generic/file-io.cpp b/options/ansi/generic/file-io.cpp index 12877727..5c8320b6 100644 --- a/options/ansi/generic/file-io.cpp +++ b/options/ansi/generic/file-io.cpp @@ -423,8 +423,8 @@ size_t fread(void *__restrict buffer, size_t size, size_t count, size_t fwrite(const void *__restrict buffer, size_t size, size_t count, FILE *__restrict file_base) { auto file = static_cast(file_base); - __ensure(size); - __ensure(count); + if(!size || !count) + return 0; // Distinguish two cases here: If the object size is one, we perform byte-wise writes. // Otherwise, we try to write each object individually. diff --git a/options/ansi/generic/stdio-stubs.cpp b/options/ansi/generic/stdio-stubs.cpp index 7172bc42..760ed1f1 100644 --- a/options/ansi/generic/stdio-stubs.cpp +++ b/options/ansi/generic/stdio-stubs.cpp @@ -210,7 +210,7 @@ int vsnprintf(char *__restrict buffer, size_t max_size, LimitedPrinter p(buffer, max_size - 1); // frigg::infoLogger() << "printf(" << format << ")" << frigg::EndLog(); frigg::printf(p, format, args); - p.buffer[frigg::min(max_size, p.count)] = 0; + p.buffer[frigg::min(max_size - 1, p.count)] = 0; return p.count; } int vsprintf(char *__restrict buffer, const char *__restrict format, __gnuc_va_list args) { diff --git a/options/ansi/generic/stdlib-stubs.cpp b/options/ansi/generic/stdlib-stubs.cpp index 904b1e03..6db8ae3c 100644 --- a/options/ansi/generic/stdlib-stubs.cpp +++ b/options/ansi/generic/stdlib-stubs.cpp @@ -308,9 +308,13 @@ int mblen(const char *mb_chr, size_t max_size) { __ensure(!"Not implemented"); __builtin_unreachable(); } -int mbtowc(wchar_t *__restrict wc, const char *__restrict mb_chr, size_t max_size) { - __ensure(!"Not implemented"); - __builtin_unreachable(); +int mbtowc(wchar_t *__restrict wc, const char *__restrict mbs, size_t max_size) { + __ensure(wc); + __ensure(mbs); + __ensure(max_size); + __ensure(*mbs); + *wc = *mbs; + return 1; } int wctomb(char *mb_chr, wchar_t wc) { __ensure(!"Not implemented"); diff --git a/options/ansi/generic/wchar-stubs.cpp b/options/ansi/generic/wchar-stubs.cpp index 8eece680..a7d8baf0 100644 --- a/options/ansi/generic/wchar-stubs.cpp +++ b/options/ansi/generic/wchar-stubs.cpp @@ -5,7 +5,10 @@ #include int wcwidth(wchar_t) { - frigg::infoLogger() << "\e[35mmlibc: wcwidth() always returns 1\e[39m" << frigg::endLog; + static bool warned = false; + if(!warned) + frigg::infoLogger() << "\e[35mmlibc: wcwidth() always returns 1\e[39m" << frigg::endLog; + warned = true; return 1; } diff --git a/options/posix/generic/sys-select-stubs.cpp b/options/posix/generic/sys-select-stubs.cpp index 98c68f5a..e4a819d4 100644 --- a/options/posix/generic/sys-select-stubs.cpp +++ b/options/posix/generic/sys-select-stubs.cpp @@ -25,8 +25,6 @@ void FD_ZERO(fd_set *set) { int select(int num_fds, fd_set *__restrict read_set, fd_set *__restrict write_set, fd_set *__restrict except_set, struct timeval *__restrict timeout) { - __ensure(!timeout); - // TODO: Do not keep errors from epoll (?). int fd = epoll_create1(0); if(fd == -1) @@ -52,7 +50,8 @@ int select(int num_fds, fd_set *__restrict read_set, fd_set *__restrict write_se } struct epoll_event evnts[16]; - int n = epoll_wait(fd, evnts, 16, -1); + int n = epoll_wait(fd, evnts, 16, + timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 10) : -1); if(n == -1) return -1; diff --git a/sysdeps/managarm/generic/ensure.cpp b/sysdeps/managarm/generic/ensure.cpp index 1918053e..b3f4dde3 100644 --- a/sysdeps/managarm/generic/ensure.cpp +++ b/sysdeps/managarm/generic/ensure.cpp @@ -19,6 +19,13 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line, abort(); } +void __frigg_assert_fail(const char *assertion, const char *file, unsigned int line, + const char *function) { + frigg::panicLogger() << "In function " << function + << ", file " << file << ":" << line << "\n" + << "__ensure(" << assertion << ") failed" << frigg::endLog; +} + void __ensure_fail(const char *assertion, const char *file, unsigned int line, const char *function) { frigg::panicLogger() << "In function " << function diff --git a/sysdeps/managarm/generic/entry.cpp b/sysdeps/managarm/generic/entry.cpp index 3dd06050..7d7ceeb8 100644 --- a/sysdeps/managarm/generic/entry.cpp +++ b/sysdeps/managarm/generic/entry.cpp @@ -22,6 +22,8 @@ extern "C" uintptr_t *__dlapi_entrystack(); // declared in posix-pipe.hpp thread_local Queue globalQueue; +void *__mlibc_clk_tracker_page; + namespace { thread_local HelHandle *cachedFileTable; @@ -33,7 +35,8 @@ namespace { void actuallyCacheInfos() { HelError error; - asm volatile ("syscall" : "=D"(error), "=S"(cachedFileTable) : "0"(kHelCallSuper + 1)); + asm volatile ("syscall" : "=D"(error), "=c"(__mlibc_clk_tracker_page), + "=S"(cachedFileTable) : "0"(kHelCallSuper + 1)); HEL_CHECK(error); } } diff --git a/sysdeps/managarm/generic/file.cpp b/sysdeps/managarm/generic/file.cpp index 2acc3d54..9b7faf48 100644 --- a/sysdeps/managarm/generic/file.cpp +++ b/sysdeps/managarm/generic/file.cpp @@ -2159,6 +2159,9 @@ int sys_open(const char *path, int flags, int *fd) { if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { errno = ENOENT; return -1; + }else if(resp.error() == managarm::posix::Errors::ALREADY_EXISTS) { + errno = EEXIST; + return -1; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *fd = resp.fd(); diff --git a/sysdeps/managarm/generic/time.cpp b/sysdeps/managarm/generic/time.cpp index 22363397..60d8b96a 100644 --- a/sysdeps/managarm/generic/time.cpp +++ b/sysdeps/managarm/generic/time.cpp @@ -7,8 +7,20 @@ #include #include #include +#include +#include #include +struct TrackerPage { + uint64_t seqlock; + int32_t state; + int32_t padding; + int64_t refClock; + int64_t baseRealtime; +}; + +extern TrackerPage *__mlibc_clk_tracker_page; + namespace mlibc { int sys_clock_get(int clock, time_t *secs, long *nanos) { @@ -18,10 +30,13 @@ int sys_clock_get(int clock, time_t *secs, long *nanos) { *secs = tick / 1000000000; *nanos = tick % 1000000000; }else if(clock == CLOCK_REALTIME) { - frigg::infoLogger() << "\e[31mmlibc: clock_gettime does not support CLOCK_REALTIME" - "\e[39m" << frigg::endLog; + cacheFileTable(); + uint64_t tick; HEL_CHECK(helGetClock(&tick)); + __ensure(tick >= __mlibc_clk_tracker_page->refClock); // TODO: Respect the seqlock! + tick -= __mlibc_clk_tracker_page->refClock; + tick += __mlibc_clk_tracker_page->baseRealtime; *secs = tick / 1000000000; *nanos = tick % 1000000000; }else if(clock == CLOCK_PROCESS_CPUTIME_ID) {