diff options
Diffstat (limited to 'src/libstrongswan/utils.c')
-rw-r--r-- | src/libstrongswan/utils.c | 99 |
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; |