summaryrefslogtreecommitdiff
path: root/trust/index.c
diff options
context:
space:
mode:
Diffstat (limited to 'trust/index.c')
-rw-r--r--trust/index.c912
1 files changed, 0 insertions, 912 deletions
diff --git a/trust/index.c b/trust/index.c
deleted file mode 100644
index f4b6b4b..0000000
--- a/trust/index.c
+++ /dev/null
@@ -1,912 +0,0 @@
-/*
- * Copyright (C) 2013 Red Hat Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
- * * Redistributions in binary form must reproduce the
- * above copyright notice, this list of conditions and
- * the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- * * The names of contributors to this software may not be
- * used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * Author: Stef Walter <stefw@redhat.com>
- */
-
-#include "compat.h"
-
-#define P11_DEBUG_FLAG P11_DEBUG_TRUST
-
-#include "attrs.h"
-#include "debug.h"
-#include "dict.h"
-#include "index.h"
-#include "module.h"
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*
- * The number of buckets we use for indexing, should end up as roughly
- * equal to the expected number of unique attribute values * 0.75,
- * prime if possible. Currently we don't expand the index, so this is
- * just a good guess for general usage.
- */
-#define NUM_BUCKETS 7919
-
-/*
- * The number of indexes to use when trying to find a matching object.
- */
-#define MAX_SELECT 3
-
-typedef struct {
- CK_OBJECT_HANDLE *elem;
- int num;
-} index_bucket;
-
-struct _p11_index {
- /* The list of objects by handle */
- p11_dict *objects;
-
- /* Used for indexing */
- index_bucket *buckets;
-
- /* Data passed to callbacks */
- void *data;
-
- /* Called to build an new/modified object */
- p11_index_build_cb build;
-
- /* Called after each object ready to be stored */
- p11_index_store_cb store;
-
- /* Called after an object has been removed */
- p11_index_remove_cb remove;
-
- /* Called after objects change */
- p11_index_notify_cb notify;
-
- /* Used for queueing changes, when in a batch */
- p11_dict *changes;
- bool notifying;
-};
-
-typedef struct {
- CK_OBJECT_HANDLE handle;
- CK_ATTRIBUTE *attrs;
-} index_object;
-
-static void
-free_object (void *data)
-{
- index_object *obj = data;
- p11_attrs_free (obj->attrs);
- free (obj);
-}
-
-static CK_RV
-default_build (void *data,
- p11_index *index,
- CK_ATTRIBUTE *attrs,
- CK_ATTRIBUTE *merge,
- CK_ATTRIBUTE **populate)
-{
- return CKR_OK;
-}
-
-static CK_RV
-default_store (void *data,
- p11_index *index,
- CK_OBJECT_HANDLE handle,
- CK_ATTRIBUTE **attrs)
-{
- return CKR_OK;
-}
-
-static void
-default_notify (void *data,
- p11_index *index,
- CK_OBJECT_HANDLE handle,
- CK_ATTRIBUTE *attrs)
-{
-
-}
-
-static CK_RV
-default_remove (void *data,
- p11_index *index,
- CK_ATTRIBUTE *attrs)
-{
- return CKR_OK;
-}
-
-p11_index *
-p11_index_new (p11_index_build_cb build,
- p11_index_store_cb store,
- p11_index_remove_cb remove,
- p11_index_notify_cb notify,
- void *data)
-{
- p11_index *index;
-
- index = calloc (1, sizeof (p11_index));
- return_val_if_fail (index != NULL, NULL);
-
- if (build == NULL)
- build = default_build;
- if (store == NULL)
- store = default_store;
- if (notify == NULL)
- notify = default_notify;
- if (remove == NULL)
- remove = default_remove;
-
- index->build = build;
- index->store = store;
- index->notify = notify;
- index->remove = remove;
- index->data = data;
-
- index->objects = p11_dict_new (p11_dict_ulongptr_hash,
- p11_dict_ulongptr_equal,
- NULL, free_object);
- return_val_if_fail (index->objects != NULL, NULL);
-
- index->buckets = calloc (NUM_BUCKETS, sizeof (index_bucket));
- return_val_if_fail (index->buckets != NULL, NULL);
-
- return index;
-}
-
-void
-p11_index_free (p11_index *index)
-{
- int i;
-
- return_if_fail (index != NULL);
-
- p11_dict_free (index->objects);
- p11_dict_free (index->changes);
- for (i = 0; i < NUM_BUCKETS; i++)
- free (index->buckets[i].elem);
- free (index->buckets);
- free (index);
-}
-
-int
-p11_index_size (p11_index *index)
-{
- return_val_if_fail (index != NULL, -1);
- return p11_dict_size (index->objects);
-}
-
-static bool
-is_indexable (p11_index *index,
- CK_ATTRIBUTE_TYPE type)
-{
- switch (type) {
- case CKA_CLASS:
- case CKA_VALUE:
- case CKA_OBJECT_ID:
- case CKA_ID:
- case CKA_X_ORIGIN:
- return true;
- }
-
- return false;
-}
-
-static unsigned int
-alloc_size (int num)
-{
- unsigned int n = num ? 1 : 0;
- while (n < num && n > 0)
- n <<= 1;
- return n;
-}
-
-static int
-binary_search (CK_OBJECT_HANDLE *elem,
- int low,
- int high,
- CK_OBJECT_HANDLE handle)
-{
- int mid;
-
- if (low == high)
- return low;
-
- mid = low + ((high - low) / 2);
- if (handle > elem[mid])
- return binary_search (elem, mid + 1, high, handle);
- else if (handle < elem[mid])
- return binary_search (elem, low, mid, handle);
-
- return mid;
-}
-
-
-static void
-bucket_insert (index_bucket *bucket,
- CK_OBJECT_HANDLE handle)
-{
- unsigned int alloc;
- int at = 0;
-
- if (bucket->elem) {
- at = binary_search (bucket->elem, 0, bucket->num, handle);
- if (at < bucket->num && bucket->elem[at] == handle)
- return;
- }
-
- alloc = alloc_size (bucket->num);
- if (bucket->num + 1 > alloc) {
- alloc = alloc ? alloc * 2 : 1;
- return_if_fail (alloc != 0);
- bucket->elem = realloc (bucket->elem, alloc * sizeof (CK_OBJECT_HANDLE));
- }
-
- return_if_fail (bucket->elem != NULL);
- memmove (bucket->elem + at + 1, bucket->elem + at,
- (bucket->num - at) * sizeof (CK_OBJECT_HANDLE));
- bucket->elem[at] = handle;
- bucket->num++;
-}
-
-static bool
-bucket_push (index_bucket *bucket,
- CK_OBJECT_HANDLE handle)
-{
- unsigned int alloc;
-
- alloc = alloc_size (bucket->num);
- if (bucket->num + 1 > alloc) {
- alloc = alloc ? alloc * 2 : 1;
- return_val_if_fail (alloc != 0, false);
- bucket->elem = realloc (bucket->elem, alloc * sizeof (CK_OBJECT_HANDLE));
- }
-
- return_val_if_fail (bucket->elem != NULL, false);
- bucket->elem[bucket->num++] = handle;
- return true;
-}
-
-static void
-index_hash (p11_index *index,
- index_object *obj)
-{
- unsigned int hash;
- int i;
-
- for (i = 0; !p11_attrs_terminator (obj->attrs + i); i++) {
- if (is_indexable (index, obj->attrs[i].type)) {
- hash = p11_attr_hash (obj->attrs + i);
- bucket_insert (index->buckets + (hash % NUM_BUCKETS), obj->handle);
- }
- }
-}
-
-static void
-merge_attrs (CK_ATTRIBUTE *output,
- CK_ULONG *noutput,
- CK_ATTRIBUTE *merge,
- CK_ULONG nmerge,
- p11_array *to_free)
-{
- CK_ULONG i;
-
- for (i = 0; i < nmerge; i++) {
- /* Already have this attribute? */
- if (p11_attrs_findn (output, *noutput, merge[i].type)) {
- p11_array_push (to_free, merge[i].pValue);
-
- } else {
- memcpy (output + *noutput, merge + i, sizeof (CK_ATTRIBUTE));
- (*noutput)++;
- }
- }
-
- /* Freeing the array itself */
- p11_array_push (to_free, merge);
-}
-
-static CK_RV
-index_build (p11_index *index,
- CK_OBJECT_HANDLE handle,
- CK_ATTRIBUTE **attrs,
- CK_ATTRIBUTE *merge)
-{
- CK_ATTRIBUTE *extra = NULL;
- CK_ATTRIBUTE *built;
- p11_array *stack = NULL;
- CK_ULONG count;
- CK_ULONG nattrs;
- CK_ULONG nmerge;
- CK_ULONG nextra;
- CK_RV rv;
- int i;
-
- rv = index->build (index->data, index, *attrs, merge, &extra);
- if (rv != CKR_OK)
- return rv;
-
- /* Short circuit when nothing to merge */
- if (*attrs == NULL && extra == NULL) {
- built = merge;
- stack = NULL;
-
- } else {
- stack = p11_array_new (NULL);
- nattrs = p11_attrs_count (*attrs);
- nmerge = p11_attrs_count (merge);
- nextra = p11_attrs_count (extra);
-
- /* Make a shallow copy of the combined attributes for validation */
- built = calloc (nmerge + nattrs + nextra + 1, sizeof (CK_ATTRIBUTE));
- return_val_if_fail (built != NULL, CKR_GENERAL_ERROR);
-
- count = nmerge;
- memcpy (built, merge, sizeof (CK_ATTRIBUTE) * nmerge);
- p11_array_push (stack, merge);
- merge_attrs (built, &count, *attrs, nattrs, stack);
- merge_attrs (built, &count, extra, nextra, stack);
-
- /* The terminator attribute */
- built[count].type = CKA_INVALID;
- assert (p11_attrs_terminator (built + count));
- }
-
- rv = index->store (index->data, index, handle, &built);
-
- if (rv == CKR_OK) {
- for (i = 0; stack && i < stack->num; i++)
- free (stack->elem[i]);
- *attrs = built;
- } else {
- p11_attrs_free (extra);
- free (built);
- }
-
- p11_array_free (stack);
- return rv;
-}
-
-static void
-call_notify (p11_index *index,
- CK_OBJECT_HANDLE handle,
- CK_ATTRIBUTE *attrs)
-{
- assert (index->notify);
-
- /* When attrs is NULL, means this is a modify */
- if (attrs == NULL) {
- attrs = p11_index_lookup (index, handle);
- if (attrs == NULL)
- return;
-
- /* Otherwise a remove operation, handle not valid anymore */
- } else {
- handle = 0;
- }
-
- index->notifying = true;
- index->notify (index->data, index, handle, attrs);
- index->notifying = false;
-}
-
-static void
-index_notify (p11_index *index,
- CK_OBJECT_HANDLE handle,
- CK_ATTRIBUTE *removed)
-{
- index_object *obj;
-
- if (!index->notify || index->notifying) {
- p11_attrs_free (removed);
-
- } else if (!index->changes) {
- call_notify (index, handle, removed);
- p11_attrs_free (removed);
-
- } else {
- obj = calloc (1, sizeof (index_object));
- return_if_fail (obj != NULL);
-
- obj->handle = handle;
- obj->attrs = removed;
- if (!p11_dict_set (index->changes, &obj->handle, obj))
- return_if_reached ();
- }
-}
-
-void
-p11_index_load (p11_index *index)
-{
- return_if_fail (index != NULL);
-
- if (index->changes)
- return;
-
- index->changes = p11_dict_new (p11_dict_ulongptr_hash,
- p11_dict_ulongptr_equal,
- NULL, free_object);
- return_if_fail (index->changes != NULL);
-}
-
-void
-p11_index_finish (p11_index *index)
-{
- p11_dict *changes;
- index_object *obj;
- p11_dictiter iter;
-
- return_if_fail (index != NULL);
-
- if (!index->changes)
- return;
-
- changes = index->changes;
- index->changes = NULL;
-
- p11_dict_iterate (changes, &iter);
- while (p11_dict_next (&iter, NULL, (void **)&obj)) {
- index_notify (index, obj->handle, obj->attrs);
- obj->attrs = NULL;
- }
-
- p11_dict_free (changes);
-}
-
-bool
-p11_index_loading (p11_index *index)
-{
- return_val_if_fail (index != NULL, false);
- return index->changes ? true : false;
-}
-
-CK_RV
-p11_index_take (p11_index *index,
- CK_ATTRIBUTE *attrs,
- CK_OBJECT_HANDLE *handle)
-{
- index_object *obj;
- CK_RV rv;
-
- return_val_if_fail (index != NULL, CKR_GENERAL_ERROR);
- return_val_if_fail (attrs != NULL, CKR_GENERAL_ERROR);
-
- obj = calloc (1, sizeof (index_object));
- return_val_if_fail (obj != NULL, CKR_HOST_MEMORY);
-
- obj->handle = p11_module_next_id ();
-
- rv = index_build (index, obj->handle, &obj->attrs, attrs);
- if (rv != CKR_OK) {
- p11_attrs_free (attrs);
- free (obj);
- return rv;
- }
-
- return_val_if_fail (obj->attrs != NULL, CKR_GENERAL_ERROR);
-
- if (!p11_dict_set (index->objects, &obj->handle, obj))
- return_val_if_reached (CKR_HOST_MEMORY);
-
- index_hash (index, obj);
-
- if (handle)
- *handle = obj->handle;
-
- index_notify (index, obj->handle, NULL);
- return CKR_OK;
-}
-
-CK_RV
-p11_index_add (p11_index *index,
- CK_ATTRIBUTE *attrs,
- CK_ULONG count,
- CK_OBJECT_HANDLE *handle)
-{
- CK_ATTRIBUTE *copy;
-
- return_val_if_fail (index != NULL, CKR_GENERAL_ERROR);
- return_val_if_fail (attrs == NULL || count > 0, CKR_ARGUMENTS_BAD);
-
- copy = p11_attrs_buildn (NULL, attrs, count);
- return_val_if_fail (copy != NULL, CKR_HOST_MEMORY);
-
- return p11_index_take (index, copy, handle);
-}
-
-CK_RV
-p11_index_update (p11_index *index,
- CK_OBJECT_HANDLE handle,
- CK_ATTRIBUTE *update)
-{
- index_object *obj;
- CK_RV rv;
-
- return_val_if_fail (index != NULL, CKR_GENERAL_ERROR);
- return_val_if_fail (update != NULL, CKR_GENERAL_ERROR);
-
- obj = p11_dict_get (index->objects, &handle);
- if (obj == NULL) {
- p11_attrs_free (update);
- return CKR_OBJECT_HANDLE_INVALID;
- }
-
- rv = index_build (index, obj->handle, &obj->attrs, update);
- if (rv != CKR_OK) {
- p11_attrs_free (update);
- return rv;
- }
-
- index_hash (index, obj);
- index_notify (index, obj->handle, NULL);
-
- return CKR_OK;
-}
-
-CK_RV
-p11_index_set (p11_index *index,
- CK_OBJECT_HANDLE handle,
- CK_ATTRIBUTE *attrs,
- CK_ULONG count)
-{
- CK_ATTRIBUTE *update;
- index_object *obj;
-
- return_val_if_fail (index != NULL, CKR_GENERAL_ERROR);
-
- obj = p11_dict_get (index->objects, &handle);
- if (obj == NULL)
- return CKR_OBJECT_HANDLE_INVALID;
-
- update = p11_attrs_buildn (NULL, attrs, count);
- return_val_if_fail (update != NULL, CKR_HOST_MEMORY);
-
- return p11_index_update (index, handle, update);
-}
-
-CK_RV
-p11_index_remove (p11_index *index,
- CK_OBJECT_HANDLE handle)
-{
- index_object *obj;
- CK_RV rv;
-
- return_val_if_fail (index != NULL, CKR_GENERAL_ERROR);
-
- if (!p11_dict_steal (index->objects, &handle, NULL, (void **)&obj))
- return CKR_OBJECT_HANDLE_INVALID;
-
- rv = (index->remove) (index->data, index, obj->attrs);
-
- /* If the writer failed the remove, then add it back */
- if (rv != CKR_OK) {
- if (!p11_dict_set (index->objects, &obj->handle, obj))
- return_val_if_reached (CKR_HOST_MEMORY);
- return rv;
- }
-
- /* This takes ownership of the attributes */
- index_notify (index, handle, obj->attrs);
- obj->attrs = NULL;
- free_object (obj);
-
- return CKR_OK;
-}
-
-static CK_RV
-index_replacev (p11_index *index,
- CK_OBJECT_HANDLE *handles,
- CK_ATTRIBUTE_TYPE key,
- CK_ATTRIBUTE **replace,
- CK_ULONG replacen)
-{
- index_object *obj;
- CK_ATTRIBUTE *attrs;
- CK_ATTRIBUTE *attr;
- bool handled = false;
- CK_RV rv;
- int i, j;
-
- for (i = 0; handles && handles[i] != 0; i++) {
- obj = p11_dict_get (index->objects, handles + i);
- if (obj == NULL)
- continue;
-
- handled = false;
- attr = p11_attrs_find (obj->attrs, key);
-
- /* The match doesn't have the key, so remove it */
- if (attr != NULL) {
- for (j = 0; j < replacen; j++) {
- if (!replace[j])
- continue;
- if (p11_attrs_matchn (replace[j], attr, 1)) {
- attrs = NULL;
- rv = index_build (index, obj->handle, &attrs, replace[j]);
- if (rv != CKR_OK)
- return rv;
- p11_attrs_free (obj->attrs);
- obj->attrs = attrs;
- replace[j] = NULL;
- handled = true;
- index_hash (index, obj);
- index_notify (index, obj->handle, NULL);
- break;
- }
- }
- }
-
- if (!handled) {
- rv = p11_index_remove (index, handles[i]);
- if (rv != CKR_OK)
- return rv;
- }
- }
-
- for (j = 0; j < replacen; j++) {
- if (!replace[j])
- continue;
- attrs = replace[j];
- replace[j] = NULL;
- rv = p11_index_take (index, attrs, NULL);
- if (rv != CKR_OK)
- return rv;
- }
-
- return CKR_OK;
-}
-
-CK_RV
-p11_index_replace (p11_index *index,
- CK_OBJECT_HANDLE handle,
- CK_ATTRIBUTE *replace)
-{
- CK_OBJECT_HANDLE handles[] = { handle, 0 };
- return_val_if_fail (index != NULL, CKR_GENERAL_ERROR);
- return index_replacev (index, handles, CKA_INVALID,
- &replace, replace ? 1 : 0);
-}
-
-CK_RV
-p11_index_replace_all (p11_index *index,
- CK_ATTRIBUTE *match,
- CK_ATTRIBUTE_TYPE key,
- p11_array *replace)
-{
- CK_OBJECT_HANDLE *handles;
- CK_RV rv;
- int i;
-
- return_val_if_fail (index != NULL, CKR_GENERAL_ERROR);
-
- handles = p11_index_find_all (index, match, -1);
-
- rv = index_replacev (index, handles, key,
- replace ? (CK_ATTRIBUTE **)replace->elem : NULL,
- replace ? replace->num : 0);
-
- if (rv == CKR_OK) {
- if (replace)
- p11_array_clear (replace);
- } else {
- for (i = 0; replace && i < replace->num; i++) {
- if (!replace->elem[i]) {
- p11_array_remove (replace, i);
- i--;
- }
- }
- }
-
- free (handles);
- return rv;
-}
-
-CK_ATTRIBUTE *
-p11_index_lookup (p11_index *index,
- CK_OBJECT_HANDLE handle)
-{
- index_object *obj;
-
- return_val_if_fail (index != NULL, NULL);
-
- if (handle == CK_INVALID_HANDLE)
- return NULL;
-
- obj = p11_dict_get (index->objects, &handle);
- return obj ? obj->attrs : NULL;
-}
-
-typedef bool (* index_sink) (p11_index *index,
- index_object *obj,
- CK_ATTRIBUTE *match,
- CK_ULONG count,
- void *data);
-
-static void
-index_select (p11_index *index,
- CK_ATTRIBUTE *match,
- CK_ULONG count,
- index_sink sink,
- void *data)
-{
- index_bucket *selected[MAX_SELECT];
- CK_OBJECT_HANDLE handle;
- index_object *obj;
- unsigned int hash;
- p11_dictiter iter;
- CK_ULONG n;
- int num, at;
- int i, j;
-
- /* First look for any matching buckets */
- for (n = 0, num = 0; n < count && num < MAX_SELECT; n++) {
- if (is_indexable (index, match[n].type)) {
- hash = p11_attr_hash (match + n);
- selected[num] = index->buckets + (hash % NUM_BUCKETS);
-
- /* If any index is empty, then obviously no match */
- if (!selected[num]->num)
- return;
-
- num++;
- }
- }
-
- /* Fall back on selecting all the items, if no index */
- if (num == 0) {
- p11_dict_iterate (index->objects, &iter);
- while (p11_dict_next (&iter, NULL, (void *)&obj)) {
- if (!sink (index, obj, match, count, data))
- return;
- }
- return;
- }
-
- for (i = 0; i < selected[0]->num; i++) {
- /* A candidate match from first bucket */
- handle = selected[0]->elem[i];
-
- /* Check if the candidate is in other buckets */
- for (j = 1; j < num; j++) {
- assert (selected[j]->elem); /* checked above */
- at = binary_search (selected[j]->elem, 0, selected[j]->num, handle);
- if (at >= selected[j]->num || selected[j]->elem[at] != handle) {
- handle = 0;
- break;
- }
- }
-
- /* Matched all the buckets, now actually match attrs */
- if (handle != 0) {
- obj = p11_dict_get (index->objects, &handle);
- if (obj != NULL) {
- if (!sink (index, obj, match, count, data))
- return;
- }
- }
- }
-}
-
-static bool
-sink_one_match (p11_index *index,
- index_object *obj,
- CK_ATTRIBUTE *match,
- CK_ULONG count,
- void *data)
-{
- CK_OBJECT_HANDLE *result = data;
-
- if (p11_attrs_matchn (obj->attrs, match, count)) {
- *result = obj->handle;
- return false;
- }
-
- return true;
-}
-
-CK_OBJECT_HANDLE
-p11_index_find (p11_index *index,
- CK_ATTRIBUTE *match,
- int count)
-{
- CK_OBJECT_HANDLE handle = 0UL;
-
- return_val_if_fail (index != NULL, 0UL);
-
- if (count < 0)
- count = p11_attrs_count (match);
-
- index_select (index, match, count, sink_one_match, &handle);
- return handle;
-}
-
-static bool
-sink_if_match (p11_index *index,
- index_object *obj,
- CK_ATTRIBUTE *match,
- CK_ULONG count,
- void *data)
-{
- index_bucket *handles = data;
-
- if (p11_attrs_matchn (obj->attrs, match, count))
- bucket_push (handles, obj->handle);
- return true;
-}
-
-CK_OBJECT_HANDLE *
-p11_index_find_all (p11_index *index,
- CK_ATTRIBUTE *match,
- int count)
-{
- index_bucket handles = { NULL, 0 };
-
- return_val_if_fail (index != NULL, NULL);
-
- if (count < 0)
- count = p11_attrs_count (match);
-
- index_select (index, match, count, sink_if_match, &handles);
-
- /* Null terminate */
- bucket_push (&handles, 0UL);
- return handles.elem;
-}
-
-static bool
-sink_any (p11_index *index,
- index_object *obj,
- CK_ATTRIBUTE *match,
- CK_ULONG count,
- void *data)
-{
- index_bucket *handles = data;
- bucket_push (handles, obj->handle);
- return true;
-}
-
-CK_OBJECT_HANDLE *
-p11_index_snapshot (p11_index *index,
- p11_index *base,
- CK_ATTRIBUTE *attrs,
- CK_ULONG count)
-{
- index_bucket handles = { NULL, 0 };
-
- return_val_if_fail (index != NULL, NULL);
-
- if (count < (CK_ULONG)0UL)
- count = p11_attrs_count (attrs);
-
- index_select (index, attrs, count, sink_any, &handles);
- if (base)
- index_select (base, attrs, count, sink_any, &handles);
-
- /* Null terminate */
- bucket_push (&handles, 0UL);
- return handles.elem;
-}