diff options
Diffstat (limited to 'p11-kit/util.c')
-rw-r--r-- | p11-kit/util.c | 188 |
1 files changed, 155 insertions, 33 deletions
diff --git a/p11-kit/util.c b/p11-kit/util.c index fdf434b..eab0b13 100644 --- a/p11-kit/util.c +++ b/p11-kit/util.c @@ -36,6 +36,7 @@ #include "config.h" +#include "debug.h" #include "p11-kit.h" #include "private.h" #include "util.h" @@ -46,6 +47,18 @@ #include <stdio.h> #include <string.h> +/* + * This is the mutex that protects the global data of this library + * and the pkcs11 proxy module. Note that we *never* call into our + * underlying pkcs11 modules while holding this mutex. Therefore it + * doesn't have to be recursive and we can keep things simple. + */ +mutex_t _p11_mutex; + +#ifdef OS_UNIX +pthread_once_t _p11_once; +#endif + /** * SECTION:p11-kit-future * @title: Future @@ -56,9 +69,6 @@ * MACRO. See the p11-kit.h header for more details. */ -#define MAX_MESSAGE 512 -static pthread_once_t key_once = PTHREAD_ONCE_INIT; -static pthread_key_t message_buffer_key = 0; static int print_messages = 1; void* @@ -143,44 +153,34 @@ p11_kit_space_strdup (const unsigned char *string, size_t max_length) } static void -create_message_buffer_key (void) -{ - pthread_key_create (&message_buffer_key, free); -} - -static void store_message_buffer (const char* msg, size_t length) { - char *thread_buf; + p11_local *local; - if (length > MAX_MESSAGE - 1) - length = MAX_MESSAGE - 1; + if (length > P11_MAX_MESSAGE - 1) + length = P11_MAX_MESSAGE - 1; - pthread_once (&key_once, create_message_buffer_key); - thread_buf = pthread_getspecific (message_buffer_key); - if (!thread_buf) { - thread_buf = malloc (MAX_MESSAGE); - pthread_setspecific (message_buffer_key, thread_buf); + local = _p11_library_get_thread_local (); + if (local != NULL) { + memcpy (local->message, msg, length); + local->message[length] = 0; } - - memcpy (thread_buf, msg, length); - thread_buf[length] = 0; } void _p11_message (const char* msg, ...) { - char buffer[MAX_MESSAGE]; + char buffer[P11_MAX_MESSAGE]; va_list va; size_t length; va_start (va, msg); - length = vsnprintf (buffer, MAX_MESSAGE - 1, msg, va); + length = vsnprintf (buffer, P11_MAX_MESSAGE - 1, msg, va); va_end (va); /* Was it truncated? */ - if (length > MAX_MESSAGE - 1) - length = MAX_MESSAGE - 1; + if (length > P11_MAX_MESSAGE - 1) + length = P11_MAX_MESSAGE - 1; buffer[length] = 0; /* If printing is not disabled, just print out */ @@ -220,20 +220,18 @@ p11_kit_be_quiet (void) const char* p11_kit_message (void) { - char *thread_buf; - pthread_once (&key_once, create_message_buffer_key); - thread_buf = pthread_getspecific (message_buffer_key); - return thread_buf && thread_buf[0] ? thread_buf : NULL; + p11_local *local; + local = _p11_library_get_thread_local (); + return local && local->message[0] ? local->message : NULL; } void _p11_kit_clear_message (void) { - char *thread_buf; - pthread_once (&key_once, create_message_buffer_key); - thread_buf = pthread_getspecific (message_buffer_key); - if (thread_buf != NULL) - thread_buf[0] = 0; + p11_local *local; + local = _p11_library_get_thread_local (); + if (local != NULL) + local->message[0] = 0; } void @@ -246,3 +244,127 @@ _p11_kit_default_message (CK_RV rv) store_message_buffer (msg, strlen (msg)); } } + +#ifdef OS_UNIX + +static pthread_key_t thread_local = 0; + +p11_local * +_p11_library_get_thread_local (void) +{ + p11_local *local; + + _p11_library_init_once (); + + local = pthread_getspecific (thread_local); + if (local == NULL) { + local = calloc (1, sizeof (p11_local)); + pthread_setspecific (thread_local, local); + } + + return local; +} + +void +_p11_library_init (void) +{ + debug_init (); + mutex_init (&_p11_mutex); + pthread_key_create (&thread_local, free); +} + +void +_p11_library_uninit (void) +{ + pthread_key_delete (thread_local); + mutex_uninit (&_p11_mutex); +} + +#endif /* OS_UNIX */ + +#ifdef OS_WIN32 + +static DWORD thread_local = TLS_OUT_OF_INDEXES; + +BOOL WINAPI DllMain (HINSTANCE, DWORD, LPVOID); + +p11_local * +_p11_library_get_thread_local (void) +{ + LPVOID data; + + if (thread_local == TLS_OUT_OF_INDEXES) + return NULL; + + data = TlsGetValue (thread_local); + if (data == NULL) { + data = LocalAlloc (LPTR, sizeof (p11_local)); + TlsSetValue (thread_local, data); + } + + return (p11_local *)data; +} + +void +_p11_library_init (void) +{ + debug_init (); + mutex_init (&_p11_mutex); + thread_local = TlsAlloc (); +} + +static void +free_tls_value (LPVOID data) +{ + p11_local *local = data; + if (local->last_error) + LocalFree (local->last_error); + LocalFree (data); +} + +void +_p11_library_uninit (void) +{ + LPVOID data; + + if (thread_local != TLS_OUT_OF_INDEXES) { + data = TlsGetValue (thread_local); + free_tls_value (data); + TlsFree (thread_local); + } + mutex_uninit (&_p11_mutex); +} + +BOOL WINAPI +DllMain (HINSTANCE instance, + DWORD reason, + LPVOID reserved) +{ + LPVOID data; + + switch (reason) { + case DLL_PROCESS_ATTACH: + _p11_library_init (); + if (thread_local == TLS_OUT_OF_INDEXES) + return FALSE; + break; + + case DLL_THREAD_DETACH: + if (thread_local != TLS_OUT_OF_INDEXES) { + data = TlsGetValue (thread_local); + free_tls_value (data); + } + break; + + case DLL_PROCESS_DETACH: + _p11_library_uninit (); + break; + + default: + break; + } + + return TRUE; +} + +#endif /* OS_WIN32 */ |