aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYang Tse <yangsita@gmail.com>2008-09-12 10:51:57 +0000
committerYang Tse <yangsita@gmail.com>2008-09-12 10:51:57 +0000
commitc3d1b07c455928de7497677b2da7ffa470a62fee (patch)
tree9fc63f2879f3d49c12b21c906fdc3c56b6737442
parent77bafd823b6e36586f483cbd459649774729357c (diff)
ensure that errno is not modified inside Curl_strerror()
-rw-r--r--lib/strerror.c72
1 files changed, 39 insertions, 33 deletions
diff --git a/lib/strerror.c b/lib/strerror.c
index f1d22e143..526187bb8 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -24,10 +24,11 @@
#include "setup.h"
#ifdef HAVE_STRERROR_R
-#if !defined(HAVE_POSIX_STRERROR_R) && !defined(HAVE_GLIBC_STRERROR_R)
-#error "you MUST have either POSIX or glibc strerror_r if strerror_r is found"
-#endif /* !POSIX && !glibc */
-#endif /* HAVE_STRERROR_R */
+# if (!defined(HAVE_POSIX_STRERROR_R) && !defined(HAVE_GLIBC_STRERROR_R)) || \
+ (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R))
+# error "strerror_r MUST be either POSIX-style or glibc-style"
+# endif
+#endif
#include <curl/curl.h>
#include <stdlib.h>
@@ -43,14 +44,6 @@
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
-#if defined(HAVE_STRERROR_R) && defined(HAVE_NO_STRERROR_R_DECL)
-#ifdef HAVE_POSIX_STRERROR_R
-/* seen on AIX 5100-02 gcc 2.9 */
-extern int strerror_r(int errnum, char *strerrbuf, size_t buflen);
-#else
-extern char *strerror_r(int errnum, char *buf, size_t buflen);
-#endif
-#endif
const char *
curl_easy_strerror(CURLcode error)
@@ -590,6 +583,7 @@ const char *Curl_strerror(struct connectdata *conn, int err)
{
char *buf, *p;
size_t max;
+ int old_errno = ERRNO;
DEBUGASSERT(conn);
DEBUGASSERT(err >= 0);
@@ -601,17 +595,15 @@ const char *Curl_strerror(struct connectdata *conn, int err)
#ifdef USE_WINSOCK
#ifdef _WIN32_WCE
- buf[0]=0;
{
wchar_t wbuf[256];
+ wbuf[0] = L'\0';
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL);
wcstombs(buf,wbuf,max);
}
-
#else
-
/* 'sys_nerr' is the maximum errno number, it is not widely portable */
if(err >= 0 && err < sys_nerr)
strncpy(buf, strerror(err), max);
@@ -622,34 +614,43 @@ const char *Curl_strerror(struct connectdata *conn, int err)
snprintf(buf, max, "Unknown error %d (%#x)", err, err);
}
#endif
+
#else /* not USE_WINSOCK coming up */
- /* These should be atomic and hopefully thread-safe */
-#ifdef HAVE_STRERROR_R
- /* There are two different APIs for strerror_r(). The POSIX and the GLIBC
- versions. */
-#ifdef HAVE_POSIX_STRERROR_R
- strerror_r(err, buf, max);
- /* this may set errno to ERANGE if insufficient storage was supplied via
- 'strerrbuf' and 'buflen' to contain the generated message string, or
- EINVAL if the value of 'errnum' is not a valid error number.*/
-#else
+#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R)
+ /*
+ * The POSIX-style strerror_r() may set errno to ERANGE if insufficient
+ * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated
+ * message string, or EINVAL if 'errnum' is not a valid error number.
+ */
+ if(0 != strerror_r(err, buf, max)) {
+ if('\0' == buf[0])
+ snprintf(buf, max, "Unknown error %d", err);
+ }
+#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
+ /*
+ * The glibc-style strerror_r() only *might* use the buffer we pass to
+ * the function, but it always returns the error message as a pointer,
+ * so we must copy that string unconditionally (if non-NULL).
+ */
{
- /* HAVE_GLIBC_STRERROR_R */
char buffer[256];
char *msg = strerror_r(err, buffer, sizeof(buffer));
- /* this version of strerror_r() only *might* use the buffer we pass to
- the function, but it always returns the error message as a pointer,
- so we must copy that string unconditionally (if non-NULL) */
if(msg)
strncpy(buf, msg, max);
else
snprintf(buf, max, "Unknown error %d", err);
}
-#endif /* end of HAVE_GLIBC_STRERROR_R */
-#else /* HAVE_STRERROR_R */
- strncpy(buf, strerror(err), max);
-#endif /* end of HAVE_STRERROR_R */
+#else
+ {
+ char *msg = strerror(err);
+ if(msg)
+ strncpy(buf, msg, max);
+ else
+ snprintf(buf, max, "Unknown error %d", err);
+ }
+#endif
+
#endif /* end of ! USE_WINSOCK */
buf[max] = '\0'; /* make sure the string is zero terminated */
@@ -659,6 +660,10 @@ const char *Curl_strerror(struct connectdata *conn, int err)
*p = '\0';
if((p = strrchr(buf,'\r')) != NULL && (p - buf) >= 1)
*p = '\0';
+
+ if(old_errno != ERRNO)
+ SET_ERRNO(old_errno);
+
return buf;
}
@@ -680,6 +685,7 @@ const char *Curl_idn_strerror (struct connectdata *conn, int err)
buf = conn->syserr_buf;
max = sizeof(conn->syserr_buf)-1;
+ *buf = '\0';
#ifndef CURL_DISABLE_VERBOSE_STRINGS
switch ((Idna_rc)err) {