Эх сурвалжийг харах

2006-10-30 Marcus Brinkmann <marcus@g10code.de>

	* configure.ac (VERSION_MAJOR, VERSION_MINOR): New variable
	definitions.
	* src/gpgsm.h: Fix syntax error.
	* src/table.c, src/table.h: Rewritten.
	* src/slots.c: Reorganized and rewritten to use the new table
	interface.  Include gpgsm.h.
	* src/p11-signinit.c, src/p11-sign.c, src/p11-getslotlist.c,
	src/p11-getsessioninfo.c, src/p11-getmechanismlist.c,
	src/p11-getattributevalue.c, src/p11-findobjectsinit.c,
	src/p11-findobjectsfinal.c, src/p11-findobjects.c,
	src/p11-closesession.c: Adjust callers.
Marcus Brinkmann 19 жил өмнө
parent
commit
1330318afa

+ 14 - 0
ChangeLog

@@ -1,3 +1,17 @@
+2006-10-30  Marcus Brinkmann  <marcus@g10code.de>
+
+	* configure.ac (VERSION_MAJOR, VERSION_MINOR): New variable
+	definitions.
+	* src/gpgsm.h: Fix syntax error.
+	* src/table.c, src/table.h: Rewritten.
+	* src/slots.c: Reorganized and rewritten to use the new table
+	interface.  Include gpgsm.h.
+	* src/p11-signinit.c, src/p11-sign.c, src/p11-getslotlist.c,
+	src/p11-getsessioninfo.c, src/p11-getmechanismlist.c,
+	src/p11-getattributevalue.c, src/p11-findobjectsinit.c,
+	src/p11-findobjectsfinal.c, src/p11-findobjects.c,
+	src/p11-closesession.c: Adjust callers.
+
 2006-10-26  Marcus Brinkmann  <marcus@g10code.de>
 2006-10-26  Marcus Brinkmann  <marcus@g10code.de>
 
 
 	* src/settings.h: Require VERSION_MAJOR and VERSION_MINOR to be
 	* src/settings.h: Require VERSION_MAJOR and VERSION_MINOR to be

+ 6 - 0
configure.ac

@@ -34,6 +34,10 @@ LIBSCUTE_LT_CURRENT=0
 LIBSCUTE_LT_AGE=0
 LIBSCUTE_LT_AGE=0
 LIBSCUTE_LT_REVISION=0
 LIBSCUTE_LT_REVISION=0
 
 
+# Version numbers reported by the PKCS #11 module to its users.
+VERSION_MAJOR=0
+VERSION_MINOR=0
+
 NEED_GPG_ERROR_VERSION=0.7
 NEED_GPG_ERROR_VERSION=0.7
 NEED_LIBASSUAN_VERSION=0.6.10
 NEED_LIBASSUAN_VERSION=0.6.10
 NEED_GPGSM_VERSION=1.9.6
 NEED_GPGSM_VERSION=1.9.6
@@ -85,6 +89,8 @@ AC_SUBST(PACKAGE)
 AC_SUBST(VERSION)
 AC_SUBST(VERSION)
 AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package])
 AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package])
 AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package])
 AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package])
+AC_DEFINE_UNQUOTED(VERSION_MAJOR, $VERSION_MAJOR, [Major version number])
+AC_DEFINE_UNQUOTED(VERSION_MINOR, $VERSION_MINOR, [Minor version number])
 
 
 # Don't default to build static libs.
 # Don't default to build static libs.
 AC_DISABLE_STATIC
 AC_DISABLE_STATIC

+ 5 - 4
src/gpgsm.h

@@ -42,9 +42,10 @@
    Returns allocated attributes for the certificate object in ATTRP
    Returns allocated attributes for the certificate object in ATTRP
    and ATTR_COUNTP, and for the private key object in PRV_ATTRP
    and ATTR_COUNTP, and for the private key object in PRV_ATTRP
    and PRV_ATTR_COUNTP.  */
    and PRV_ATTR_COUNTP.  */
-gpg_error_t
-scute_gpgsm_get_cert (char *grip,
-		      CK_ATTRIBUTE_PTR *attrp, CK_ULONG *attr_countp,
-		      CK_ATTRIBUTE_PTR *prv_attrp, CK_ULONG *prv_attr_countp)
+gpg_error_t scute_gpgsm_get_cert (char *grip,
+				  CK_ATTRIBUTE_PTR *attrp,
+				  CK_ULONG *attr_countp,
+				  CK_ATTRIBUTE_PTR *prv_attrp,
+				  CK_ULONG *prv_attr_countp);
 
 
 #endif	/* GPGSM_H */
 #endif	/* GPGSM_H */

+ 3 - 2
src/p11-closesession.c

@@ -45,16 +45,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)
 {
 {
   CK_RV err = CKR_OK;
   CK_RV err = CKR_OK;
   slot_iterator_t slot;
   slot_iterator_t slot;
+  session_iterator_t session;
 
 
   err = scute_global_lock ();
   err = scute_global_lock ();
   if (err)
   if (err)
     return err;
     return err;
 
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
   if (err)
     goto out;
     goto out;
 
 
-  err = slot_close_session (slot, hSession);
+  err = slot_close_session (slot, session);
 
 
  out:
  out:
   scute_global_unlock ();
   scute_global_unlock ();

+ 4 - 3
src/p11-findobjects.c

@@ -52,6 +52,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)
   CK_RV err = CKR_OK;
   CK_RV err = CKR_OK;
   CK_ULONG count;
   CK_ULONG count;
   slot_iterator_t slot;
   slot_iterator_t slot;
+  session_iterator_t session;
   object_iterator_t *oids;
   object_iterator_t *oids;
   int oids_len;
   int oids_len;
 
 
@@ -62,11 +63,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)
   if (err)
   if (err)
     return err;
     return err;
 
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
   if (err)
     goto out;
     goto out;
 
 
-  err = session_get_search_result (slot, hSession, &oids, &oids_len);
+  err = session_get_search_result (slot, session, &oids, &oids_len);
   assert (!err);
   assert (!err);
 
 
   count = MIN (ulMaxObjectCount, oids_len);
   count = MIN (ulMaxObjectCount, oids_len);
@@ -74,7 +75,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)
 
 
   oids_len = oids_len - count;
   oids_len = oids_len - count;
   memmove (oids, oids + count, sizeof (CK_OBJECT_HANDLE) * oids_len);
   memmove (oids, oids + count, sizeof (CK_OBJECT_HANDLE) * oids_len);
-  err = session_set_search_result (slot, hSession, oids, oids_len);
+  err = session_set_search_result (slot, session, oids, oids_len);
   assert (!err);
   assert (!err);
 
 
   *pulObjectCount = count;
   *pulObjectCount = count;

+ 3 - 2
src/p11-findobjectsfinal.c

@@ -47,16 +47,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)
 {
 {
   CK_RV err = CKR_OK;
   CK_RV err = CKR_OK;
   slot_iterator_t slot;
   slot_iterator_t slot;
+  session_iterator_t session;
 
 
   err = scute_global_lock ();
   err = scute_global_lock ();
   if (err)
   if (err)
     return err;
     return err;
 
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
   if (err)
     goto out;
     goto out;
 
 
-  err = session_set_search_result (slot, hSession, NULL, 0);
+  err = session_set_search_result (slot, session, NULL, 0);
 
 
  out:
  out:
   scute_global_unlock ();
   scute_global_unlock ();

+ 4 - 6
src/p11-findobjectsinit.c

@@ -50,6 +50,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)
 {
 {
   CK_RV err = CKR_OK;
   CK_RV err = CKR_OK;
   slot_iterator_t slot;
   slot_iterator_t slot;
+  session_iterator_t session;
   object_iterator_t object;
   object_iterator_t object;
   object_iterator_t *search_result;
   object_iterator_t *search_result;
   int search_result_len = 0;
   int search_result_len = 0;
@@ -61,7 +62,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)
   if (err)
   if (err)
     return err;
     return err;
 
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
   if (err)
     goto out;
     goto out;
 
 
@@ -77,7 +78,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)
     }
     }
   search_result_len = 0;
   search_result_len = 0;
 
 
-  err = objects_iterate_begin (slot, &object);
+  err = objects_iterate_first (slot, &object);
   if (err)
   if (err)
     {
     {
       free (search_result);
       free (search_result);
@@ -124,16 +125,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)
 	}
 	}
     }
     }
 
 
-  /* Always call this after an iteration.  */
-  objects_iterate_end (slot, &object);
-
   if (err)
   if (err)
     {
     {
       free (search_result);
       free (search_result);
       goto out;
       goto out;
     }
     }
 
 
-  err = session_set_search_result (slot, hSession, search_result,
+  err = session_set_search_result (slot, session, search_result,
 				   search_result_len);
 				   search_result_len);
 
 
  out:
  out:

+ 2 - 1
src/p11-getattributevalue.c

@@ -48,6 +48,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)
 {
 {
   CK_RV err = CKR_OK;
   CK_RV err = CKR_OK;
   slot_iterator_t slot;
   slot_iterator_t slot;
+  session_iterator_t session;
   CK_ATTRIBUTE_PTR attr;
   CK_ATTRIBUTE_PTR attr;
   CK_ULONG attr_count;
   CK_ULONG attr_count;
 
 
@@ -58,7 +59,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)
   if (err)
   if (err)
     return err;
     return err;
 
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
   if (err)
     goto out;
     goto out;
 
 

+ 1 - 4
src/p11-getmechanismlist.c

@@ -63,7 +63,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)
   /* Leave LEFT positive for the whole search when only counting.  */
   /* Leave LEFT positive for the whole search when only counting.  */
   left = pMechanismList ? *pulCount : 1;
   left = pMechanismList ? *pulCount : 1;
   *pulCount = 0;
   *pulCount = 0;
-  err = mechanisms_iterate_begin (slot, &mechanism);
+  err = mechanisms_iterate_first (slot, &mechanism);
   if (err)
   if (err)
     goto out;
     goto out;
 
 
@@ -79,9 +79,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)
       err = mechanisms_iterate_next (slot, &mechanism);
       err = mechanisms_iterate_next (slot, &mechanism);
     }
     }
 
 
-  /* Always call this after an iteration.  */
-  mechanisms_iterate_end (slot, &mechanism);
-
   if (err)
   if (err)
     goto out;
     goto out;
 
 

+ 4 - 3
src/p11-getsessioninfo.c

@@ -47,6 +47,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)
 {
 {
   CK_RV err = CKR_OK;
   CK_RV err = CKR_OK;
   slot_iterator_t slot;
   slot_iterator_t slot;
+  session_iterator_t session;
   bool rw;
   bool rw;
 
 
   if (pInfo == NULL_PTR)
   if (pInfo == NULL_PTR)
@@ -56,7 +57,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)
   if (err)
   if (err)
     return err;
     return err;
 
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
   if (err)
     goto out;
     goto out;
 
 
@@ -66,11 +67,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)
 
 
   /* We have to re-lookup the session handle, as it might just have
   /* We have to re-lookup the session handle, as it might just have
      become invalid.  */
      become invalid.  */
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
   if (err)
     goto out;
     goto out;
 
 
-  rw = session_get_rw (slot, hSession);
+  rw = session_get_rw (slot, session);
   switch (slot_get_status (slot))
   switch (slot_get_status (slot))
     {
     {
     case SLOT_LOGIN_PUBLIC:
     case SLOT_LOGIN_PUBLIC:

+ 1 - 4
src/p11-getslotlist.c

@@ -64,7 +64,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)
   /* Leave LEFT positive for the whole search when only counting.  */
   /* Leave LEFT positive for the whole search when only counting.  */
   left = pSlotList ? *pulCount : 1;
   left = pSlotList ? *pulCount : 1;
   *pulCount = 0;
   *pulCount = 0;
-  err = slots_iterate_begin (&slot);
+  err = slots_iterate_first (&slot);
   if (err)
   if (err)
     goto out;
     goto out;
 
 
@@ -83,9 +83,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)
       err = slots_iterate_next (&slot);
       err = slots_iterate_next (&slot);
     }
     }
 
 
-  /* Always call this after an iteration.  */
-  slots_iterate_end (&slot);
-
   if (err)
   if (err)
     goto out;
     goto out;
 
 

+ 3 - 2
src/p11-sign.c

@@ -46,6 +46,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)
 {
 {
   CK_RV err = CKR_OK;
   CK_RV err = CKR_OK;
   slot_iterator_t slot;
   slot_iterator_t slot;
+  session_iterator_t session;
 
 
   if (pData == NULL_PTR || pulSignatureLen == NULL_PTR)
   if (pData == NULL_PTR || pulSignatureLen == NULL_PTR)
     return CKR_ARGUMENTS_BAD;
     return CKR_ARGUMENTS_BAD;
@@ -54,12 +55,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)
   if (err)
   if (err)
     return err;
     return err;
 
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
   if (err)
     goto out;
     goto out;
 
 
   /* FIXME: Who cares if they called sign init correctly.  */
   /* FIXME: Who cares if they called sign init correctly.  */
-  err = session_sign (slot, hSession, pData, ulDataLen,
+  err = session_sign (slot, session, pData, ulDataLen,
 		      pSignature, pulSignatureLen);
 		      pSignature, pulSignatureLen);
 
 
  out:
  out:

+ 3 - 2
src/p11-signinit.c

@@ -46,6 +46,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)
 {
 {
   CK_RV err = CKR_OK;
   CK_RV err = CKR_OK;
   slot_iterator_t slot;
   slot_iterator_t slot;
+  session_iterator_t session;
 
 
   if (pMechanism == NULL_PTR || pMechanism->mechanism != CKM_RSA_PKCS)
   if (pMechanism == NULL_PTR || pMechanism->mechanism != CKM_RSA_PKCS)
     return CKR_ARGUMENTS_BAD;
     return CKR_ARGUMENTS_BAD;
@@ -57,11 +58,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)
   if (err)
   if (err)
     return err;
     return err;
 
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
   if (err)
     goto out;
     goto out;
 
 
-  err = session_set_signing_key (slot, hSession, hKey);
+  err = session_set_signing_key (slot, session, hKey);
 
 
  out:
  out:
   scute_global_unlock ();
   scute_global_unlock ();

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 333 - 324
src/slots.c


+ 6 - 15
src/slots.h

@@ -56,7 +56,7 @@ typedef int mechanism_iterator_t;
 typedef CK_OBJECT_HANDLE object_iterator_t;
 typedef CK_OBJECT_HANDLE object_iterator_t;
 
 
 /* A session pointer.  */
 /* A session pointer.  */
-typedef CK_SESSION_HANDLE session_iterator_t;
+typedef int session_iterator_t;
 
 
 
 
 /* Initialize the slot list.  */
 /* Initialize the slot list.  */
@@ -76,14 +76,11 @@ CK_RV slots_update_slot (slot_iterator_t id);
 
 
 /* Begin iterating over the list of slots.  If succeeds, will be
 /* Begin iterating over the list of slots.  If succeeds, will be
    followed up by a slot_iterate_end.  */
    followed up by a slot_iterate_end.  */
-CK_RV slots_iterate_begin (slot_iterator_t *slot);
+CK_RV slots_iterate_first (slot_iterator_t *slot);
 
 
 /* Continue iterating over the list of slots.  */
 /* Continue iterating over the list of slots.  */
 CK_RV slots_iterate_next (slot_iterator_t *slot);
 CK_RV slots_iterate_next (slot_iterator_t *slot);
 
 
-/* Continue iterating over the list of slots.  */
-CK_RV slots_iterate_end (slot_iterator_t *slot);
-
 /* Return true iff the previous slot was the last one.  */
 /* Return true iff the previous slot was the last one.  */
 bool slots_iterate_last (slot_iterator_t *slot);
 bool slots_iterate_last (slot_iterator_t *slot);
 
 
@@ -125,17 +122,13 @@ CK_SLOT_ID slot_get_id (slot_iterator_t slot);
 
 
 /* Begin iterating over the list of mechanisms.  If succeeds, will be
 /* Begin iterating over the list of mechanisms.  If succeeds, will be
    followed up by a slot_iterate_end.  */
    followed up by a slot_iterate_end.  */
-CK_RV mechanisms_iterate_begin (slot_iterator_t id,
+CK_RV mechanisms_iterate_first (slot_iterator_t id,
 				mechanism_iterator_t *mechanism);
 				mechanism_iterator_t *mechanism);
 
 
 /* Continue iterating over the list of mechanisms.  */
 /* Continue iterating over the list of mechanisms.  */
 CK_RV mechanisms_iterate_next (slot_iterator_t id,
 CK_RV mechanisms_iterate_next (slot_iterator_t id,
 			       mechanism_iterator_t *mechanism);
 			       mechanism_iterator_t *mechanism);
 
 
-/* Stop iterating over the list of mechanisms.  */
-CK_RV mechanisms_iterate_end (slot_iterator_t id,
-			      mechanism_iterator_t *mechanism);
-
 /* Return true iff the previous slot was the last one.  */
 /* Return true iff the previous slot was the last one.  */
 bool mechanisms_iterate_last (slot_iterator_t id,
 bool mechanisms_iterate_last (slot_iterator_t id,
 			      mechanism_iterator_t *mechanisms);
 			      mechanism_iterator_t *mechanisms);
@@ -160,7 +153,8 @@ CK_RV slot_create_session (slot_iterator_t id, session_iterator_t *session,
 			   bool rw);
 			   bool rw);
 
 
 /* Look up session.  */
 /* Look up session.  */
-CK_RV slots_lookup_session (session_iterator_t sid, slot_iterator_t *id);
+CK_RV slots_lookup_session (CK_SESSION_HANDLE sid, slot_iterator_t *id,
+			    session_iterator_t *session_id);
 
 
 /* Close the session.  */
 /* Close the session.  */
 CK_RV slot_close_session (slot_iterator_t id, session_iterator_t sid);
 CK_RV slot_close_session (slot_iterator_t id, session_iterator_t sid);
@@ -179,14 +173,11 @@ slot_login_t slot_get_status (slot_iterator_t id);
 
 
 /* Begin iterating over the list of objects.  If succeeds, will be
 /* Begin iterating over the list of objects.  If succeeds, will be
    followed up by a slot_iterate_end.  */
    followed up by a slot_iterate_end.  */
-CK_RV objects_iterate_begin (slot_iterator_t id, object_iterator_t *object);
+CK_RV objects_iterate_first (slot_iterator_t id, object_iterator_t *object);
 
 
 /* Continue iterating over the list of objects.  */
 /* Continue iterating over the list of objects.  */
 CK_RV objects_iterate_next (slot_iterator_t id, object_iterator_t *object);
 CK_RV objects_iterate_next (slot_iterator_t id, object_iterator_t *object);
 
 
-/* Stop iterating over the list of objects.  */
-CK_RV objects_iterate_end (slot_iterator_t id, object_iterator_t *object);
-
 /* Return true iff the previous slot was the last one.  */
 /* Return true iff the previous slot was the last one.  */
 bool objects_iterate_last (slot_iterator_t id, object_iterator_t *object);
 bool objects_iterate_last (slot_iterator_t id, object_iterator_t *object);
 
 

+ 238 - 26
src/table.c

@@ -1,5 +1,5 @@
-/* table.c - Table abstraction implementation.
-   Copyright (C) 2004, 2006 Marcus Brinkmann
+/* table.c - Indexed table implementation.
+   Copyright (C) 2006 g10 Code GmbH
 
 
    This file is part of Scute[1].
    This file is part of Scute[1].
 
 
@@ -34,60 +34,172 @@
 #include <config.h>
 #include <config.h>
 #endif
 #endif
 
 
+#include <stdlib.h>
 #include <assert.h>
 #include <assert.h>
-#include <string.h>
+
+#include <gpg-error.h>
 
 
 #include "table.h"
 #include "table.h"
 
 
+/* Indices are 1 based externally, but 0 based internally.  */
+#define INDEX_COPY_IN(idx) ((idx) - 1)
+#define INDEX_COPY_OUT(idx) ((idx) + 1)
+
+/* End of table marker.  */
+#define INDEX_EOT (-1)
+
 
 
-/* Initialize the table TABLE.  */
-error_t
-hurd_table_init (hurd_table_t table, unsigned int entry_size)
+/* This is an indexed list implementation.  It only supports storing
+   and retrieving pointers.  One would like to support arbitrary data
+   types inline, but this is not possible in a portable manner,
+   because of aliasing and alignment restrictions.
+
+   Note that this implementation is only fast if the lists are very
+   short.  */
+
+struct scute_table
+{
+  /* The user data pointers.  */
+  void **data;
+
+  /* The size of DATA.  */
+  int size;
+
+  /* The number of used entries in DATA.  */
+  int used;
+
+  /* The index of the lowest entry that is unused.  */
+  unsigned int first_free;
+
+  /* The index after the highest entry that is used.  */
+  unsigned int last_used;
+
+  /* The allocator and deallocator callback.  */
+  scute_table_alloc_cb_t alloc;
+  scute_table_dealloc_cb_t dealloc;
+};
+
+
+/* Some support functions for iteration.  */
+
+/* Return the first element in TABLE.  */
+static int
+index_first (scute_table_t table)
+{
+  int index = 0;
+
+  while (index < table->last_used && table->data[index] == NULL)
+    index++;
+
+  if (index == table->last_used)
+    return INDEX_EOT;
+
+  return index;
+}
+
+
+/* Return the element following INDEX, or the end-of-list marker if
+   INDEX is the last element on the list.  */
+static int
+index_next (scute_table_t table, int index)
 {
 {
-  assert (sizeof (entry_size) >= sizeof (void *));
+  index++;
 
 
-  *table = (struct hurd_table) HURD_TABLE_INITIALIZER (entry_size);
+  while (index < table->last_used && table->data[index] == NULL)
+    index++;
+
+  if (index >= table->last_used)
+    index = INDEX_EOT;
+
+  return index;
+}
+
+
+/* TABLE interface implementation.  */
+
+/* Create a new table and return it in TABLE_R.  */
+gpg_error_t
+scute_table_create (scute_table_t *table_r,
+				scute_table_alloc_cb_t alloc,
+				scute_table_dealloc_cb_t dealloc)
+{
+  scute_table_t table;
+
+  table = malloc (sizeof (*table));
+  if (!table)
+    return gpg_error_from_syserror ();
+
+  table->data = NULL;
+  table->size = 0;
+  table->used = 0;
+  table->first_free = 0;
+  table->last_used = 0;
+  table->alloc = alloc;
+  table->dealloc = dealloc;
+
+  *table_r = table;
   return 0;
   return 0;
 }
 }
 
 
 
 
-/* Destroy the table TABLE.  */
+/* Destroy the indexed list TABLE.  The user has to make sure that the
+   existing entries are not needed anymore before calling this
+   function.  */
 void
 void
-hurd_table_destroy (hurd_table_t table)
+scute_table_destroy (scute_table_t table)
 {
 {
+  int idx = 0;
+
+  if (table == NULL)
+    return;
+
+  for (idx = 0; idx < table->last_used; idx++)
+    if (table->data[idx] != NULL)
+      (*table->dealloc) (table->data[idx]);
+
   if (table->data)
   if (table->data)
     free (table->data);
     free (table->data);
+  free (table);
 }
 }
 
 
-
+
 /* The initial table size.  */
 /* The initial table size.  */
 #define TABLE_START_SIZE	4
 #define TABLE_START_SIZE	4
 
 
-/* Add the table element DATA to the table TABLE.  The index for this
-   element is returned in R_IDX.  Note that the data is added by
-   copying ENTRY_SIZE bytes into the table (the ENTRY_SIZE parameter
-   was provided at table initialization time).  */
-error_t
-hurd_table_enter (hurd_table_t table, void *data, unsigned int *r_idx)
+/* Allocate a new table entry with a free index.  Returns the index
+   pointing to the new list entry in INDEX_R.  This calls the
+   allocator on the new entry before returning.  Also returns the
+   table entry in *DATA_R if this is not NULL.  */
+gpg_error_t
+scute_table_alloc (scute_table_t table, int *index_r, void **data_r,
+		   void *hook)
 {
 {
+  gpg_error_t err;
   unsigned int idx;
   unsigned int idx;
+  void *data;
 
 
   if (table->used == table->size)
   if (table->used == table->size)
     {
     {
       unsigned int size_new = table->size ? 2 * table->size : TABLE_START_SIZE;
       unsigned int size_new = table->size ? 2 * table->size : TABLE_START_SIZE;
       void *data_new;
       void *data_new;
 
 
-      data_new = realloc (table->data, size_new * table->entry_size);
+      data_new = realloc (table->data, size_new * sizeof (*(table->data)));
       if (!data_new)
       if (!data_new)
-	return errno;
+	return gpg_error_from_syserror ();
 
 
       table->first_free = table->size;
       table->first_free = table->size;
       table->data = data_new;
       table->data = data_new;
       table->size = size_new;
       table->size = size_new;
     }
     }
 
 
-  for (idx = table->first_free; idx < table->init_size; idx++)
-    if (_HURD_TABLE_ENTRY_LOOKUP (table, idx) == HURD_TABLE_EMPTY)
+  /* We may needlessly have increased the table size if this fails,
+     but that is not a problem.  */
+  err = (*table->alloc) (&data, hook);
+  if (err)
+    return err;
+
+  for (idx = table->first_free; idx < table->last_used; idx++)
+    if (table->data[idx] == NULL)
       break;
       break;
 
 
   /* The following setting for FIRST_FREE is safe, because if this was
   /* The following setting for FIRST_FREE is safe, because if this was
@@ -96,14 +208,114 @@ hurd_table_enter (hurd_table_t table, void *data, unsigned int *r_idx)
      the meantime.  */
      the meantime.  */
   table->first_free = idx + 1;
   table->first_free = idx + 1;
 
 
-  if (idx == table->init_size)
-    table->init_size++;
   if (idx == table->last_used)
   if (idx == table->last_used)
     table->last_used++;
     table->last_used++;
 
 
-  memcpy (HURD_TABLE_LOOKUP (table, idx), data, table->entry_size);
+  table->data[idx] = data;
   table->used++;
   table->used++;
-  *r_idx = idx;
+
+  *index_r = INDEX_COPY_OUT (idx);
+  if (data_r != NULL)
+    *data_r = data;
+
   return 0;
   return 0;
 }
 }
- 
+
+
+/* Deallocate the list entry index.  Afterwards, INDEX points to the
+   following entry.  This calls the deallocator on the entry before
+   returning.  */
+void
+scute_table_dealloc (scute_table_t table, int *index)
+{
+  int idx = INDEX_COPY_IN (*index);
+  void *data = NULL;
+
+  if (idx == INDEX_EOT)
+    return NULL;
+
+  assert (idx >= 0 && idx < table->last_used);
+  assert (table->data[idx] != NULL);
+
+  data = table->data[idx];
+  table->data[idx] = NULL;
+
+  table->used--;
+
+  if (idx < table->first_free)
+    table->first_free = idx;
+
+  /* Update TABLE->last_used if necessary.  */
+  if (idx + 1 == table->last_used)
+    while (table->last_used > 0)
+      {
+	if (table->data[table->last_used - 1] != NULL)
+	  break;
+	table->last_used--;
+      }
+
+  *index = INDEX_COPY_OUT (index_next (table, idx));
+
+  (*table->dealloc) (data);
+}
+
+
+/* Return the iterator for the beginning of the list TABLE.  */
+int
+scute_table_first (scute_table_t table)
+{
+  if (table->used)
+    {
+      if (table->data[0] != NULL)
+	return INDEX_COPY_OUT (0);
+      else
+	return INDEX_COPY_OUT (index_first (table));
+    }
+
+  return 0;
+}
+
+
+/* Return the index following INDEX.  If INDEX is the last element in
+   the list, return 0.  */
+int
+scute_table_next (scute_table_t table, int index)
+{
+  int idx = INDEX_COPY_IN (index);
+
+  if (idx == INDEX_EOT)
+    return 0;
+
+  idx = index_next (table, idx);
+  return INDEX_COPY_OUT (idx);
+}
+
+
+/* Return true iff INDEX is the end-of-list marker.  */
+bool
+scute_table_last (scute_table_t table, int index)
+{
+  return INDEX_COPY_IN (index) == INDEX_EOT;
+}
+
+
+/* Return the user data associated with INDEX.  Return NULL if INDEX
+   is not valid.  */
+void *
+scute_table_data (scute_table_t table, int index)
+{
+  int idx = INDEX_COPY_IN (index);
+
+  if (idx >= 0 && idx < table->last_used)
+    return table->data[idx];
+
+  return NULL;
+}
+
+
+/* Return the number of entries in the table TABLE.  */
+int
+scute_table_used (scute_table_t table)
+{
+  return table->used;
+}

+ 45 - 181
src/table.h

@@ -1,5 +1,5 @@
-/* table.h - Table abstraction interface.
-   Copyright (C) 2004, 2006 Marcus Brinkmann
+/* table.h - Iterative table interface.
+   Copyright (C) 2006 g10 Code GmbH
 
 
    This file is part of Scute[1].
    This file is part of Scute[1].
 
 
@@ -30,200 +30,64 @@
    not obligated to do so.  If you do not wish to do so, delete this
    not obligated to do so.  If you do not wish to do so, delete this
    exception statement from your version.  */
    exception statement from your version.  */
 
 
-#ifndef _HURD_TABLE_H
-#define _HURD_TABLE_H	1
+#ifndef TABLE_H
+#define TABLE_H	1
 
 
-#include <errno.h>
-#include <stdlib.h>
-#include <assert.h>
+#include <stdbool.h>
 
 
-
-/* The hurd_table data type is a fancy array.  At initialization time,
-   you have to provide the size ENTRY_SIZE of each table entry.  When
-   you enter an element, you get an index number in return.  This
-   index can be used for fast lookup of table elements.  You access
-   the table elements through pointers to the beginning of the each
-   block of ENTRY_SIZE bytes.
-
-   Embedded at the beginning of the ENTRY_SIZE bytes in each slot is a
-   void pointer.  You can use this void pointer freely for your own
-   purpose with the following restriction: In a used table entry, it
-   must never be NULL.  NULL at the beginning of a table entry
-   indicates an unused (free) table entry.
-
-   The table will grow (and eventually shrink, not yet implemented)
-   automatically.  New elements are always allocated from the
-   beginning of the table.  This means that when a new element is
-   added, the free slot with the lowest index is always used.  This
-   makes slot usage predictable and attempts to prevent fragmentation
-   and sparse usage.
-
-   Note that tables, unlike hashes, can not be reorganized, because
-   the index is not stable under reorganization.
-
-   Of all operations supported, only lookup is immediate.  Entering
-   new elements is usually fast, too, unless the first free slot is
-   unknown and has to be searched for, or there are no more free slots
-   and the table has to be enlarged.
-
-   Iterating over the used elements of the table is always
-   of the order of the table size.
-
-   In the future, removing an element can also shrink the table.  In
-   order to be able to do this, the implementation keeps track of the
-   last used slot.  For this reason, the remove operation is sometimes
-   not immediate.  */
-
-
-/* Because the first element in each table entry is a pointer, the
-   table entry should be naturally aligned.  */
-#define _HURD_TABLE_ALIGN(x) \
-  (((x) + sizeof (void *) - 1) & ~(sizeof (void *) - 1))
-
-
-/* The value used for empty table entries.  */
-#define HURD_TABLE_EMPTY	(NULL)
-
-struct hurd_table
-{
-  /* The size of one entry.  Must at least be sizeof (void *).  At the
-     beginning of each entry, a void * should be present that is
-     HURD_TABLE_EMPTY for unused elements and something else for used
-     table elements.  */
-  unsigned int entry_size;
-
-  /* The number of allocated table entries.  */
-  unsigned int size;
-
-  /* The number of table entries that are initialized.  */
-  unsigned int init_size;
-
-  /* The number of used table entries.  */
-  unsigned int used;
-
-  /* The index of the lowest entry that is unused.  */
-  unsigned int first_free;
-
-  /* The index after the highest entry that is used.  */
-  unsigned int last_used;
-
-  /* The table data.  */
-  char *data;
-};
-typedef struct hurd_table *hurd_table_t;
-
-
-#define HURD_TABLE_INITIALIZER(size_of_one)				\
-  { .entry_size = _HURD_TABLE_ALIGN (size_of_one), .size = 0,		\
-    .init_size = 0, .used = 0, .first_free = 0, .last_used = 0,		\
-    .data = NULL }
-
-/* Fast accessor without range check.  */
-#define HURD_TABLE_LOOKUP(table, idx)					\
-  ((void *) (&(table)->data[(idx) * (table)->entry_size]))
-
-/* For bound checks.  */
-#define HURD_TABLE_EXTENT(table)					\
-  ((table)->last_used)
-
-/* For bound checks.  */
-#define HURD_TABLE_USED(table)						\
-  ((table)->used)
-
-/* This is an lvalue for the pointer embedded in the table entry.  */
-#define _HURD_TABLE_ENTRY(entry)	(*(void **) (entry))
-
-#define _HURD_TABLE_ENTRY_LOOKUP(table, idx)				\
-  _HURD_TABLE_ENTRY (HURD_TABLE_LOOKUP (table, idx))
+#include <gpg-error.h>
 
 
 
 
-/* Initialize the table TABLE.  */
-error_t hurd_table_init (hurd_table_t table, unsigned int entry_size);
-
-
-/* Destroy the table TABLE.  */
-void hurd_table_destroy (hurd_table_t table);
+/* The indexed list type.  */
+struct scute_table;
+typedef struct scute_table *scute_table_t;
 
 
 
 
-/* Add the table element DATA to the table TABLE.  The index for this
-   element is returned in R_IDX.  Note that the data is added by
-   copying ENTRY_SIZE bytes into the table (the ENTRY_SIZE parameter
-   was provided at table initialization time).  */
-error_t hurd_table_enter (hurd_table_t table, void *data, unsigned int *r_idx);
+/* TABLE interface.  */
 
 
+/* A table entry allocator function callback.  Should return the new
+   table entry in DATA_R.  */
+typedef gpg_error_t (*scute_table_alloc_cb_t) (void **data_r, void *hook);
 
 
-/* Lookup the table element with the index IDX in the table TABLE.  If
-   there is no element with this index, return NULL.  Otherwise a
-   pointer to the table entry is returned.  */
-static inline void *
-hurd_table_lookup (hurd_table_t table, unsigned int idx)
-{
-  void *result;
+/* A table entry deallocator function callback.  */
+typedef void (*scute_table_dealloc_cb_t) (void *data);
 
 
-  if (idx >= table->init_size)
-    return NULL;
+/* Allocate a new table and return it in TABLE_R.  */
+gpg_error_t scute_table_create (scute_table_t *table_r,
+				scute_table_alloc_cb_t alloc,
+				scute_table_dealloc_cb_t dealloc);
 
 
-  result = HURD_TABLE_LOOKUP (table, idx);
-  if (_HURD_TABLE_ENTRY (result) == HURD_TABLE_EMPTY)
-    return NULL;
+/* Destroy the indexed list TABLE.  This also calls the deallocator on
+   all entries.  */
+void scute_table_destroy (scute_table_t table);
 
 
-  return result;
-}
+/* Allocate a new table entry with a free index.  Returns the index
+   pointing to the new list entry in INDEX_R.  This calls the
+   allocator on the new entry before returning.  Also returns the
+   table entry in *DATA_R if this is not NULL.  */
+gpg_error_t scute_table_alloc (scute_table_t table, int *index_r,
+			       void **data_r, void *hook);
 
 
+/* Deallocate the list entry index.  Afterwards, INDEX points to the
+   following entry.  This calls the deallocator on the entry before
+   returning.  */
+void scute_table_dealloc (scute_table_t table, int *index);
 
 
-/* Remove the table element with the index IDX from the table
-   TABLE.  */
-static inline void
-hurd_table_remove (hurd_table_t table, unsigned int idx)
-{
-  void *entry;
+/* Return the index for the beginning of the list TABLE.  */
+int scute_table_first (scute_table_t table);
 
 
-  assert (idx < table->init_size);
+/* Return the index following INDEX.  If INDEX is the last element in
+   the list, return 0.  */
+int scute_table_next (scute_table_t table, int index);
 
 
-  entry = HURD_TABLE_LOOKUP (table, idx);
-  assert (_HURD_TABLE_ENTRY (entry) != HURD_TABLE_EMPTY);
+/* Return true iff INDEX is the end-of-list marker.  */
+bool scute_table_last (scute_table_t table, int index);
 
 
-  _HURD_TABLE_ENTRY (entry) = HURD_TABLE_EMPTY;
+/* Return the user data associated with INDEX.  Return NULL if INDEX is
+   the end-of-list marker.  */
+void *scute_table_data (scute_table_t table, int index);
 
 
-  if (idx < table->first_free)
-    table->first_free = idx;
+/* Return the number of entries in the table TABLE.  */
+int scute_table_used (scute_table_t table);
 
 
-  if (idx + 1 == table->last_used)
-    while (table->last_used > 0)
-      {
-	if (_HURD_TABLE_ENTRY_LOOKUP (table, table->last_used - 1)
-	    != HURD_TABLE_EMPTY)
-	  break;
-	table->last_used--;
-      }
-
-  table->used--;
-}
-
-
-/* Iterate over all elements in the table.  You use this macro
-   with a block, for example like this:
-
-     error_t err;
-     HURD_TABLE_ITERATE (table, idx)
-       {
-         err = foo (idx);
-         if (err)
-           break;
-       }
-     if (err)
-       cleanup_and_return ();
-
-   Or even like this:
-
-     HURD_TABLE_ITERATE (ht, idx)
-       foo (idx);
-
-   The block will be run for every used element in the table.  Because
-   IDX is already a verified valid table index, you can lookup the
-   table entry with the fast macro HURD_TABLE_LOOKUP.  */
-#define HURD_TABLE_ITERATE(table, idx)					\
-  for (unsigned int idx = 0; idx < (table)->last_used; idx++)		\
-    if (_HURD_TABLE_ENTRY_LOOKUP ((table), (idx)) != HURD_TABLE_EMPTY)
-
-#endif	/* _HURD_TABLE_H */
+#endif	/* !TABLE_H */

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно