Andreas Jellinghaus wrote:
Am Mittwoch, 25. Januar 2006 22:41 schrieb Nils Larsch:
attached is a revised version of the patch.
Comments are still welcome :)
I don't know the subject well, but still a few comments:
- the patch does many things at the same time. that makes
it hard to review.
- it is a good idea to check the create mutex function return
value and add proper error handling.
- why those changes with time handling? why specify in several
files how to sleep? shouldn't we better have one central header
file instead of cut&pasting those sleep definitions everywhere?
- why rename sc_timestamp_t to timestamp_tß
- why the new global variable thread_ctx?
(about?) everything can be called with a context only, so why
not keep it there? why a global variable?
attached is yet another version of the patch. Comments are
welcome otherwise I will commit it in a couple of days.
Cheers,
Nils
Index: src/pkcs11/pkcs11-global.c
===================================================================
--- src/pkcs11/pkcs11-global.c (Revision 2826)
+++ src/pkcs11/pkcs11-global.c (Arbeitskopie)
@@ -18,8 +18,15 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <stdlib.h>
#include <string.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
#include "sc-pkcs11.h"
sc_context_t *context = NULL;
@@ -30,16 +37,156 @@
extern CK_FUNCTION_LIST pkcs11_function_list;
+#if defined(HAVE_PTHREAD) && defined(PKCS11_THREAD_LOCKING)
+#include <pthread.h>
+CK_RV mutex_create(void **mutex)
+{
+ pthread_mutex_t *m = (pthread_mutex_t *) malloc(sizeof(*mutex));
+ if (m == NULL)
+ return CKR_GENERAL_ERROR;;
+ pthread_mutex_init(m, NULL);
+ *mutex = m;
+ return CKR_OK;
+}
+
+CK_RV mutex_lock(void *p)
+{
+ if (pthread_mutex_lock((pthread_mutex_t *) p) == 0)
+ return CKR_OK;
+ else
+ return CKR_GENERAL_ERROR;
+}
+
+CK_RV mutex_unlock(void *p)
+{
+ if (pthread_mutex_unlock((pthread_mutex_t *) p) == 0)
+ return CKR_OK;
+ else
+ return CKR_GENERAL_ERROR;
+}
+
+CK_RV mutex_destroy(void *p)
+{
+ pthread_mutex_destroy((pthread_mutex_t *) p);
+ free(p);
+ return CKR_OK;
+}
+
+static CK_C_INITIALIZE_ARGS _def_locks = {
+ mutex_create, mutex_destroy, mutex_lock, mutex_unlock, 0, NULL };
+#elif defined(_WIN32) && defined (PKCS11_THREAD_LOCKING)
+CK_RV mutex_create(void **mutex)
+{
+ CRITICAL_SECTION *m;
+
+ m = (CRITICAL_SECTION *) malloc(sizeof(*mutex));
+ if (m == NULL)
+ return CKR_GENERAL_ERROR;
+ InitializeCriticalSection(m);
+ *mutex = m;
+ return CKR_OK;
+}
+
+CK_RV mutex_lock(void *p)
+{
+ EnterCriticalSection((CRITICAL_SECTION *) p);
+ return CKR_OK;
+}
+
+
+CK_RV mutex_unlock(void *p)
+{
+ LeaveCriticalSection((CRITICAL_SECTION *) p);
+ return CKR_OK;
+}
+
+
+CK_RV mutex_destroy(void *p)
+{
+ DeleteCriticalSection((CRITICAL_SECTION *) p);
+ free(p);
+ return CKR_OK;
+}
+static CK_C_INITIALIZE_ARGS _def_locks = {
+ mutex_create, mutex_destroy, mutex_lock, mutex_unlock, 0, NULL };
+#endif
+
+static CK_C_INITIALIZE_ARGS_PTR _locking;
+static void * _lock = NULL;
+#if (defined(HAVE_PTHREAD) || defined(_WIN32)) &&
defined(PKCS11_THREAD_LOCKING)
+static CK_C_INITIALIZE_ARGS_PTR default_mutex_funcs = &_def_locks;
+#else
+static CK_C_INITIALIZE_ARGS_PTR default_mutex_funcs = NULL;
+#endif
+
+/* wrapper for the locking functions for libopensc */
+static int sc_create_mutex(void **m)
+{
+ if (_locking == NULL)
+ return SC_SUCCESS;
+ if (_locking->CreateMutex(m) == CKR_OK)
+ return SC_SUCCESS;
+ else
+ return SC_ERROR_INTERNAL;
+}
+
+static int sc_lock_mutex(void *m)
+{
+ if (_locking == NULL)
+ return SC_SUCCESS;
+ if (_locking->LockMutex(m) == CKR_OK)
+ return SC_SUCCESS;
+ else
+ return SC_ERROR_INTERNAL;
+}
+
+static int sc_unlock_mutex(void *m)
+{
+ if (_locking == NULL)
+ return SC_SUCCESS;
+ if (_locking->UnlockMutex(m) == CKR_OK)
+ return SC_SUCCESS;
+ else
+ return SC_ERROR_INTERNAL;
+
+}
+
+static void sc_destroy_mutex(void *m)
+{
+ if (_locking == NULL)
+ return;
+ _locking->DestroyMutex(m);
+}
+
+static sc_thread_context_t sc_thread_ctx = {
+ 0, sc_create_mutex, sc_lock_mutex,
+ sc_unlock_mutex, sc_destroy_mutex, NULL
+};
+
CK_RV C_Initialize(CK_VOID_PTR pReserved)
{
int i, rc, rv;
+ sc_context_param_t ctx_opts;
if (context != NULL) {
sc_error(context, "C_Initialize(): Cryptoki already
initialized\n");
return CKR_CRYPTOKI_ALREADY_INITIALIZED;
}
- rc = sc_establish_context(&context, "opensc-pkcs11");
- if (rc != 0) {
+
+ rv = sc_pkcs11_init_lock((CK_C_INITIALIZE_ARGS_PTR) pReserved);
+ if (rv != CKR_OK) {
+ sc_release_context(context);
+ context = NULL;
+ }
+
+ /* set context options */
+ memset(&ctx_opts, 0, sizeof(sc_context_param_t));
+ ctx_opts.ver = 0;
+ ctx_opts.app_name = "opensc-pkcs11";
+ ctx_opts.thread_ctx = &sc_thread_ctx;
+
+ rc = sc_context_create(&context, &ctx_opts);
+ if (rc != SC_SUCCESS) {
rv = CKR_DEVICE_ERROR;
goto out;
}
@@ -57,12 +204,6 @@
/* Detect any card, but do not flag "insert" events */
__card_detect_all(0);
- rv = sc_pkcs11_init_lock((CK_C_INITIALIZE_ARGS_PTR) pReserved);
- if (rv != CKR_OK) {
- sc_release_context(context);
- context = NULL;
- }
-
out:
if (context != NULL)
sc_debug(context, "C_Initialize: result = %d\n", rv);
@@ -190,6 +331,33 @@
return rv;
}
+static sc_timestamp_t get_current_time(void)
+{
+#ifndef _WIN32
+ struct timeval tv;
+ struct timezone tz;
+ sc_timestamp_t curr;
+
+ if (gettimeofday(&tv, &tz) != 0)
+ return 0;
+
+ curr = tv.tv_sec;
+ curr *= 1000;
+ curr += tv.tv_usec / 1000;
+#else
+ struct _timeb time_buf;
+ timestamp_t curr;
+
+ _ftime(&time_buf);
+
+ curr = time_buf.time;
+ curr *= 1000;
+ curr += time_buf.millitm;
+#endif
+
+ return curr;
+}
+
CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
{
struct sc_pkcs11_slot *slot;
@@ -209,7 +377,7 @@
rv = slot_get_slot(slotID, &slot);
if (rv == CKR_OK){
- now = sc_current_time();
+ now = get_current_time();
if (now >= card_table[slot->reader].slot_state_expires || now
== 0) {
/* Update slot status */
rv = card_detect(slot->reader);
@@ -418,9 +586,6 @@
* Locking functions
*/
-static CK_C_INITIALIZE_ARGS_PTR _locking;
-static void * _lock = NULL;
-
CK_RV
sc_pkcs11_init_lock(CK_C_INITIALIZE_ARGS_PTR args)
{
@@ -441,7 +606,7 @@
*/
_locking = NULL;
if (args->flags & CKF_OS_LOCKING_OK) {
-#if (defined(HAVE_PTHREAD) && !defined(PKCS11_THREAD_LOCKING))
+#if defined(HAVE_PTHREAD) && !defined(PKCS11_THREAD_LOCKING)
/* FIXME:
* Mozilla uses the CKF_OS_LOCKING_OK flag in C_Initialize().
* The result is that the Mozilla process doesn't end when
@@ -457,18 +622,17 @@
*/
return CKR_OK;
#endif
- if (!(_lock = sc_mutex_new()))
- rv = CKR_CANT_LOCK;
- } else
- if (args->CreateMutex
- && args->DestroyMutex
- && args->LockMutex
- && args->UnlockMutex) {
- rv = args->CreateMutex(&_lock);
- if (rv == CKR_OK)
- _locking = args;
+ _locking = default_mutex_funcs;
+ } else if (args->CreateMutex && args->DestroyMutex &&
+ args->LockMutex && args->UnlockMutex) {
+ _locking = args;
}
+ if (_locking != NULL) {
+ /* create mutex */
+ rv = _locking->CreateMutex(&_lock);
+ }
+
return rv;
}
@@ -483,9 +647,7 @@
if (_locking) {
while (_locking->LockMutex(_lock) != CKR_OK)
;
- } else {
- sc_mutex_lock((sc_mutex_t *) _lock);
- }
+ }
return CKR_OK;
}
@@ -498,9 +660,7 @@
if (_locking) {
while (_locking->UnlockMutex(lock) != CKR_OK)
;
- } else {
- sc_mutex_unlock((sc_mutex_t *) lock);
- }
+ }
}
void
@@ -532,8 +692,6 @@
if (_locking)
_locking->DestroyMutex(tempLock);
- else
- sc_mutex_free((sc_mutex_t *) tempLock);
_locking = NULL;
}
Index: src/pkcs11/sc-pkcs11.h
===================================================================
--- src/pkcs11/sc-pkcs11.h (Revision 2826)
+++ src/pkcs11/sc-pkcs11.h (Arbeitskopie)
@@ -184,6 +184,12 @@
* PKCS#11 Slot (used to access card with specific framework data)
*/
+#ifndef _WIN32
+typedef unsigned long long sc_timestamp_t;
+#else
+typedef unsigned __int64 sc_timestamp_t;
+#endif
+
struct sc_pkcs11_card {
int reader;
struct sc_card *card;
Index: src/pkcs15init/pkcs15-gpk.c
===================================================================
--- src/pkcs15init/pkcs15-gpk.c (Revision 2826)
+++ src/pkcs15init/pkcs15-gpk.c (Arbeitskopie)
@@ -483,6 +483,14 @@
return r;
}
+/* this could be removed once we include libopensc/internal.h */
+#ifndef _WIN32
+#define msleep(t) usleep((t) * 1000)
+#else
+#define msleep(t) Sleep(t)
+#define sleep(t) Sleep((t) * 1000)
+#endif
+
/*
* On-board key generation.
*/
Index: src/libopensc/ctbcs.c
===================================================================
--- src/libopensc/ctbcs.c (Revision 2826)
+++ src/libopensc/ctbcs.c (Arbeitskopie)
@@ -178,12 +178,14 @@
dummy_card.reader = reader;
dummy_card.slot = slot;
dummy_card.ctx = reader->ctx;
- dummy_card.mutex = sc_mutex_new();
+ r = sc_mutex_create(reader->ctx, &dummy_card.mutex);
+ if (r != SC_SUCCESS)
+ return r;
dummy_card.ops = &ops;
card = &dummy_card;
r = sc_transmit_apdu(card, &apdu);
- sc_mutex_free(card->mutex);
+ sc_mutex_destroy(reader->ctx, card->mutex);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
/* Check CTBCS status word */
Index: src/libopensc/sc.c
===================================================================
--- src/libopensc/sc.c (Revision 2826)
+++ src/libopensc/sc.c (Arbeitskopie)
@@ -672,3 +672,52 @@
memset(ptr, 0, len);
#endif
}
+
+/**************************** mutex functions ************************/
+
+int sc_mutex_create(const sc_context_t *ctx, void **mutex)
+{
+ if (ctx == NULL)
+ return SC_ERROR_INVALID_ARGUMENTS;
+ if (ctx->thread_ctx != NULL && ctx->thread_ctx->create_mutex != NULL)
+ return ctx->thread_ctx->create_mutex(mutex);
+ else
+ return SC_SUCCESS;
+}
+
+int sc_mutex_lock(const sc_context_t *ctx, void *mutex)
+{
+ if (ctx == NULL)
+ return SC_ERROR_INVALID_ARGUMENTS;
+ if (ctx->thread_ctx != NULL && ctx->thread_ctx->lock_mutex != NULL)
+ return ctx->thread_ctx->lock_mutex(mutex);
+ else
+ return SC_SUCCESS;
+}
+
+int sc_mutex_unlock(const sc_context_t *ctx, void *mutex)
+{
+ if (ctx == NULL)
+ return SC_ERROR_INVALID_ARGUMENTS;
+ if (ctx->thread_ctx != NULL && ctx->thread_ctx->unlock_mutex != NULL)
+ return ctx->thread_ctx->unlock_mutex(mutex);
+ else
+ return SC_SUCCESS;
+}
+
+void sc_mutex_destroy(const sc_context_t *ctx, void *mutex)
+{
+ if (ctx == NULL || ctx->thread_ctx == NULL ||
+ ctx->thread_ctx->destroy_mutex == NULL)
+ return;
+ ctx->thread_ctx->destroy_mutex(mutex);
+}
+
+unsigned long sc_thread_id(const sc_context_t *ctx)
+{
+ if (ctx == NULL || ctx->thread_ctx == NULL ||
+ ctx->thread_ctx->thread_id == NULL)
+ return 0UL;
+ else
+ return ctx->thread_ctx->thread_id();
+}
Index: src/libopensc/card.c
===================================================================
--- src/libopensc/card.c (Revision 2826)
+++ src/libopensc/card.c (Arbeitskopie)
@@ -48,10 +48,13 @@
apdu->p2 = (u8) p2;
}
-static sc_card_t * sc_card_new(void)
+static sc_card_t * sc_card_new(sc_context_t *ctx)
{
sc_card_t *card;
+ if (ctx == NULL)
+ return NULL;
+
card = (sc_card_t *) calloc(1, sizeof(struct sc_card));
if (card == NULL)
return NULL;
@@ -60,10 +63,17 @@
free(card);
return NULL;
}
+
+ card->ctx = ctx;
+ if (sc_mutex_create(ctx, &card->mutex) != SC_SUCCESS) {
+ free(card->ops);
+ free(card);
+ return NULL;
+ }
+
card->type = -1;
card->app_count = -1;
card->magic = SC_CARD_MAGIC;
- card->mutex = sc_mutex_new();
return card;
}
@@ -77,28 +87,30 @@
free(card->ops);
if (card->algorithms != NULL)
free(card->algorithms);
- sc_mutex_free(card->mutex);
+ if (card->mutex != NULL)
+ sc_mutex_destroy(card->ctx, card->mutex);
sc_mem_clear(card, sizeof(*card));
free(card);
}
-int sc_connect_card(sc_reader_t *reader, int slot_id,
- sc_card_t **card_out)
+int sc_connect_card(sc_reader_t *reader, int slot_id, sc_card_t **card_out)
{
sc_card_t *card;
- sc_context_t *ctx = reader->ctx;
+ sc_context_t *ctx;
sc_slot_info_t *slot = _sc_get_slot_info(reader, slot_id);
struct sc_card_driver *driver;
int i, r = 0, idx, connected = 0;
- assert(card_out != NULL);
+ if (card_out == NULL || reader == NULL)
+ return SC_ERROR_INVALID_ARGUMENTS;
+ ctx = reader->ctx;
SC_FUNC_CALLED(ctx, 1);
if (reader->ops->connect == NULL)
SC_FUNC_RETURN(ctx, 0, SC_ERROR_NOT_SUPPORTED);
if (slot == NULL)
SC_FUNC_RETURN(ctx, 0, SC_ERROR_SLOT_NOT_FOUND);
- card = sc_card_new();
+ card = sc_card_new(ctx);
if (card == NULL)
SC_FUNC_RETURN(ctx, 1, SC_ERROR_OUT_OF_MEMORY);
r = reader->ops->connect(reader, slot);
@@ -238,8 +250,11 @@
{
int r = 0;
- assert(card != NULL);
- sc_mutex_lock(card->mutex);
+ if (card == NULL)
+ return SC_ERROR_INVALID_ARGUMENTS;
+ r = sc_mutex_lock(card->ctx, card->mutex);
+ if (r != SC_SUCCESS)
+ return r;
if (card->lock_count == 0) {
SC_FUNC_CALLED(card->ctx, 3);
if (card->reader->ops->lock != NULL)
@@ -249,7 +264,7 @@
}
if (r == 0)
card->lock_count++;
- sc_mutex_unlock(card->mutex);
+ r = sc_mutex_unlock(card->ctx, card->mutex);
return r;
}
@@ -257,18 +272,28 @@
{
int r = 0;
- assert(card != NULL);
- sc_mutex_lock(card->mutex);
+ if (card == NULL)
+ return SC_ERROR_INVALID_ARGUMENTS;
+ r = sc_mutex_lock(card->ctx, card->mutex);
+ if (r != SC_SUCCESS)
+ return r;
assert(card->lock_count >= 1);
if (card->lock_count == 1) {
SC_FUNC_CALLED(card->ctx, 3);
memset(&card->cache, 0, sizeof(card->cache));
card->cache_valid = 0;
if (card->ops->logout != NULL) {
- sc_mutex_unlock(card->mutex);
+ /*XXX*/
+ r = sc_mutex_unlock(card->ctx, card->mutex);
+ if (r != SC_SUCCESS) {
+ sc_error(card->ctx, "unable to release lock\n");
+ return r;
+ }
sc_debug(card->ctx, "Calling card logout function\n");
card->ops->logout(card);
- sc_mutex_lock(card->mutex);
+ r = sc_mutex_lock(card->ctx, card->mutex);
+ if (r != SC_SUCCESS)
+ return r;
}
}
/* Check again, lock count may have changed
@@ -278,7 +303,7 @@
r = card->reader->ops->unlock(card->reader, card->slot);
}
card->lock_count--;
- sc_mutex_unlock(card->mutex);
+ r = sc_mutex_unlock(card->ctx, card->mutex);
return r;
}
Index: src/libopensc/ctx.c
===================================================================
--- src/libopensc/ctx.c (Revision 2826)
+++ src/libopensc/ctx.c (Arbeitskopie)
@@ -678,23 +678,49 @@
int sc_establish_context(sc_context_t **ctx_out, const char *app_name)
{
- const char *default_app = "default";
- sc_context_t *ctx;
- struct _sc_ctx_options opts;
+ sc_context_param_t ctx_param;
- assert(ctx_out != NULL);
- ctx = (sc_context_t *) calloc(1, sizeof(sc_context_t));
+ memset(&ctx_param, 0, sizeof(sc_context_param_t));
+ ctx_param.ver = 0;
+ ctx_param.app_name = app_name;
+ return sc_context_create(ctx_out, &ctx_param);
+}
+
+int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm)
+{
+ sc_context_t *ctx;
+ struct _sc_ctx_options opts;
+ int r;
+
+ if (ctx_out == NULL)
+ return SC_ERROR_INVALID_ARGUMENTS;
+
+ ctx = calloc(1, sizeof(sc_context_t));
if (ctx == NULL)
return SC_ERROR_OUT_OF_MEMORY;
memset(&opts, 0, sizeof(opts));
set_defaults(ctx, &opts);
- ctx->app_name = app_name ? strdup(app_name) : strdup(default_app);
+
+ /* set the application name if set in the parameter options */
+ if (parm != NULL && parm->app_name != NULL)
+ ctx->app_name = strdup(parm->app_name);
+ else
+ ctx->app_name = strdup("default");
if (ctx->app_name == NULL) {
sc_release_context(ctx);
return SC_ERROR_OUT_OF_MEMORY;
}
+
+ /* set thread context and create mutex object (if specified) */
+ if (parm != NULL && parm->thread_ctx != NULL)
+ ctx->thread_ctx = parm->thread_ctx;
+ r = sc_mutex_create(ctx, &ctx->mutex);
+ if (r != SC_SUCCESS) {
+ sc_release_context(ctx);
+ return r;
+ }
+
process_config_file(ctx, &opts);
- ctx->mutex = sc_mutex_new();
sc_debug(ctx, "===================================\n"); /* first thing
in the log */
sc_debug(ctx, "opensc version: %s\n", sc_get_version());
@@ -755,12 +781,14 @@
fclose(ctx->debug_file);
if (ctx->error_file && ctx->error_file != stderr)
fclose(ctx->error_file);
- if (ctx->preferred_language)
+ if (ctx->preferred_language != NULL)
free(ctx->preferred_language);
- if (ctx->conf)
+ if (ctx->conf != NULL)
scconf_free(ctx->conf);
- sc_mutex_free(ctx->mutex);
- free(ctx->app_name);
+ if (ctx->mutex != NULL)
+ sc_mutex_destroy(ctx, ctx->mutex);
+ if (ctx->app_name != NULL)
+ free(ctx->app_name);
sc_mem_clear(ctx, sizeof(*ctx));
free(ctx);
return SC_SUCCESS;
@@ -770,7 +798,7 @@
{
int i = 0, match = 0;
- sc_mutex_lock(ctx->mutex);
+ sc_mutex_lock(ctx, ctx->mutex);
if (short_name == NULL) {
ctx->forced_driver = NULL;
match = 1;
@@ -784,7 +812,7 @@
}
i++;
}
- sc_mutex_unlock(ctx->mutex);
+ sc_mutex_unlock(ctx, ctx->mutex);
if (match == 0)
return SC_ERROR_OBJECT_NOT_FOUND; /* FIXME: invent error */
return SC_SUCCESS;
Index: src/libopensc/Makefile.mak
===================================================================
--- src/libopensc/Makefile.mak (Revision 2826)
+++ src/libopensc/Makefile.mak (Arbeitskopie)
@@ -11,7 +11,7 @@
HEADERSDIR = $(TOPDIR)\src\include\opensc
OBJECTS = \
- sc.obj ctx.obj ui.obj log.obj errors.obj portability.obj \
+ sc.obj ctx.obj ui.obj log.obj errors.obj \
asn1.obj base64.obj sec.obj card.obj iso7816.obj dir.obj padding.obj \
apdu.obj \
\
Index: src/libopensc/internal.h
===================================================================
--- src/libopensc/internal.h (Revision 2826)
+++ src/libopensc/internal.h (Arbeitskopie)
@@ -40,6 +40,13 @@
#define SC_CARD_MAGIC 0x27182818
#define SC_CTX_MAGIC 0x0A550335
+#ifndef _WIN32
+#define msleep(t) usleep((t) * 1000)
+#else
+#define msleep(t) Sleep(t)
+#define sleep(t) Sleep((t) * 1000)
+#endif
+
struct sc_atr_table {
/* The atr fields are required to
* be in aa:bb:cc hex format. */
@@ -108,6 +115,51 @@
const u8 *in, size_t in_len, u8 *out, size_t *out_len, size_t mod_len);
int sc_strip_zero_padding(const u8 *in,size_t in_len, u8 *out, size_t
*out_len);
+/********************************************************************/
+/* mutex functions */
+/********************************************************************/
+
+/**
+ * Creates a new sc_mutex object. Note: unless sc_mutex_set_mutex_funcs()
+ * this function does nothing and always returns SC_SUCCESS.
+ * @param ctx sc_context_t object with the thread context
+ * @param mutex pointer for the newly created mutex object
+ * @return SC_SUCCESS on success and an error code otherwise
+ */
+int sc_mutex_create(const sc_context_t *ctx, void **mutex);
+/**
+ * Tries to acquire a lock for a sc_mutex object. Note: Unless
+ * sc_mutex_set_mutex_funcs() has been called before this
+ * function does nothing and always returns SUCCESS.
+ * @param ctx sc_context_t object with the thread context
+ * @param mutex mutex object to lock
+ * @return SC_SUCCESS on success and an error code otherwise
+ */
+int sc_mutex_lock(const sc_context_t *ctx, void *mutex);
+/**
+ * Unlocks a sc_mutex object. Note: Unless sc_mutex_set_mutex_funcs()
+ * has been called before this function does nothing and always returns
+ * SC_SUCCESS.
+ * @param ctx sc_context_t object with the thread context
+ * @param mutex mutex object to unlock
+ * @return SC_SUCCESS on success and an error code otherwise
+ */
+int sc_mutex_unlock(const sc_context_t *ctx, void *mutex);
+/**
+ * Destroys a sc_mutex object. Note: Unless sc_mutex_set_mutex_funcs()
+ * has been called before this function does nothing and always returns
+ * SC_SUCCESS.
+ * @param ctx sc_context_t object with the thread context
+ * @param mutex mutex object to be destroyed
+ */
+void sc_mutex_destroy(const sc_context_t *ctx, void *mutex);
+/**
+ * Returns a unique id for every thread.
+ * @param ctx sc_context_t object with the thread context
+ * @return unsigned long with the unique id or 0 if not supported
+ */
+unsigned long sc_thread_id(const sc_context_t *ctx);
+
#ifdef __cplusplus
}
#endif
Index: src/libopensc/portability.c
===================================================================
--- src/libopensc/portability.c (Revision 2826)
+++ src/libopensc/portability.c (Arbeitskopie)
@@ -1,147 +0,0 @@
-/*
- * portability.c: Miscellaneous stuff needed for porting to other platforms
- *
- * Copyright (C) 2003, Olaf Kirch <[EMAIL PROTECTED]>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "internal.h"
-#include <assert.h>
-#include <stdlib.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#if defined(HAVE_PTHREAD)
-#include <pthread.h>
-
-sc_mutex_t *
-sc_mutex_new(void)
-{
- pthread_mutex_t *mutex;
-
- mutex = (pthread_mutex_t *) malloc(sizeof(*mutex));
- assert(mutex);
- pthread_mutex_init(mutex, NULL);
- return (sc_mutex_t *) mutex;
-}
-
-void
-sc_mutex_lock(sc_mutex_t *p)
-{
- pthread_mutex_lock((pthread_mutex_t *) p);
-}
-
-void
-sc_mutex_unlock(sc_mutex_t *p)
-{
- pthread_mutex_unlock((pthread_mutex_t *) p);
-}
-
-void
-sc_mutex_free(sc_mutex_t *p)
-{
- pthread_mutex_destroy((pthread_mutex_t *) p);
- free(p);
-}
-#elif defined(_WIN32)
-
-sc_mutex_t *
-sc_mutex_new(void)
-{
- CRITICAL_SECTION *mutex;
-
- mutex = (CRITICAL_SECTION *) malloc(sizeof(*mutex));
- assert(mutex);
- InitializeCriticalSection(mutex);
- return (sc_mutex_t *) mutex;
-}
-
-void
-sc_mutex_lock(sc_mutex_t *p)
-{
- EnterCriticalSection((CRITICAL_SECTION *) p);
-}
-
-void
-sc_mutex_unlock(sc_mutex_t *p)
-{
- LeaveCriticalSection((CRITICAL_SECTION *) p);
-}
-
-void
-sc_mutex_free(sc_mutex_t *p)
-{
- DeleteCriticalSection((CRITICAL_SECTION *) p);
- free(p);
-}
-#else
-sc_mutex_t *
-sc_mutex_new(void)
-{
- return (sc_mutex_t *) NULL;
-}
-
-void
-sc_mutex_lock(sc_mutex_t *p)
-{
- /* NOP */
-}
-
-void
-sc_mutex_unlock(sc_mutex_t *p)
-{
- /* NOP */
-}
-
-void
-sc_mutex_free(sc_mutex_t *p)
-{
- /* NOP */
-}
-#endif
-
-#ifndef _WIN32
-sc_timestamp_t sc_current_time(void)
-{
- struct timeval tv;
- struct timezone tz;
- sc_timestamp_t curr;
-
- if (gettimeofday(&tv, &tz) != 0)
- return 0;
-
- curr = tv.tv_sec;
- curr *= 1000;
- curr += tv.tv_usec / 1000;
-
- return curr;
-}
-#else
-sc_timestamp_t sc_current_time(void)
-{
- struct _timeb time_buf;
- sc_timestamp_t curr;
-
- _ftime(&time_buf);
-
- curr = time_buf.time;
- curr *= 1000;
- curr += time_buf.millitm;
-
- return curr;
-}
-#endif
Index: src/libopensc/Makefile.am
===================================================================
--- src/libopensc/Makefile.am (Revision 2826)
+++ src/libopensc/Makefile.am (Arbeitskopie)
@@ -13,7 +13,7 @@
lib_LTLIBRARIES = libopensc.la
libopensc_la_SOURCES = \
- sc.c ctx.c ui.c log.c errors.c portability.c \
+ sc.c ctx.c ui.c log.c errors.c \
asn1.c base64.c sec.c card.c iso7816.c dir.c padding.c apdu.c \
\
pkcs15.c pkcs15-cert.c pkcs15-data.c pkcs15-pin.c \
Index: src/libopensc/opensc.h
===================================================================
--- src/libopensc/opensc.h (Revision 2826)
+++ src/libopensc/opensc.h (Arbeitskopie)
@@ -192,16 +192,6 @@
#define SC_ALGORITHM_RSA_HASH_MD5_SHA1 0x00000080
#define SC_ALGORITHM_RSA_HASH_RIPEMD160 0x00000100
-/* A 64-bit uint, used in sc_current_time() */
-#ifndef _WIN32
-typedef unsigned long long sc_timestamp_t;
-#define msleep(t) usleep((t) * 1000)
-#else
-typedef unsigned __int64 sc_timestamp_t;
-#define msleep(t) Sleep(t)
-#define sleep(t) Sleep((t) * 1000)
-#endif
-
/* Event masks for sc_wait_for_event() */
#define SC_EVENT_CARD_INSERTED 0x0001
#define SC_EVENT_CARD_REMOVED 0x0002
@@ -419,17 +409,6 @@
int timeout);
};
-/* Mutexes - this is just a dummy struct used for type
- * safety; internally we use objects defined by the
- * underlying thread model
- */
-typedef struct sc_mutex sc_mutex_t;
-
-struct sc_mutex *sc_mutex_new(void);
-void sc_mutex_lock(struct sc_mutex *p);
-void sc_mutex_unlock(struct sc_mutex *p);
-void sc_mutex_free(struct sc_mutex *p);
-
/*
* Card flags
*
@@ -511,7 +490,7 @@
sc_serial_number_t serialnr;
- sc_mutex_t *mutex;
+ void *mutex;
unsigned int magic;
} sc_card_t;
@@ -642,6 +621,26 @@
void *dll;
} sc_card_driver_t;
+/**
+ * @struct sc_thread_context_t
+ * Structure for the locking function to use when using libopensc
+ * in a multi-threaded application.
+ */
+typedef struct {
+ /** the version number of this structure (0 for this version) */
+ unsigned int ver;
+ /** creates a mutex object */
+ int (*create_mutex)(void **);
+ /** locks a mutex object (blocks until the lock has been acquired) */
+ int (*lock_mutex)(void *);
+ /** unlocks a mutex object */
+ int (*unlock_mutex)(void *);
+ /** destroys a mutex object */
+ void (*destroy_mutex)(void *);
+ /** returns unique identifier for the thread (can be NULL) */
+ unsigned long (*thread_id)(void);
+} sc_thread_context_t;
+
typedef struct sc_context {
scconf_context *conf;
scconf_block *conf_blocks[3];
@@ -661,7 +660,8 @@
struct sc_card_driver *card_drivers[SC_MAX_CARD_DRIVERS];
struct sc_card_driver *forced_driver;
- sc_mutex_t *mutex;
+ sc_thread_context_t *thread_ctx;
+ void *mutex;
unsigned int magic;
} sc_context_t;
@@ -684,7 +684,8 @@
/********************************************************************/
/**
- * Establishes an OpenSC context
+ * Establishes an OpenSC context. Note: this function is deprecated,
+ * please use sc_context_create() instead.
* @param ctx A pointer to a pointer that will receive the allocated context
* @param app_name A string that identifies the application, used primarily
* in finding application-specific configuration data. Can be NULL.
@@ -692,6 +693,34 @@
int sc_establish_context(sc_context_t **ctx, const char *app_name);
/**
+ * @struct sc_context_t initialization parameters
+ * Structure to supply additional parameters, for example
+ * mutex information, to the sc_context_t creation.
+ */
+typedef struct {
+ /** version number of this structure (0 for this version) */
+ unsigned int ver;
+ /** name of the application (used for finding application
+ * dependend configuration data). If NULL the name "default"
+ * will be used. */
+ const char *app_name;
+ /** flags, currently unused */
+ unsigned long flags;
+ /** mutex functions to use (optional) */
+ sc_thread_context_t *thread_ctx;
+} sc_context_param_t;
+/**
+ * Creates a new sc_context_t object.
+ * @param ctx pointer to a sc_context_t pointer for the newly
+ * created sc_context_t object.
+ * @param parm parameters for the sc_context_t creation (see
+ * sc_context_param_t for a description of the supported
+ * options). This parameter is optional and can be NULL.
+ * @return SC_SUCCESS on success and an error code otherwise.
+ */
+int sc_context_create(sc_context_t **ctx, const sc_context_param_t *parm);
+
+/**
* Releases an established OpenSC context
* @param ctx A pointer to the context structure to be released
*/
@@ -737,8 +766,7 @@
* @param reader Reader structure
* @param slot_id Slot ID to connect to
* @param card The allocated card object will go here */
-int sc_connect_card(sc_reader_t *reader, int slot_id,
- sc_card_t **card);
+int sc_connect_card(sc_reader_t *reader, int slot_id, sc_card_t **card);
/**
* Disconnects from a card, and frees the card structure. Any locks
* made by the application must be released before calling this function.
@@ -996,9 +1024,6 @@
size_t linelength);
int sc_base64_decode(const char *in, u8 *out, size_t outlen);
-/* Returns the current time in milliseconds */
-sc_timestamp_t sc_current_time(void);
-
/**
* Clears a memory buffer (note: when OpenSSL is used this is
* currently a wrapper for OPENSSL_cleanse() ).
_______________________________________________
opensc-devel mailing list
[email protected]
http://www.opensc-project.org/mailman/listinfo/opensc-devel