summaryrefslogtreecommitdiff
path: root/src/libstrongswan/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/utils.c')
-rw-r--r--src/libstrongswan/utils.c99
1 files changed, 89 insertions, 10 deletions
diff --git a/src/libstrongswan/utils.c b/src/libstrongswan/utils.c
index f76245a19..d43a4bc2f 100644
--- a/src/libstrongswan/utils.c
+++ b/src/libstrongswan/utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 Tobias Brunner
+ * Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -25,6 +25,7 @@
#include <limits.h>
#include <dirent.h>
#include <time.h>
+#include <pthread.h>
#include "enum.h"
#include "debug.h"
@@ -194,6 +195,85 @@ bool mkdir_p(const char *path, mode_t mode)
return TRUE;
}
+
+/**
+ * The size of the thread-specific error buffer
+ */
+#define STRERROR_BUF_LEN 256
+
+/**
+ * Key to store thread-specific error buffer
+ */
+static pthread_key_t strerror_buf_key;
+
+/**
+ * Only initialize the key above once
+ */
+static pthread_once_t strerror_buf_key_once = PTHREAD_ONCE_INIT;
+
+/**
+ * Create the key used for the thread-specific error buffer
+ */
+static void create_strerror_buf_key()
+{
+ pthread_key_create(&strerror_buf_key, free);
+}
+
+/**
+ * Retrieve the error buffer assigned to the current thread (or create it)
+ */
+static inline char *get_strerror_buf()
+{
+ char *buf;
+
+ pthread_once(&strerror_buf_key_once, create_strerror_buf_key);
+ buf = pthread_getspecific(strerror_buf_key);
+ if (!buf)
+ {
+ buf = malloc(STRERROR_BUF_LEN);
+ pthread_setspecific(strerror_buf_key, buf);
+ }
+ return buf;
+}
+
+#ifdef HAVE_STRERROR_R
+/*
+ * Described in header.
+ */
+const char *safe_strerror(int errnum)
+{
+ char *buf = get_strerror_buf(), *msg;
+
+#ifdef STRERROR_R_CHAR_P
+ /* char* version which may or may not return the original buffer */
+ msg = strerror_r(errnum, buf, STRERROR_BUF_LEN);
+#else
+ /* int version returns 0 on success */
+ msg = strerror_r(errnum, buf, STRERROR_BUF_LEN) ? "Unknown error" : buf;
+#endif
+ return msg;
+}
+#else /* HAVE_STRERROR_R */
+/* we actually wan't to call strerror(3) below */
+#undef strerror
+/*
+ * Described in header.
+ */
+const char *safe_strerror(int errnum)
+{
+ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ char *buf = get_strerror_buf();
+
+ /* use a mutex to ensure calling strerror(3) is thread-safe */
+ pthread_mutex_lock(&mutex);
+ strncpy(buf, strerror(errnum), STRERROR_BUF_LEN);
+ pthread_mutex_unlock(&mutex);
+ buf[STRERROR_BUF_LEN - 1] = '\0';
+ return buf;
+}
+#endif /* HAVE_STRERROR_R */
+
+
#ifndef HAVE_CLOSEFROM
/**
* Described in header.
@@ -315,7 +395,6 @@ void nop()
}
#ifndef HAVE_GCC_ATOMIC_OPERATIONS
-#include <pthread.h>
/**
* We use a single mutex for all refcount variables.
@@ -371,7 +450,7 @@ _cas_impl(ptr, void*)
/**
* Described in header.
*/
-int time_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args)
{
static const char* months[] = {
@@ -384,7 +463,7 @@ int time_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
if (time == UNDEFINED_TIME)
{
- return print_in_hook(dst, len, "--- -- --:--:--%s----",
+ return print_in_hook(data, "--- -- --:--:--%s----",
utc ? " UTC " : " ");
}
if (utc)
@@ -395,7 +474,7 @@ int time_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
{
localtime_r(time, &t);
}
- return print_in_hook(dst, len, "%s %02d %02d:%02d:%02d%s%04d",
+ return print_in_hook(data, "%s %02d %02d:%02d:%02d%s%04d",
months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900);
}
@@ -403,7 +482,7 @@ int time_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
/**
* Described in header.
*/
-int time_delta_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args)
{
char* unit = "second";
@@ -426,7 +505,7 @@ int time_delta_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
delta /= 60;
unit = "minute";
}
- return print_in_hook(dst, len, "%" PRIu64 " %s%s", delta, unit,
+ return print_in_hook(data, "%" PRIu64 " %s%s", delta, unit,
(delta == 1) ? "" : "s");
}
@@ -440,7 +519,7 @@ static char hexdig_upper[] = "0123456789ABCDEF";
/**
* Described in header.
*/
-int mem_printf_hook(char *dst, size_t dstlen,
+int mem_printf_hook(printf_hook_data_t *data,
printf_hook_spec_t *spec, const void *const *args)
{
char *bytes = *((void**)(args[0]));
@@ -455,7 +534,7 @@ int mem_printf_hook(char *dst, size_t dstlen,
int i = 0;
int written = 0;
- written += print_in_hook(dst, dstlen, "=> %u bytes @ %p", len, bytes);
+ written += print_in_hook(data, "=> %u bytes @ %p", len, bytes);
while (bytes_pos < bytes_roof)
{
@@ -476,7 +555,7 @@ int mem_printf_hook(char *dst, size_t dstlen,
*buffer_pos++ = '\0';
ascii_buffer[i] = '\0';
- written += print_in_hook(dst, dstlen, "\n%4d: %s %s",
+ written += print_in_hook(data, "\n%4d: %s %s",
line_start, buffer, ascii_buffer);
buffer_pos = buffer;