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

Reply via email to