[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/2] libc: Implementiere strerror_r()



+ Eigentlich ist das relativ einfach, weil strerror() schon snprintf()
  benutzt.  Leider gibt es aber grundsätzlich zwei Versionen von
  strerror_r(), und die Manpage sagt im Prinzip, dass per default die
  XSI-Variante benutzt wird, aber bei _GNU_SOURCE dann die GNU-Variante.
  Das klingt, als sollten wir am besten beide anbieten, und das macht
  das ganze dann leider komplizierter, als es nötig sein sollte.

Signed-off-by: Hanna Reitz <hanna.reitz@xxxxxxxxxxx>
---
 src/include/string.h             |  6 +++++
 src/modules/lib/posix/strerror.c | 40 ++++++++++++++++++++++++++++----
 2 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/src/include/string.h b/src/include/string.h
index c7a69831..db244ac3 100644
--- a/src/include/string.h
+++ b/src/include/string.h
@@ -83,6 +83,12 @@ char* strndup(const char* str, size_t n);
 char *strpbrk(const char *s1, const char *s2);
 
 char* strerror(int error_code);
+#if (_POSIX_C_SOURCE >= 200112l) && !defined(_GNU_SOURCE)
+int _xsi_strerror_r(int error_code, char* buf, size_t buflen);
+#define strerror_r _xsi_strerror_r
+#else
+char* strerror_r(int error_code, char* buf, size_t buflen);
+#endif
 
 int strcasecmp(const char* s1, const char* s2);
 int strncasecmp(const char* s1, const char* s2, size_t n);
diff --git a/src/modules/lib/posix/strerror.c b/src/modules/lib/posix/strerror.c
index d73b3a7d..28a0a8a4 100644
--- a/src/modules/lib/posix/strerror.c
+++ b/src/modules/lib/posix/strerror.c
@@ -31,6 +31,12 @@
 #include <stdio.h>
 #include <errno.h>
 
+// string.h koennte dieses Macro definiert haben, aber hier koennen wir
+// das nicht brauchen.
+#ifdef strerror_r
+#undef strerror_r
+#endif
+
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
 
 static char* error_messages[] = {
@@ -61,22 +67,46 @@ static char* error_messages[] = {
  * TODO: ATM nur stub
  *
  * @param error_code Fehlernummer
+ * @param buf Puffer, in dem die Fehlermeldung gespeichert wird
+ * @param buflen Laenge des Puffers
  * 
- * @return Pointer auf internen Buffer mit Fehlermeldung
+ * @return 0 bei Erfolg, sonst errno (errno wird ebenfalls gesetzt)
  */
-char* strerror(int error_code)
+int _xsi_strerror_r(int error_code, char* buf, size_t buflen)
 {
-    static char error_message[64];
+    int old_errno = errno;
+    int printf_len;
+    int ret = 0;
 
     if (error_code >= 0 && error_code < ARRAY_SIZE(error_messages) &&
         error_messages[error_code] != NULL)
     {
-        snprintf(error_message, sizeof(error_message),
+        printf_len = snprintf(buf, buflen,
             "%s (%d)", error_messages[error_code], error_code);
+        errno = old_errno; // errno nicht veraendern
     } else {
-        snprintf(error_message, sizeof(error_message),
+        printf_len = snprintf(buf, buflen,
             "Unbekannter Fehler %d", error_code);
+        ret = errno = EINVAL;
     }
+
+    if (printf_len >= buflen) {
+        ret = errno = ERANGE;
+    }
+
+    return ret;
+}
+
+char* strerror(int error_code)
+{
+    static char error_message[64];
+    _xsi_strerror_r(error_code, error_message, sizeof(error_message));
     return error_message;
 }
 
+char* strerror_r(int error_code, char* buf, size_t buflen)
+{
+    _xsi_strerror_r(error_code, buf, buflen);
+    return buf;
+}
+
-- 
2.31.0