From 0b4574b53e7798c6197a2e6af6300a7e64ad7d06 Mon Sep 17 00:00:00 2001 From: Timerix Date: Fri, 21 Nov 2025 13:15:17 +0500 Subject: [PATCH] replaced strerror() with thread-safe strerror_malloc() --- include/tlibc/collections/Array.h | 2 +- include/tlibc/errors.h | 5 +++-- include/tlibc/string/cstr.h | 3 +++ src/errors.c | 2 +- src/filesystem/dir.c | 7 ++++++- src/filesystem/file.c | 29 ++++++++++++++++++++--------- src/string/cstr.c | 18 ++++++++++++++++++ src/time.c | 18 ++++++++++-------- 8 files changed, 62 insertions(+), 22 deletions(-) diff --git a/include/tlibc/collections/Array.h b/include/tlibc/collections/Array.h index 53022c9..737c184 100755 --- a/include/tlibc/collections/Array.h +++ b/include/tlibc/collections/Array.h @@ -20,7 +20,7 @@ typedef struct Array_ { static inline Array_ Array_alloc_size(u32 size){ if(size == 0) return Array_null; - return Array_construct_size(size > 0 ? malloc(size) : NULL, size); + return Array_construct_size(malloc(size), size); } #define Array_realloc(SELF, T, COUNT) Array_realloc_size(SELF, (COUNT) * sizeof(T)) diff --git a/include/tlibc/errors.h b/include/tlibc/errors.h index 59709a2..ce7ec31 100755 --- a/include/tlibc/errors.h +++ b/include/tlibc/errors.h @@ -74,8 +74,9 @@ typedef struct Result_ { RESULT_ERROR_CODE(NONE, 0, MSG, IS_MSG_ON_HEAP); #define RESULT_ERROR_FMT(FORMAT, ARGS...) \ RESULT_ERROR_CODE_FMT(NONE, 0, FORMAT ,##ARGS) + #define RESULT_ERROR_ERRNO() \ - RESULT_ERROR_CODE(LIBC_ERRNO, errno, strerror(errno), false) + RESULT_ERROR_CODE(LIBC_ERRNO, errno, strerror_malloc(errno), true) #define RESULT_VOID (Result_){ .error = NULL, .u = 0 } #define RESULT_VALUE(FIELD, V) (Result_){ .error = NULL, .FIELD = V } @@ -122,7 +123,7 @@ typedef struct Result_ { #define try_stderrcode(CALL) do {\ int r = CALL;\ if(r != 0){\ - Return RESULT_ERROR_CODE(LIBC_ERRNO, r, strerror(r), false);\ + Return RESULT_ERROR_CODE(LIBC_ERRNO, r, strerror_malloc(r), true);\ }\ } while(0) diff --git a/include/tlibc/string/cstr.h b/include/tlibc/string/cstr.h index d0081e4..66be7c9 100755 --- a/include/tlibc/string/cstr.h +++ b/include/tlibc/string/cstr.h @@ -9,3 +9,6 @@ char* _vstrcat_malloc(u64 n, cstr str0, va_list args); char* sprintf_malloc(cstr format, ...) ATTRIBUTE_CHECK_FORMAT_PRINTF(1, 2); char* vsprintf_malloc(cstr format, va_list args); + +/// thread-safe version of strerror +char* strerror_malloc(int errcode); diff --git a/src/errors.c b/src/errors.c index 829a0fa..8458a58 100755 --- a/src/errors.c +++ b/src/errors.c @@ -50,7 +50,7 @@ str Error_toStr(Error* e){ void Error_printAndExit(Error* e){ str e_str = Error_toStr(e); - printfe("%s\n", e_str.data); + printfe("\n"FMT_str"\n", e_str.size, e_str.data); free(e_str.data); Error_free(e); exit(111); diff --git a/src/filesystem/dir.c b/src/filesystem/dir.c index c7207e5..6501438 100644 --- a/src/filesystem/dir.c +++ b/src/filesystem/dir.c @@ -37,7 +37,12 @@ Result(bool) dir_create(cstr path){ if(mkdir(path, 0777) == -1) #endif { - Return RESULT_ERROR_FMT("Can't create dicectory '%s': %s", path, strerror(errno)); + char* errno_s = strerror_malloc(errno); + ResultVar(void) err = RESULT_ERROR_FMT( + "Can't create dicectory '%s': %s", + path, errno_s); + free(errno_s); + Return err; } Return RESULT_VALUE(i, true); diff --git a/src/filesystem/file.c b/src/filesystem/file.c index 75b70f4..bc68cbf 100644 --- a/src/filesystem/file.c +++ b/src/filesystem/file.c @@ -25,21 +25,29 @@ bool file_exists(cstr path){ Result(FILE*) file_open(cstr file_name, cstr fopen_mode){ FILE* f = fopen(file_name, fopen_mode); if(f == NULL){ - return RESULT_ERROR_FMT( + char* errno_s = strerror_malloc(errno); + ResultVar(void) err = RESULT_ERROR_FMT( "Can't open (%s) file '%s': %s", - fopen_mode, file_name, strerror(errno)); + fopen_mode, file_name, errno_s); + free(errno_s); + return err; } return RESULT_VALUE(p, f); } Result(FILE*) file_openOrCreateReadWrite(cstr file_name){ - FILE* f = fopen(file_name, "rb+"); + cstr fopen_mode = "rb+"; + FILE* f = fopen(file_name, fopen_mode); if(f == NULL){ - f = fopen(file_name, "wb+"); + fopen_mode = "wb+"; + f = fopen(file_name, fopen_mode); if(f == NULL){ - return RESULT_ERROR_FMT( - "Can't create (%s) file: %s", - file_name, strerror(errno)); + char* errno_s = strerror_malloc(errno); + ResultVar(void) err = RESULT_ERROR_FMT( + "Can't open (%s) file '%s': %s", + fopen_mode, file_name, errno_s); + free(errno_s); + return err; } } return RESULT_VALUE(p, f); @@ -57,9 +65,12 @@ Result(i64) file_tellPos(FILE* f){ Result(void) file_seek(FILE* f, i64 offset, SeekOrigin origin){ if(IFWIN(_fseeki64, fseeko64)(f, offset, (int)origin) != 0){ - return RESULT_ERROR_FMT( + char* errno_s = strerror_malloc(errno); + ResultVar(void) err = RESULT_ERROR_FMT( "Can't seek (offset: "FMT_i64", origin: %i) in file: %s", - offset, origin, strerror(errno)); + offset, origin, errno_s); + free(errno_s); + return err; } return RESULT_VOID; } diff --git a/src/string/cstr.c b/src/string/cstr.c index 9ab8dd2..e70bda0 100755 --- a/src/string/cstr.c +++ b/src/string/cstr.c @@ -1,3 +1,9 @@ +// Enable POSIX 2004 definitions. +// Required to use strerror_r in ISO C. +#ifndef _XOPEN_SOURCE + #define _XOPEN_SOURCE 600 +#endif + #include "tlibc/string/cstr.h" char* cstr_copy(cstr self){ @@ -70,3 +76,15 @@ char* vsprintf_malloc(cstr format, va_list args){ } return buf; } + +#if defined(_WIN64) || defined(_WIN32) +#define portable_strerror_s(BUF, BUFSIZE, ERRCODE) strerror_s(BUF, BUFSIZE, ERRCODE) +#else +#define portable_strerror_s(BUF, BUFSIZE, ERRCODE) strerror_r(ERRCODE, BUF, BUFSIZE) +#endif +char* strerror_malloc(int errcode){ + const int buf_size = 256; + char* buf = malloc(buf_size); + portable_strerror_s(buf, buf_size, errcode); + return buf; +} diff --git a/src/time.c b/src/time.c index 53d5b11..13d8e7e 100644 --- a/src/time.c +++ b/src/time.c @@ -1,10 +1,7 @@ -// posix version definition to use clock_gettime +// Enable POSIX 2004 definitions. +// Required to use clock_gettime, localtime_r, gmtime_r in ISO C. #ifndef _XOPEN_SOURCE - #if __STDC_VERSION__ >= 199901L - #define _XOPEN_SOURCE 600 - #else - #define _XOPEN_SOURCE 500 - #endif + #define _XOPEN_SOURCE 600 #endif #include "tlibc/time.h" @@ -45,8 +42,13 @@ void sleepMsec(msec_t time){ sleepNsec(time * M); } -#define portable_localtime_s(time_t_ptr, tm_ptr) IFWIN(localtime_s(tm_ptr, time_t_ptr), localtime_r(time_t_ptr, tm_ptr)) -#define portable_gmtime_s(time_t_ptr, tm_ptr) IFWIN(gmtime_s(tm_ptr, time_t_ptr), gmtime_r(time_t_ptr, tm_ptr)) +#if defined(_WIN64) || defined(_WIN32) +#define portable_localtime_s(time_t_ptr, tm_ptr) localtime_s(tm_ptr, time_t_ptr) +#define portable_gmtime_s(time_t_ptr, tm_ptr) gmtime_s(tm_ptr, time_t_ptr) +#else +#define portable_localtime_s(time_t_ptr, tm_ptr) localtime_r(time_t_ptr, tm_ptr) +#define portable_gmtime_s(time_t_ptr, tm_ptr) gmtime_r(time_t_ptr, tm_ptr) +#endif void DateTime_get(DateTime* dt, bool utc_time){ time_t c_time = time(NULL);