summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibC
diff options
context:
space:
mode:
authorGunnar Beutner <gbeutner@serenityos.org>2021-05-24 16:43:12 +0200
committerAndreas Kling <kling@serenityos.org>2021-05-25 17:36:02 +0200
commitc81b3e1ee3c005f1703f8a9e47b53b3ed836fc32 (patch)
tree1aa0cbd7edf718bfcf9dbf4c7eada0f67a0f48bc /Userland/Libraries/LibC
parent3526fbbc5f548935efc79bad3ce5d396a6d58e3b (diff)
downloadserenity-c81b3e1ee3c005f1703f8a9e47b53b3ed836fc32.zip
LibC: Implement strerror_r()
This implements the XSI-compliant version of strerror_r() - as opposed to the GNU-specific variant. The function explicitly saves errno so as to not accidentally change it with one of the calls to other functions.
Diffstat (limited to 'Userland/Libraries/LibC')
-rw-r--r--Userland/Libraries/LibC/string.cpp20
-rw-r--r--Userland/Libraries/LibC/string.h1
2 files changed, 21 insertions, 0 deletions
diff --git a/Userland/Libraries/LibC/string.cpp b/Userland/Libraries/LibC/string.cpp
index db74946ae8..3847afb6dc 100644
--- a/Userland/Libraries/LibC/string.cpp
+++ b/Userland/Libraries/LibC/string.cpp
@@ -354,6 +354,26 @@ const char* const sys_errlist[] = {
int sys_nerr = EMAXERRNO;
+int strerror_r(int errnum, char* buf, size_t buflen)
+{
+ auto saved_errno = errno;
+ if (errnum >= EMAXERRNO) {
+ auto rc = strlcpy(buf, "unknown error", buflen);
+ if (rc >= buflen)
+ dbgln("strerror_r(): Invalid error number '{}' specified and the output buffer is too small.", errnum);
+ errno = saved_errno;
+ return EINVAL;
+ }
+ auto text = strerror(errnum);
+ auto rc = strlcpy(buf, text, buflen);
+ if (rc >= buflen) {
+ errno = saved_errno;
+ return ERANGE;
+ }
+ errno = saved_errno;
+ return 0;
+}
+
char* strerror(int errnum)
{
if (errnum < 0 || errnum >= EMAXERRNO) {
diff --git a/Userland/Libraries/LibC/string.h b/Userland/Libraries/LibC/string.h
index beaf594a33..d7010ef6ac 100644
--- a/Userland/Libraries/LibC/string.h
+++ b/Userland/Libraries/LibC/string.h
@@ -43,6 +43,7 @@ char* strncat(char* dest, const char* src, size_t);
size_t strspn(const char*, const char* accept);
size_t strcspn(const char*, const char* reject);
+int strerror_r(int, char*, size_t);
char* strerror(int errnum);
char* strsignal(int signum);
char* strpbrk(const char*, const char* accept);