Move CCAPI sources to krb5 repository
authorAlexandra Ellwood <lxs@mit.edu>
Thu, 31 May 2007 21:06:54 +0000 (21:06 +0000)
committerAlexandra Ellwood <lxs@mit.edu>
Thu, 31 May 2007 21:06:54 +0000 (21:06 +0000)
ticket: new
status: open

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19564 dc483132-0cff-0310-8789-dd5450dbe970

133 files changed:
src/ccapi/common/cci_array_internal.c [new file with mode: 0644]
src/ccapi/common/cci_array_internal.h [new file with mode: 0644]
src/ccapi/common/cci_common.h [new file with mode: 0644]
src/ccapi/common/cci_cred_union.c [new file with mode: 0644]
src/ccapi/common/cci_cred_union.h [new file with mode: 0644]
src/ccapi/common/cci_debugging.c [new file with mode: 0644]
src/ccapi/common/cci_debugging.h [new file with mode: 0644]
src/ccapi/common/cci_identifier.c [new file with mode: 0644]
src/ccapi/common/cci_identifier.h [new file with mode: 0644]
src/ccapi/common/cci_message.c [new file with mode: 0644]
src/ccapi/common/cci_message.h [new file with mode: 0644]
src/ccapi/common/cci_os_debugging.h [new file with mode: 0644]
src/ccapi/common/cci_os_identifier.h [new file with mode: 0644]
src/ccapi/common/cci_stream.c [new file with mode: 0644]
src/ccapi/common/cci_stream.h [new file with mode: 0644]
src/ccapi/common/cci_types.h [new file with mode: 0644]
src/ccapi/common/mac/cci_mig.defs [new file with mode: 0644]
src/ccapi/common/mac/cci_mig_reply.defs [new file with mode: 0644]
src/ccapi/common/mac/cci_mig_request.defs [new file with mode: 0644]
src/ccapi/common/mac/cci_mig_types.h [new file with mode: 0644]
src/ccapi/common/mac/cci_os_debugging.c [new file with mode: 0644]
src/ccapi/common/mac/cci_os_identifier.c [new file with mode: 0644]
src/ccapi/lib/ccapi.exports [new file with mode: 0644]
src/ccapi/lib/ccapi_ccache.c [new file with mode: 0644]
src/ccapi/lib/ccapi_ccache.h [new file with mode: 0644]
src/ccapi/lib/ccapi_ccache_iterator.c [new file with mode: 0644]
src/ccapi/lib/ccapi_ccache_iterator.h [new file with mode: 0644]
src/ccapi/lib/ccapi_context.c [new file with mode: 0644]
src/ccapi/lib/ccapi_context.h [new file with mode: 0644]
src/ccapi/lib/ccapi_context_change_time.c [new file with mode: 0644]
src/ccapi/lib/ccapi_context_change_time.h [new file with mode: 0644]
src/ccapi/lib/ccapi_credentials.c [new file with mode: 0644]
src/ccapi/lib/ccapi_credentials.h [new file with mode: 0644]
src/ccapi/lib/ccapi_credentials_iterator.c [new file with mode: 0644]
src/ccapi/lib/ccapi_credentials_iterator.h [new file with mode: 0644]
src/ccapi/lib/ccapi_err.et [new file with mode: 0644]
src/ccapi/lib/ccapi_ipc.c [new file with mode: 0644]
src/ccapi/lib/ccapi_ipc.h [new file with mode: 0644]
src/ccapi/lib/ccapi_os_ipc.h [new file with mode: 0644]
src/ccapi/lib/ccapi_string.c [new file with mode: 0644]
src/ccapi/lib/ccapi_string.h [new file with mode: 0644]
src/ccapi/lib/ccapi_v2.c [new file with mode: 0644]
src/ccapi/lib/ccapi_v2.exports [new file with mode: 0644]
src/ccapi/lib/mac/ccapi_os_ipc.c [new file with mode: 0644]
src/ccapi/lib/mac/ccapi_vector.c [new file with mode: 0644]
src/ccapi/lib/mac/ccapi_vector.exports [new file with mode: 0644]
src/ccapi/lib/mac/ccapi_vector.h [new file with mode: 0644]
src/ccapi/server/ccs_array.c [new file with mode: 0644]
src/ccapi/server/ccs_array.h [new file with mode: 0644]
src/ccapi/server/ccs_cache_collection.c [new file with mode: 0644]
src/ccapi/server/ccs_cache_collection.h [new file with mode: 0644]
src/ccapi/server/ccs_ccache.c [new file with mode: 0644]
src/ccapi/server/ccs_ccache.h [new file with mode: 0644]
src/ccapi/server/ccs_ccache_iterator.c [new file with mode: 0644]
src/ccapi/server/ccs_ccache_iterator.h [new file with mode: 0644]
src/ccapi/server/ccs_common.h [new file with mode: 0644]
src/ccapi/server/ccs_credentials.c [new file with mode: 0644]
src/ccapi/server/ccs_credentials.h [new file with mode: 0644]
src/ccapi/server/ccs_credentials_iterator.c [new file with mode: 0644]
src/ccapi/server/ccs_credentials_iterator.h [new file with mode: 0644]
src/ccapi/server/ccs_list.c [new file with mode: 0644]
src/ccapi/server/ccs_list.h [new file with mode: 0644]
src/ccapi/server/ccs_list_internal.c [new file with mode: 0644]
src/ccapi/server/ccs_list_internal.h [new file with mode: 0644]
src/ccapi/server/ccs_lock.c [new file with mode: 0644]
src/ccapi/server/ccs_lock.h [new file with mode: 0644]
src/ccapi/server/ccs_lock_state.c [new file with mode: 0644]
src/ccapi/server/ccs_lock_state.h [new file with mode: 0644]
src/ccapi/server/ccs_os_pipe.h [new file with mode: 0644]
src/ccapi/server/ccs_os_server.h [new file with mode: 0644]
src/ccapi/server/ccs_pipe.c [new file with mode: 0644]
src/ccapi/server/ccs_pipe.h [new file with mode: 0644]
src/ccapi/server/ccs_server.c [new file with mode: 0644]
src/ccapi/server/ccs_server.h [new file with mode: 0644]
src/ccapi/server/ccs_types.h [new file with mode: 0644]
src/ccapi/server/mac/CCacheServerInfo.plist [new file with mode: 0644]
src/ccapi/server/mac/ccs_os_pipe.c [new file with mode: 0644]
src/ccapi/server/mac/edu.mit.Kerberos.CCacheServer.plist [new file with mode: 0644]
src/ccapi/server/mac/main.c [new file with mode: 0644]
src/ccapi/test/Makefile [new file with mode: 0644]
src/ccapi/test/main.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_compare.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_destroy.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_get_change_time.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_get_credentials_version.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_get_last_default_time.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_get_name.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_get_principal.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_iterator_next.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_move.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_new_credentials_iterator.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_release.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_remove_credentials.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_set_default.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_set_principal.c [new file with mode: 0644]
src/ccapi/test/test_cc_ccache_store_credentials.c [new file with mode: 0644]
src/ccapi/test/test_cc_context_compare.c [new file with mode: 0644]
src/ccapi/test/test_cc_context_create_ccache.c [new file with mode: 0644]
src/ccapi/test/test_cc_context_create_default_ccache.c [new file with mode: 0644]
src/ccapi/test/test_cc_context_create_new_ccache.c [new file with mode: 0644]
src/ccapi/test/test_cc_context_get_change_time.c [new file with mode: 0644]
src/ccapi/test/test_cc_context_get_default_ccache_name.c [new file with mode: 0644]
src/ccapi/test/test_cc_context_get_version.c [new file with mode: 0644]
src/ccapi/test/test_cc_context_new_ccache_iterator.c [new file with mode: 0644]
src/ccapi/test/test_cc_context_open_ccache.c [new file with mode: 0644]
src/ccapi/test/test_cc_context_open_default_ccache.c [new file with mode: 0644]
src/ccapi/test/test_cc_context_release.c [new file with mode: 0644]
src/ccapi/test/test_cc_credentials_iterator_next.c [new file with mode: 0644]
src/ccapi/test/test_cc_initialize.c [new file with mode: 0644]
src/ccapi/test/test_ccapi_ccache.c [new file with mode: 0644]
src/ccapi/test/test_ccapi_ccache.h [new file with mode: 0644]
src/ccapi/test/test_ccapi_check.c [new file with mode: 0644]
src/ccapi/test/test_ccapi_check.h [new file with mode: 0644]
src/ccapi/test/test_ccapi_constants.c [new file with mode: 0644]
src/ccapi/test/test_ccapi_constants.h [new file with mode: 0644]
src/ccapi/test/test_ccapi_context.c [new file with mode: 0644]
src/ccapi/test/test_ccapi_context.h [new file with mode: 0644]
src/ccapi/test/test_ccapi_globals.c [new file with mode: 0644]
src/ccapi/test/test_ccapi_globals.h [new file with mode: 0644]
src/ccapi/test/test_ccapi_iterators.c [new file with mode: 0644]
src/ccapi/test/test_ccapi_iterators.h [new file with mode: 0644]
src/ccapi/test/test_ccapi_log.c [new file with mode: 0644]
src/ccapi/test/test_ccapi_log.h [new file with mode: 0644]
src/ccapi/test/test_ccapi_util.c [new file with mode: 0644]
src/ccapi/test/test_ccapi_util.h [new file with mode: 0644]
src/ccapi/test/test_constants.c [new file with mode: 0644]
src/include/CredentialsCache.h [new file with mode: 0644]
src/include/CredentialsCache2.h [new file with mode: 0644]
src/lib/krb5/ccache/ccapi/stdcc.c
src/lib/krb5/krb/rd_req_dec.c

diff --git a/src/ccapi/common/cci_array_internal.c b/src/ccapi/common/cci_array_internal.c
new file mode 100644 (file)
index 0000000..8e6bcd7
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "cci_common.h"
+#include "cci_array_internal.h"
+
+/* ------------------------------------------------------------------------ */
+
+struct cci_array_d {
+    cci_array_object_t *objects;
+    cc_uint64 count;
+    cc_uint64 max_count;
+    
+    cci_array_object_release_t object_release;
+};
+
+struct cci_array_d cci_array_initializer = { NULL, 0, 0, NULL };
+
+#define CCI_ARRAY_COUNT_INCREMENT 16
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 cci_array_resize (cci_array_t io_array,
+                                  cc_uint64   in_new_count)
+{
+    cc_int32 err = ccNoError;
+    cc_uint64 new_max_count = 0;
+    cci_array_object_t *objects = NULL;
+    
+    if (!io_array) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        cc_uint64 old_max_count = io_array->max_count;
+        new_max_count = io_array->max_count;
+        
+        if (in_new_count > old_max_count) {
+            /* Expand the array */
+            while (in_new_count > new_max_count) {
+                new_max_count += CCI_ARRAY_COUNT_INCREMENT;
+            }
+            
+        } else if ((in_new_count + CCI_ARRAY_COUNT_INCREMENT) < old_max_count) {
+            /* Shrink the array, but never drop below CC_ARRAY_COUNT_INCREMENT */
+            while ((in_new_count + CCI_ARRAY_COUNT_INCREMENT) < new_max_count &&
+                   (new_max_count > CCI_ARRAY_COUNT_INCREMENT)) {
+                new_max_count -= CCI_ARRAY_COUNT_INCREMENT;
+            }
+        }
+    }
+    
+    if (!err) {
+        objects = io_array->objects;
+        
+        if (!objects) {
+            objects = malloc (new_max_count * sizeof (*objects));
+        } else {
+            objects = realloc (objects, new_max_count * sizeof (*objects));
+        }
+        if (!objects) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        io_array->objects = objects;
+        io_array->max_count = new_max_count;
+    }
+    
+    return cci_check_error (err); 
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_new (cci_array_t                *out_array,
+                        cci_array_object_release_t  in_array_object_release)
+{
+    cc_int32 err = ccNoError;
+    cci_array_t array = NULL;
+    
+    if (!out_array) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        array = malloc (sizeof (*array));
+        if (array) { 
+            *array = cci_array_initializer;
+            array->object_release = in_array_object_release;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        *out_array = array;
+        array = NULL;
+    }
+    
+    cci_array_release (array);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_release (cci_array_t io_array)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_array) { err = ccErrBadParam; }
+    
+    if (!err) {
+        cc_uint64 i;
+        
+        for (i = 0; i < io_array->count; i++) {
+            io_array->object_release (io_array->objects[i]);
+        }
+        free (io_array->objects);
+        free (io_array);
+    }
+    
+    return err;        
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint64 cci_array_count (cci_array_t in_array)
+{
+    return in_array ? in_array->count : 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cci_array_object_t cci_array_object_at_index (cci_array_t io_array,
+                                              cc_uint64   in_position)
+{
+    if (io_array && in_position < io_array->count) {
+        return io_array->objects[in_position];
+    } else {
+        if (!io_array) {
+            cci_debug_printf ("%s() got NULL array", __FUNCTION__);
+        } else {
+            cci_debug_printf ("%s() got bad index %lld (count = %lld)", __FUNCTION__, 
+                              in_position, io_array->count);
+        }     
+        return NULL;
+    }
+}
+
+#pragma mark -
+    
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_insert (cci_array_t        io_array,
+                           cci_array_object_t in_object,
+                           cc_uint64          in_position)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_array ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_object) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        /* Don't try to insert past the end and don't overflow the array */
+        if (in_position > io_array->count || io_array->count == UINT64_MAX) {
+            err = cci_check_error (ccErrBadParam);
+        }
+    }
+    
+    if (!err) {
+        err = cci_array_resize (io_array, io_array->count + 1);
+    }
+    
+    if (!err) {
+        unsigned char **objects = (unsigned char **)io_array->objects;
+        cc_uint64 move_count = io_array->count - in_position;
+        
+        if (move_count > 0) {
+            memmove (&objects[in_position + 1], &objects[in_position],
+                     move_count * sizeof (*objects));
+        }
+        
+        objects[in_position] = in_object;
+        io_array->count++;
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_remove (cci_array_t io_array,
+                           cc_uint64   in_position)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_array) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err && in_position >= io_array->count) {
+        err = cci_check_error (ccErrBadParam);
+    }
+    
+    if (!err) {
+        unsigned char **objects = (unsigned char **)io_array->objects;
+        cc_uint64 move_count = io_array->count - in_position - 1;
+        cci_array_object_t object = objects[in_position];
+        
+        if (move_count > 0) {
+            memmove (&objects[in_position], &objects[in_position + 1],
+                     move_count * sizeof (*objects));
+        }
+        
+        io_array->object_release (object);
+        io_array->count--;
+        
+        cci_array_resize (io_array, io_array->count);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_move (cci_array_t  io_array,
+                         cc_uint64    in_position,
+                         cc_uint64    in_new_position,
+                         cc_uint64   *out_real_new_position)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_array             ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_real_new_position) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err && in_position >= io_array->count) {
+        err = cci_check_error (ccErrBadParam);
+    }
+    
+    if (!err && in_new_position > io_array->count) {
+        err = cci_check_error (ccErrBadParam);
+    }
+    if (!err) {
+        cc_uint64 move_from = 0;
+        cc_uint64 move_to = 0;
+        cc_uint64 move_count = 0;
+        cc_uint64 real_new_position = 0;
+        
+        if (in_position < in_new_position) {
+            /* shift right, making an empty space so the
+             * actual new position is one less in_new_position */
+            move_from = in_position + 1;
+            move_to = in_position;
+            move_count = in_new_position - in_position - 1;
+            real_new_position = in_new_position - 1;
+        } else {
+            /* shift left */
+            move_from = in_new_position;
+            move_to = in_new_position + 1;
+            move_count = in_position - in_new_position;     
+            real_new_position = in_new_position;
+        }
+        
+        if (move_count > 0) {
+            unsigned char **objects = (unsigned char **)io_array->objects;
+            cci_array_object_t object = objects[in_position];
+            
+            memmove (&objects[move_to], &objects[move_from], 
+                     move_count * sizeof (*objects));
+            objects[real_new_position] = object;
+        }
+        
+        *out_real_new_position = real_new_position;
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_array_push_front (cci_array_t io_array,
+                               cc_uint64   in_position)
+{
+    cc_uint64 real_new_position = 0;
+    return cci_array_move (io_array, in_position, 0, &real_new_position);
+}
+
diff --git a/src/ccapi/common/cci_array_internal.h b/src/ccapi/common/cci_array_internal.h
new file mode 100644 (file)
index 0000000..a88e529
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCI_ARRAY_INTERNAL_H
+#define CCI_ARRAY_INTERNAL_H
+
+#include "cci_types.h"
+
+typedef void *cci_array_object_t;
+typedef cc_int32 (*cci_array_object_release_t) (cci_array_object_t);
+
+struct cci_array_d;
+typedef struct cci_array_d *cci_array_t;
+
+cc_int32 cci_array_new (cci_array_t                *out_array,
+                        cci_array_object_release_t  in_array_object_release);
+
+cc_int32 cci_array_release (cci_array_t io_array);
+
+cc_uint64 cci_array_count (cci_array_t in_array);
+
+cci_array_object_t cci_array_object_at_index (cci_array_t io_array,
+                                              cc_uint64   in_position);
+
+cc_int32 cci_array_insert (cci_array_t        io_array,
+                           cci_array_object_t in_object,
+                           cc_uint64          in_position);
+
+cc_int32 cci_array_remove (cci_array_t io_array,
+                           cc_uint64   in_position);
+
+cc_int32 cci_array_move (cci_array_t  io_array,
+                         cc_uint64    in_position,
+                         cc_uint64    in_new_position,
+                         cc_uint64   *out_real_new_position);
+
+cc_int32 cci_array_push_front (cci_array_t io_array,
+                               cc_uint64   in_position);
+
+
+#endif /* CCI_ARRAY_INTERNAL_H */
diff --git a/src/ccapi/common/cci_common.h b/src/ccapi/common/cci_common.h
new file mode 100644 (file)
index 0000000..a77b16c
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCI_COMMON_H
+#define CCI_COMMON_H
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <com_err.h>
+
+#include <CredentialsCache.h>
+
+#if TARGET_OS_MAC
+#define VECTOR_FUNCTIONS_INITIALIZER ,NULL
+#else
+#define VECTOR_FUNCTIONS_INITIALIZER
+#endif
+
+#define k_cci_context_initial_ccache_name "Initial default ccache"
+
+#include "cci_cred_union.h"
+#include "cci_debugging.h"
+#include "cci_identifier.h"
+#include "cci_message.h"
+#include "cci_stream.h"
+
+#endif /* CCI_COMMON_H */
diff --git a/src/ccapi/common/cci_cred_union.c b/src/ccapi/common/cci_cred_union.c
new file mode 100644 (file)
index 0000000..74a87a6
--- /dev/null
@@ -0,0 +1,679 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "cci_common.h"
+
+#pragma mark - 
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v4_release (cc_credentials_v4_t *io_v4creds)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_v4creds) { err = ccErrBadParam; }
+    
+    if (!err) {
+        memset (io_v4creds, 0, sizeof (*io_v4creds));
+        free (io_v4creds);
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v4_read (cc_credentials_v4_t **out_v4creds,
+                                          cci_stream_t          io_stream)
+{
+    cc_int32 err = ccNoError;
+    cc_credentials_v4_t *v4creds = NULL;
+    
+    if (!io_stream  ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_v4creds) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        v4creds = malloc (sizeof (*v4creds));
+        if (!v4creds) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (io_stream, &v4creds->version);
+    }
+    
+    if (!err) {
+        err = cci_stream_read (io_stream, v4creds->principal, cc_v4_name_size);
+    }
+    
+    if (!err) {
+        err = cci_stream_read (io_stream, v4creds->principal_instance, cc_v4_instance_size);
+    }
+    
+    if (!err) {
+        err = cci_stream_read (io_stream, v4creds->service, cc_v4_name_size);
+    }
+    
+    if (!err) {
+        err = cci_stream_read (io_stream, v4creds->service_instance, cc_v4_instance_size);
+    }
+    
+    if (!err) {
+        err = cci_stream_read (io_stream, v4creds->realm, cc_v4_realm_size);
+    }
+    
+    if (!err) {
+        err = cci_stream_read (io_stream, v4creds->session_key, cc_v4_key_size);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_int32 (io_stream, &v4creds->kvno);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_int32 (io_stream, &v4creds->string_to_key_type);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_time (io_stream, &v4creds->issue_date);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_int32 (io_stream, &v4creds->lifetime);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (io_stream, &v4creds->address);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_int32 (io_stream, &v4creds->ticket_size);
+    }
+    
+    if (!err) {
+        err = cci_stream_read (io_stream, v4creds->ticket, cc_v4_ticket_size);
+    }
+    
+    if (!err) {
+        *out_v4creds = v4creds;
+        v4creds = NULL;
+    }
+    
+    free (v4creds);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v4_write (cc_credentials_v4_t *in_v4creds,
+                                           cci_stream_t         io_stream)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_v4creds) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (io_stream, in_v4creds->version);
+    }
+    
+    if (!err) {
+        err = cci_stream_write (io_stream, in_v4creds->principal, cc_v4_name_size);
+    }
+    
+    if (!err) {
+        err = cci_stream_write (io_stream, in_v4creds->principal_instance, cc_v4_instance_size);
+    }
+    
+    if (!err) {
+        err = cci_stream_write (io_stream, in_v4creds->service, cc_v4_name_size);
+    }
+    
+    if (!err) {
+        err = cci_stream_write (io_stream, in_v4creds->service_instance, cc_v4_instance_size);
+    }
+    
+    if (!err) {
+        err = cci_stream_write (io_stream, in_v4creds->realm, cc_v4_realm_size);
+    }
+    
+    if (!err) {
+        err = cci_stream_write (io_stream, in_v4creds->session_key, cc_v4_key_size);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_int32 (io_stream, in_v4creds->kvno);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_int32 (io_stream, in_v4creds->string_to_key_type);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_time (io_stream, in_v4creds->issue_date);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_int32 (io_stream, in_v4creds->lifetime);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (io_stream, in_v4creds->address);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_int32 (io_stream, in_v4creds->ticket_size);
+    }
+    
+    if (!err) {
+        err = cci_stream_write (io_stream, in_v4creds->ticket, cc_v4_ticket_size);
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark - 
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_contents_release (cc_data *io_ccdata)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccdata && io_ccdata->data) { err = ccErrBadParam; }
+    
+    if (!err) {
+        if (io_ccdata->length) {
+            memset (io_ccdata->data, 0, io_ccdata->length);
+        }
+        free (io_ccdata->data);
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_release (cc_data *io_ccdata)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccdata) { err = ccErrBadParam; }
+    
+    if (!err) {
+        cci_cc_data_contents_release (io_ccdata);
+        free (io_ccdata);
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_read (cc_data      *io_ccdata,
+                                   cci_stream_t  io_stream)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 type = 0;
+    cc_uint32 length = 0;
+    char *data = NULL;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    if (!io_ccdata) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (io_stream, &type);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (io_stream, &length);
+    }
+    
+    if (!err && length > 0) {
+        data = malloc (length);
+        if (!data) { err = cci_check_error (ccErrNoMem); }
+
+        if (!err) {
+            err = cci_stream_read (io_stream, data, length);
+        }
+    }
+    
+    if (!err) {
+        io_ccdata->type = type;
+        io_ccdata->length = length;
+        io_ccdata->data = data;
+        data = NULL;
+    }
+    
+    free (data);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_write (cc_data      *in_ccdata,
+                                    cci_stream_t  io_stream)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    if (!in_ccdata) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (io_stream, in_ccdata->type);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (io_stream, in_ccdata->length);
+    }
+    
+    if (!err && in_ccdata->length > 0) {
+        err = cci_stream_write (io_stream, in_ccdata->data, in_ccdata->length);
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark - 
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_array_release (cc_data **io_ccdata_array)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccdata_array) { err = ccErrBadParam; }
+    
+    if (!err) {
+        cc_uint32 i;
+        
+        for (i = 0; io_ccdata_array && io_ccdata_array[i]; i++) {
+            cci_cc_data_release (io_ccdata_array[i]);
+        }
+        free (io_ccdata_array);        
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_array_read (cc_data      ***io_ccdata_array,
+                                         cci_stream_t    io_stream)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 count = 0;
+    cc_data **array = NULL;
+    cc_uint32 i;
+    
+    if (!io_stream      ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_ccdata_array) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (io_stream, &count);
+    }
+    
+    if (!err && count > 0) {
+        array = malloc ((count + 1) * sizeof (*array));
+        if (array) { 
+            for (i = 0; i <= count; i++) { array[i] = NULL; }
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        for (i = 0; !err && i < count; i++) {
+            array[i] = malloc (sizeof (cc_data));
+            if (!array[i]) { err = cci_check_error (ccErrNoMem); }
+            
+            if (!err) {
+                err = cci_cc_data_read (array[i], io_stream);
+            }
+        }
+    }
+    
+    if (!err) {
+        *io_ccdata_array = array;
+        array = NULL;
+    }
+    
+    cci_cc_data_array_release (array);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_cc_data_array_write (cc_data      **in_ccdata_array,
+                                          cci_stream_t   io_stream)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 count = 0;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    /* in_ccdata_array may be NULL */
+    
+    if (!err) {
+        for (count = 0; in_ccdata_array && in_ccdata_array[count]; count++);
+        
+        err = cci_stream_write_uint32 (io_stream, count);
+    }
+    
+    if (!err) {
+        cc_uint32 i;
+        
+        for (i = 0; !err && i < count; i++) {
+            err = cci_cc_data_write (in_ccdata_array[i], io_stream);
+        }            
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark - 
+
+/* ------------------------------------------------------------------------ */
+
+cc_credentials_v5_t cci_credentials_v5_initializer = {
+    NULL,
+    NULL,
+    { 0, 0, NULL },
+    0, 0, 0, 0, 0, 0, 
+    NULL,
+    { 0, 0, NULL },
+    { 0, 0, NULL },
+    NULL
+};
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v5_release (cc_credentials_v5_t *io_v5creds)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_v5creds) { err = ccErrBadParam; }
+    
+    if (!err) {
+        free (io_v5creds->client);
+        free (io_v5creds->server);
+        cci_cc_data_contents_release (&io_v5creds->keyblock);
+        cci_cc_data_array_release (io_v5creds->addresses);
+        cci_cc_data_contents_release (&io_v5creds->ticket);
+        cci_cc_data_contents_release (&io_v5creds->second_ticket);
+        cci_cc_data_array_release (io_v5creds->authdata);
+        free (io_v5creds);        
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v5_read (cc_credentials_v5_t **out_v5creds,
+                                          cci_stream_t          io_stream)
+{
+    cc_int32 err = ccNoError;
+    cc_credentials_v5_t *v5creds = NULL;
+    
+    if (!io_stream  ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_v5creds) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        v5creds = malloc (sizeof (*v5creds));
+        if (v5creds) { 
+            *v5creds = cci_credentials_v5_initializer;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        err = cci_stream_read_string (io_stream, &v5creds->client);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_string (io_stream, &v5creds->server);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_read (&v5creds->keyblock, io_stream);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_time (io_stream, &v5creds->authtime);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_time (io_stream, &v5creds->starttime);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_time (io_stream, &v5creds->endtime);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_time (io_stream, &v5creds->renew_till);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (io_stream, &v5creds->is_skey);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (io_stream, &v5creds->ticket_flags);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_array_read (&v5creds->addresses, io_stream);
+    }
+        
+    if (!err) {
+        err = cci_cc_data_read (&v5creds->ticket, io_stream);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_read (&v5creds->second_ticket, io_stream);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_array_read (&v5creds->authdata, io_stream);
+    }
+    
+    if (!err) {
+        *out_v5creds = v5creds;
+        v5creds = NULL;
+    }
+    
+    cci_credentials_v5_release (v5creds);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_credentials_v5_write (cc_credentials_v5_t *in_v5creds,
+                                           cci_stream_t         io_stream)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_v5creds) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write_string (io_stream, in_v5creds->client);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_string (io_stream, in_v5creds->server);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_write (&in_v5creds->keyblock, io_stream);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_time (io_stream, in_v5creds->authtime);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_time (io_stream, in_v5creds->starttime);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_time (io_stream, in_v5creds->endtime);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_time (io_stream, in_v5creds->renew_till);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (io_stream, in_v5creds->is_skey);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (io_stream, in_v5creds->ticket_flags);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_array_write (in_v5creds->addresses, io_stream);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_write (&in_v5creds->ticket, io_stream);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_write (&in_v5creds->second_ticket, io_stream);
+    }
+    
+    if (!err) {
+        err = cci_cc_data_array_write (in_v5creds->authdata, io_stream);
+    }
+    
+    
+    return cci_check_error (err);
+}
+
+#pragma mark - 
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_cred_union_release (cc_credentials_union *io_cred_union)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_cred_union) { err = ccErrBadParam; }
+    
+    if (!err) {
+        if (io_cred_union->version == cc_credentials_v4) {
+            cci_credentials_v4_release (io_cred_union->credentials.credentials_v4);
+        } else if (io_cred_union->version == cc_credentials_v5) {
+            cci_credentials_v5_release (io_cred_union->credentials.credentials_v5);
+        }
+        free (io_cred_union);
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_cred_union_read (cc_credentials_union **out_credentials_union,
+                               cci_stream_t           io_stream)
+{
+    cc_int32 err = ccNoError;
+    cc_credentials_union *cred_union = NULL;
+    
+    if (!io_stream            ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_credentials_union) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        cred_union = malloc (sizeof (*cred_union));
+        if (!cred_union) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (io_stream, &cred_union->version);
+    }
+    
+    if (!err) {
+        if (cred_union->version == cc_credentials_v4) {
+            err = cci_credentials_v4_read (&cred_union->credentials.credentials_v4,
+                                           io_stream);
+        
+        } else if (cred_union->version == cc_credentials_v5) {
+            err = cci_credentials_v5_read (&cred_union->credentials.credentials_v5,
+                                           io_stream);
+           
+        
+        } else {
+            err = ccErrBadCredentialsVersion;
+        }
+    }
+    
+    if (!err) {
+        *out_credentials_union = cred_union;
+        cred_union = NULL;
+    }
+    
+    if (cred_union) { cci_cred_union_release (cred_union); }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_cred_union_write (const cc_credentials_union *in_credentials_union,
+                                cci_stream_t                io_stream)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_stream           ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (io_stream, in_credentials_union->version);
+    }
+    
+    if (!err) {
+        if (in_credentials_union->version == cc_credentials_v4) {
+            err = cci_credentials_v4_write (in_credentials_union->credentials.credentials_v4,
+                                            io_stream);
+            
+        } else if (in_credentials_union->version == cc_credentials_v5) {
+            err = cci_credentials_v5_write (in_credentials_union->credentials.credentials_v5,
+                                            io_stream);
+            
+        } else {
+            err = ccErrBadCredentialsVersion;
+        }
+    }
+    
+    return cci_check_error (err);    
+}
diff --git a/src/ccapi/common/cci_cred_union.h b/src/ccapi/common/cci_cred_union.h
new file mode 100644 (file)
index 0000000..f734d6a
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCI_CRED_UNION_H
+#define CCI_CRED_UNION_H
+
+#include "cci_types.h"
+
+cc_uint32 cci_cred_union_release (cc_credentials_union *io_credentials);
+
+cc_uint32 cci_cred_union_read (cc_credentials_union **out_credentials_union,
+                               cci_stream_t           io_stream);
+
+cc_uint32 cci_cred_union_write (const cc_credentials_union *in_credentials_union,
+                                cci_stream_t                io_stream);
+
+
+#endif /* CCI_CRED_UNION_H */
diff --git a/src/ccapi/common/cci_debugging.c b/src/ccapi/common/cci_debugging.c
new file mode 100644 (file)
index 0000000..4545b40
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "cci_common.h"
+#include "cci_os_debugging.h"
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 _cci_check_error (cc_int32    in_error, 
+                           const char *in_function, 
+                           const char *in_file, 
+                           int         in_line)
+{
+    /* Do not log for flow control errors or when there is no error at all */
+    if (in_error != ccNoError && in_error != ccIteratorEnd) {
+        cci_debug_printf ("%s() got %d at %s: %d", in_function, 
+                          in_error, in_file, in_line);
+    }
+    
+    return in_error;    
+}
+
+/* ------------------------------------------------------------------------ */
+
+void cci_debug_printf (const char *in_format, ...)
+{
+    va_list args;
+    
+    va_start (args, in_format);
+    cci_os_debug_vprintf (in_format, args);
+    va_end (args);
+}
diff --git a/src/ccapi/common/cci_debugging.h b/src/ccapi/common/cci_debugging.h
new file mode 100644 (file)
index 0000000..169981f
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCI_DEBUGGING_H
+#define CCI_DEBUGGING_H
+
+#include "cci_types.h"
+
+cc_int32 _cci_check_error (cc_int32    in_err, 
+                           const char *in_function, 
+                           const char *in_file, 
+                           int         in_line);
+#define cci_check_error(err) _cci_check_error(err, __FUNCTION__, __FILE__, __LINE__)
+
+void cci_debug_printf (const char *in_format, ...) __attribute__ ((format (printf, 1, 2)));
+
+#endif /* CCI_DEBUGGING_H */
diff --git a/src/ccapi/common/cci_identifier.c b/src/ccapi/common/cci_identifier.c
new file mode 100644 (file)
index 0000000..8695d21
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "cci_common.h"
+#include "cci_os_identifier.h"
+
+struct cci_identifier_d {
+    cci_uuid_string_t server_id;
+    cci_uuid_string_t object_id;
+};
+
+struct cci_identifier_d cci_identifier_initializer = { NULL, NULL };
+
+#define cci_uninitialized_server_id "NEEDS_SYNC"
+#define cci_uninitialized_object_id "NEEDS_SYNC"
+
+struct cci_identifier_d cci_identifier_uninitialized_d = { 
+    cci_uninitialized_server_id, 
+    cci_uninitialized_object_id 
+};
+const cci_identifier_t cci_identifier_uninitialized = &cci_identifier_uninitialized_d;
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_new_uuid (cci_uuid_string_t *out_uuid_string)
+{
+    return cci_os_identifier_new_uuid (out_uuid_string);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 cci_identifier_alloc (cci_identifier_t *out_identifier,
+                                      cci_uuid_string_t in_server_id,
+                                      cci_uuid_string_t in_object_id)
+{
+    cc_int32 err = ccNoError;
+    cci_identifier_t identifier = NULL;
+    
+    if (!out_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!in_server_id  ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_object_id  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        identifier = malloc (sizeof (*identifier));
+        if (identifier) { 
+            *identifier = cci_identifier_initializer;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        identifier->server_id = strdup (in_server_id);
+        if (!identifier->server_id) { err = cci_check_error (ccErrNoMem); }        
+    }
+    
+    if (!err) {
+        identifier->object_id = strdup (in_object_id);
+        if (!identifier->object_id) { err = cci_check_error (ccErrNoMem); }        
+    }
+    
+    if (!err) {
+        *out_identifier = identifier;
+        identifier = NULL; /* take ownership */
+    }
+    
+    cci_identifier_release (identifier);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_new (cci_identifier_t *out_identifier,
+                             cci_uuid_string_t in_server_id)
+{
+    cc_int32 err = ccNoError;
+    cci_uuid_string_t object_id = NULL;
+    
+    if (!out_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!in_server_id  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_os_identifier_new_uuid (&object_id);
+    }
+    
+    if (!err) {
+        err = cci_identifier_alloc (out_identifier, in_server_id, object_id);
+    }
+    
+    if (object_id) { free (object_id); }
+
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_copy (cci_identifier_t *out_identifier,
+                              cci_identifier_t  in_identifier)
+{
+    cc_int32 err = ccNoError;
+
+    if (!out_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_alloc (out_identifier, 
+                                    in_identifier->server_id,
+                                    in_identifier->object_id);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_release (cci_identifier_t in_identifier)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_identifier) { err = ccErrBadParam; }
+    
+    /* Do not free the static "uninitialized" identifier */
+    if (!err && in_identifier != cci_identifier_uninitialized) {
+        free (in_identifier->server_id);
+        free (in_identifier->object_id);
+        free (in_identifier);
+    }
+    
+    return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_compare (cci_identifier_t  in_identifier,
+                                 cci_identifier_t  in_compare_to_identifier,
+                                 cc_uint32        *out_equal)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_identifier           ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_compare_to_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!out_equal               ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_equal = (!strcmp (in_identifier->object_id, 
+                               in_compare_to_identifier->object_id) &&
+                      !strcmp (in_identifier->server_id, 
+                               in_compare_to_identifier->server_id));
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_is_for_server (cci_identifier_t  in_identifier,
+                                       cci_uuid_string_t in_server_id,
+                                       cc_uint32        *out_is_for_server)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_identifier    ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_server_id     ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_is_for_server) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_is_for_server = (!strcmp (in_identifier->server_id, in_server_id) ||
+                              !strcmp (in_identifier->server_id, cci_uninitialized_server_id));
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_compare_server_id (cci_identifier_t  in_identifier,
+                                           cci_identifier_t  in_compare_to_identifier,
+                                           cc_uint32        *out_equal_server_id)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_identifier           ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_compare_to_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!out_equal_server_id     ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_equal_server_id = (!strcmp (in_identifier->server_id, 
+                                         in_compare_to_identifier->server_id));
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_identifier_is_initialized (cci_identifier_t  in_identifier,
+                                        cc_uint32        *out_is_initialized)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_identifier     ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_is_initialized) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_is_initialized = (strcmp (in_identifier->server_id, 
+                                       cci_uninitialized_server_id) != 0);
+    }
+    
+    return cci_check_error (err);    
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_identifier_read (cci_identifier_t *out_identifier,
+                               cci_stream_t      io_stream)
+{
+    cc_int32 err = ccNoError;
+    cci_uuid_string_t server_id = NULL;
+    cci_uuid_string_t object_id = NULL;
+    
+    if (!out_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!io_stream     ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_string (io_stream, &server_id);
+    }
+
+    if (!err) {
+        err = cci_stream_read_string (io_stream, &object_id);
+    }    
+     
+    if (!err) {
+        err = cci_identifier_alloc (out_identifier, server_id, object_id);
+    }
+    
+    if (server_id) { free (server_id); }
+    if (object_id) { free (object_id); }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_identifier_write (cci_identifier_t in_identifier,
+                                cci_stream_t     io_stream)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!io_stream    ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write_string (io_stream, in_identifier->server_id);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_string (io_stream, in_identifier->object_id);
+    }
+    
+    return cci_check_error (err);
+}
diff --git a/src/ccapi/common/cci_identifier.h b/src/ccapi/common/cci_identifier.h
new file mode 100644 (file)
index 0000000..7d835de
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCI_IDENTIFIER_H
+#define CCI_IDENTIFIER_H
+
+#include "cci_types.h"
+
+extern const cci_identifier_t cci_identifier_uninitialized;
+
+cc_int32 cci_identifier_new_uuid (cci_uuid_string_t *out_uuid_string);
+
+cc_int32 cci_identifier_new (cci_identifier_t *out_identifier,
+                             cci_uuid_string_t in_server_id);
+
+cc_int32 cci_identifier_copy (cci_identifier_t *out_identifier,
+                              cci_identifier_t  in_handle);
+
+cc_int32 cci_identifier_release (cci_identifier_t in_identifier);
+
+cc_int32 cci_identifier_compare (cci_identifier_t  in_identifier,
+                                 cci_identifier_t  in_compare_to_identifier,
+                                 cc_uint32        *out_equal);
+
+cc_int32 cci_identifier_is_for_server (cci_identifier_t  in_identifier,
+                                       cci_uuid_string_t in_server_id,
+                                       cc_uint32        *out_is_for_server);
+
+cc_int32 cci_identifier_compare_server_id (cci_identifier_t  in_identifier,
+                                           cci_identifier_t  in_compare_to_identifier,
+                                           cc_uint32        *out_equal_server_id);
+
+cc_int32 cci_identifier_is_initialized (cci_identifier_t  in_identifier,
+                                        cc_uint32        *out_is_initialized);
+
+cc_uint32 cci_identifier_read (cci_identifier_t *out_identifier,
+                               cci_stream_t      io_stream);
+
+cc_uint32 cci_identifier_write (cci_identifier_t in_identifier,
+                                cci_stream_t     io_stream);
+
+#endif /* CCI_IDENTIFIER_H */
diff --git a/src/ccapi/common/cci_message.c b/src/ccapi/common/cci_message.c
new file mode 100644 (file)
index 0000000..4152e6c
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "cci_common.h"
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_invalid_object_err (enum cci_msg_id_t in_request_name)
+{
+    cc_int32 err = ccNoError;
+    
+    if (in_request_name > cci_context_first_msg_id &&
+        in_request_name < cci_context_last_msg_id) {
+        err = ccErrInvalidContext;
+        
+    } else if (in_request_name > cci_ccache_first_msg_id &&
+               in_request_name < cci_ccache_last_msg_id) {
+        err = ccErrInvalidCCache;
+        
+    } else if (in_request_name > cci_ccache_iterator_first_msg_id &&
+               in_request_name < cci_ccache_iterator_last_msg_id) {
+        err = ccErrInvalidCCacheIterator;
+        
+    } else if (in_request_name > cci_credentials_iterator_first_msg_id &&
+               in_request_name < cci_credentials_iterator_last_msg_id) {
+        err = ccErrInvalidCredentialsIterator;
+        
+    } else {
+        err = ccErrBadInternalMessage;
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_new_request_header (cci_stream_t      *out_request,
+                                         enum cci_msg_id_t  in_request_name,
+                                         cci_identifier_t   in_identifier)
+{
+    cc_int32 err = ccNoError;
+    cci_stream_t request = NULL;
+    
+    if (!out_request) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (request, in_request_name);
+    }
+    
+    if (!err) {
+        err = cci_identifier_write (in_identifier, request);
+    }
+    
+    if (!err) {
+        *out_request = request;
+        request = NULL;
+    }
+    
+    cci_stream_release (request);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_read_request_header (cci_stream_t       in_request,
+                                          enum cci_msg_id_t *out_request_name,
+                                          cci_identifier_t  *out_identifier)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 request_name;
+    cci_identifier_t identifier = NULL;
+    
+    if (!in_request      ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_request_name) { err = cci_check_error (ccErrBadParam); }
+    if (!out_identifier  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (in_request, &request_name);
+    }
+    
+    if (!err) {
+        err = cci_identifier_read (&identifier, in_request);
+    }
+    
+    if (!err) {
+        *out_request_name = request_name;
+        *out_identifier = identifier;
+        identifier = NULL; /* take ownership */
+    }
+    
+    cci_identifier_release (identifier);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_new_reply_header (cci_stream_t     *out_reply,
+                                       cc_int32          in_error)
+{
+    cc_int32 err = ccNoError;
+    cci_stream_t reply = NULL;
+    
+    if (!out_reply) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&reply);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_int32 (reply, in_error);
+    }
+    
+    if (!err) {
+        *out_reply = reply;
+        reply = NULL;
+    }
+    
+    cci_stream_release (reply);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_message_read_reply_header (cci_stream_t      in_reply,
+                                        cc_int32         *out_reply_error)
+{
+    cc_int32 err = ccNoError;
+    cc_int32 reply_err = 0;
+    
+    if (!in_reply       ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_reply_error) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_int32 (in_reply, &reply_err);
+    }
+    
+    if (!err) {
+        *out_reply_error = reply_err;
+    }
+    
+    return cci_check_error (err);
+}
diff --git a/src/ccapi/common/cci_message.h b/src/ccapi/common/cci_message.h
new file mode 100644 (file)
index 0000000..7cab2dc
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCI_MESSAGE_H
+#define CCI_MESSAGE_H
+
+#include "cci_types.h"
+
+cc_int32 cci_message_invalid_object_err (enum cci_msg_id_t in_request_name);
+
+cc_int32 cci_message_new_request_header (cci_stream_t     *out_request,
+                                         enum cci_msg_id_t in_request_name,
+                                         cci_identifier_t  in_identifier);
+
+cc_int32 cci_message_read_request_header (cci_stream_t       in_request,
+                                          enum cci_msg_id_t *out_request_name,
+                                          cci_identifier_t  *out_identifier);
+
+cc_int32 cci_message_new_reply_header (cci_stream_t     *out_reply,
+                                       cc_int32          in_error);
+
+cc_int32 cci_message_read_reply_header (cci_stream_t  in_reply,
+                                        cc_int32     *out_reply_error);
+
+#endif /* CCI_MESSAGE_H */
diff --git a/src/ccapi/common/cci_os_debugging.h b/src/ccapi/common/cci_os_debugging.h
new file mode 100644 (file)
index 0000000..b08ee00
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCI_OS_DEBUGGING_H
+#define CCI_OS_DEBUGGING_H
+
+#include "cci_types.h"
+#include <stdarg.h>
+
+inline void cci_os_debug_vprintf (const char *in_format, va_list in_args);
+
+#endif /* CCI_OS_DEBUGGING_H */
diff --git a/src/ccapi/common/cci_os_identifier.h b/src/ccapi/common/cci_os_identifier.h
new file mode 100644 (file)
index 0000000..b607720
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCI_OS_IDENTIFIER_H
+#define CCI_OS_IDENTIFIER_H
+
+#include "cci_types.h"
+
+inline cc_int32 cci_os_identifier_new_uuid (cci_uuid_string_t *out_uuid_string);
+
+#endif /* CCI_OS_IDENTIFIER_H */
diff --git a/src/ccapi/common/cci_stream.c b/src/ccapi/common/cci_stream.c
new file mode 100644 (file)
index 0000000..cac5431
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "cci_common.h"
+
+#if TARGET_OS_MAC 
+#include <architecture/byte_order.h>
+
+#if !defined(htonll)
+#define htonll(x) OSSwapHostToBigInt64(x)
+#endif
+
+#if !defined(ntohll)
+#define ntohll(x) OSSwapBigToHostInt64(x)
+#endif
+
+#endif /* TARGET_OS_MAC */
+
+struct cci_stream_d {
+    char *data;
+    cc_uint64 size;
+    cc_uint64 max_size;
+};
+
+const struct cci_stream_d cci_stream_initializer = { NULL, 0, 0 };
+
+#define CC_STREAM_SIZE_INCREMENT 128
+
+/* ------------------------------------------------------------------------ */
+
+static cc_uint32 cci_stream_reallocate (cci_stream_t io_stream,
+                                        cc_uint64    in_new_size)
+{
+    cc_int32 err = ccNoError;
+    cc_uint64 new_max_size = 0;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        cc_uint64 old_max_size = io_stream->max_size;
+        new_max_size = io_stream->max_size;
+        
+        if (in_new_size > old_max_size) {
+            /* Expand the stream */
+            while (in_new_size > new_max_size) {
+                new_max_size += CC_STREAM_SIZE_INCREMENT;
+            }
+            
+        
+        } else if ((in_new_size + CC_STREAM_SIZE_INCREMENT) < old_max_size) {
+            /* Shrink the array, but never drop below CC_LIST_COUNT_INCREMENT */
+            while ((in_new_size + CC_STREAM_SIZE_INCREMENT) < new_max_size &&
+                   (new_max_size > CC_STREAM_SIZE_INCREMENT)) {
+                new_max_size -= CC_STREAM_SIZE_INCREMENT;
+            }
+        }
+    }
+    
+    if (!err && new_max_size != io_stream->max_size) {
+        char *data = io_stream->data;
+        if (!data) {
+            data = malloc (new_max_size * sizeof (*data));
+        } else {
+            data = realloc (data, new_max_size * sizeof (*data));
+        }
+        
+        if (data) { 
+            io_stream->data = data;
+            io_stream->max_size = new_max_size;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_stream_new (cci_stream_t *out_stream)
+{
+    cc_int32 err = ccNoError;
+    cci_stream_t stream = NULL;
+    
+    if (!out_stream) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        stream = malloc (sizeof (*stream));
+        if (stream) { 
+            *stream = cci_stream_initializer;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        *out_stream = stream;
+        stream = NULL;
+    }
+    
+    cci_stream_release (stream);
+    
+    return cci_check_error (err);    
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_release (cci_stream_t io_stream)
+{      
+    cc_int32 err = ccNoError;
+    
+    if (!io_stream) { err = ccErrBadParam; }
+    
+    if (!err) {
+        free (io_stream->data);
+        free (io_stream);
+    }
+    
+    return err;    
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_uint64 cci_stream_size (cci_stream_t in_stream)
+{
+    return in_stream ? in_stream->size : 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+inline const char *cci_stream_data (cci_stream_t in_stream)
+{
+    return in_stream ? in_stream->data : NULL;
+}
+
+#pragma mark - 
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_read (cci_stream_t  io_stream, 
+                           void         *io_data, 
+                           cc_uint64     in_size)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    if (!io_data  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        if (in_size > io_stream->size) { 
+            err = cci_check_error (ccErrBadInternalMessage); 
+        }
+    }
+    
+    if (!err) {
+        memcpy (io_data, io_stream->data, in_size);
+        memmove (io_stream->data, &io_stream->data[in_size], 
+                 io_stream->size - in_size);
+        
+        err = cci_stream_reallocate (io_stream, io_stream->size - in_size);
+        
+        if (!err) {
+            io_stream->size -= in_size;
+        }
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_write (cci_stream_t  io_stream,
+                            const void   *in_data, 
+                            cc_uint64     in_size)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    if (!in_data  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        /* Security check: Do not let the caller overflow the length */
+        if (in_size > (UINT64_MAX - io_stream->size)) {
+            err = cci_check_error (ccErrBadParam);
+        }
+    }
+    
+    if (!err) {
+        err = cci_stream_reallocate (io_stream, io_stream->size + in_size);
+    }
+    
+    if (!err) {
+        memcpy (&io_stream->data[io_stream->size], in_data, in_size);
+        io_stream->size += in_size;
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark - 
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_read_string (cci_stream_t   io_stream, 
+                                  char         **out_string)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 length = 0;
+    char *string = NULL;
+    
+    if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_string) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (io_stream, &length);
+    }
+    
+    if (!err) {
+        string = malloc (length);
+        if (!string) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        err = cci_stream_read (io_stream, string, length);
+    }
+    
+    if (!err) {
+        *out_string = string;
+        string = NULL;
+    }
+    
+    free (string);
+
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_write_string (cci_stream_t  io_stream, 
+                                   const char   *in_string)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 length = 0;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    if (!in_string) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        length = strlen (in_string) + 1;
+        
+        err = cci_stream_write_uint32 (io_stream, length);
+    }
+    
+    if (!err) {
+        err = cci_stream_write (io_stream, in_string, length);
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark - 
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_read_int32 (cci_stream_t  io_stream, 
+                                 cc_int32     *out_int32)
+{
+    cc_int32 err = ccNoError;
+    cc_int32 int32 = 0;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    if (!out_int32) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read (io_stream, &int32, sizeof (int32));
+    }
+    
+    if (!err) {
+        *out_int32 = ntohl (int32);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_write_int32 (cci_stream_t io_stream, 
+                                  cc_int32     in_int32)
+{
+    cc_int32 err = ccNoError;
+    cc_int32 int32 = htonl (in_int32);
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write (io_stream, &int32, sizeof (int32));
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark - 
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_read_uint32 (cci_stream_t  io_stream, 
+                                  cc_uint32    *out_uint32)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 uint32 = 0;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    if (!out_uint32) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read (io_stream, &uint32, sizeof (uint32));
+    }
+    
+    if (!err) {
+        *out_uint32 = ntohl (uint32);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_write_uint32 (cci_stream_t io_stream, 
+                                   cc_uint32    in_uint32)
+{
+    cc_int32 err = ccNoError;
+    cc_int32 uint32 = htonl (in_uint32);
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write (io_stream, &uint32, sizeof (uint32));
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark - 
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_read_int64 (cci_stream_t  io_stream, 
+                                 cc_int64     *out_int64)
+{
+    cc_int32 err = ccNoError;
+    cc_uint64 int64 = 0;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    if (!out_int64) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read (io_stream, &int64, sizeof (int64));
+    }
+    
+    if (!err) {
+        *out_int64 = ntohll (int64);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_write_int64 (cci_stream_t io_stream, 
+                                  cc_int64     in_int64)
+{
+    cc_int32 err = ccNoError;
+    cc_int64 int64 = htonll (in_int64);
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write (io_stream, &int64, sizeof (int64));
+    }
+    
+    return cci_check_error (err);
+}
+
+
+#pragma mark - 
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_read_uint64 (cci_stream_t  io_stream, 
+                                  cc_uint64     *out_uint64)
+{
+    cc_int32 err = ccNoError;
+    cc_uint64 uint64 = 0;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    if (!out_uint64) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read (io_stream, &uint64, sizeof (uint64));
+    }
+    
+    if (!err) {
+        *out_uint64 = ntohll (uint64);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_write_uint64 (cci_stream_t io_stream, 
+                                   cc_uint64     in_uint64)
+{
+    cc_int32 err = ccNoError;
+    cc_int64 uint64 = htonll (in_uint64);
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write (io_stream, &uint64, sizeof (uint64));
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark - 
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_read_time (cci_stream_t  io_stream, 
+                                cc_time_t    *out_time)
+{
+    cc_int32 err = ccNoError;
+    cc_int64 t = 0;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    if (!out_time ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_int64 (io_stream, &t);
+    }
+    
+    if (!err) {
+        *out_time = t;
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 cci_stream_write_time (cci_stream_t io_stream, 
+                                 cc_time_t    in_time)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write_int64 (io_stream, in_time);
+    }
+    
+    return cci_check_error (err);
+}
diff --git a/src/ccapi/common/cci_stream.h b/src/ccapi/common/cci_stream.h
new file mode 100644 (file)
index 0000000..9c37361
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCI_STREAM_H
+#define CCI_STREAM_H
+
+#include "cci_types.h"
+
+cc_int32 cci_stream_new (cci_stream_t *out_stream);
+
+cc_uint32 cci_stream_release (cci_stream_t io_stream);
+
+inline cc_uint64 cci_stream_size (cci_stream_t in_stream);
+
+inline const char *cci_stream_data (cci_stream_t in_stream);
+
+cc_uint32 cci_stream_read (cci_stream_t  in_stream, 
+                           void         *io_data,
+                           cc_uint64     in_size);
+cc_uint32 cci_stream_write (cci_stream_t  in_stream, 
+                            const void   *in_data,
+                            cc_uint64     in_size);
+
+cc_uint32 cci_stream_read_string (cci_stream_t   io_stream, 
+                                  char         **out_string);
+cc_uint32 cci_stream_write_string (cci_stream_t  io_stream, 
+                                   const char   *in_string);
+
+cc_uint32 cci_stream_read_int32 (cci_stream_t  io_stream, 
+                                 cc_int32     *out_int32);
+cc_uint32 cci_stream_write_int32 (cci_stream_t io_stream, 
+                                  cc_int32     in_int32);
+
+cc_uint32 cci_stream_read_uint32 (cci_stream_t  io_stream, 
+                                  cc_uint32    *out_uint32);
+cc_uint32 cci_stream_write_uint32 (cci_stream_t io_stream, 
+                                   cc_uint32    in_uint32);
+
+cc_uint32 cci_stream_read_int64 (cci_stream_t  io_stream, 
+                                 cc_int64     *out_int64);
+cc_uint32 cci_stream_write_int64 (cci_stream_t io_stream, 
+                                  cc_int64     in_int64);
+
+cc_uint32 cci_stream_read_uint64 (cci_stream_t  io_stream, 
+                                  cc_uint64    *out_uint64);
+cc_uint32 cci_stream_write_uint64 (cci_stream_t io_stream, 
+                                   cc_uint64    in_uint64);
+
+cc_uint32 cci_stream_read_time (cci_stream_t  io_stream, 
+                                cc_time_t    *out_time);
+cc_uint32 cci_stream_write_time (cci_stream_t io_stream, 
+                                 cc_time_t    in_time);
+
+#endif /* CCI_STREAM_H */
diff --git a/src/ccapi/common/cci_types.h b/src/ccapi/common/cci_types.h
new file mode 100644 (file)
index 0000000..8ace67c
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCI_TYPES_H
+#define CCI_TYPES_H
+
+#include <CredentialsCache.h>
+
+struct cci_stream_d;
+typedef struct cci_stream_d *cci_stream_t;
+
+typedef char *cci_uuid_string_t;
+
+struct cci_identifier_d;
+typedef struct cci_identifier_d *cci_identifier_t;
+
+enum cci_msg_id_t {
+    /* cc_context_t */
+    cci_context_first_msg_id,
+    
+    cci_context_release_msg_id,
+    cci_context_sync_msg_id,
+    cci_context_get_change_time_msg_id,
+    cci_context_wait_for_change_msg_id,
+    cci_context_get_default_ccache_name_msg_id,
+    cci_context_open_ccache_msg_id,
+    cci_context_open_default_ccache_msg_id,
+    cci_context_create_ccache_msg_id,
+    cci_context_create_default_ccache_msg_id,
+    cci_context_create_new_ccache_msg_id,
+    cci_context_new_ccache_iterator_msg_id,
+    cci_context_lock_msg_id,
+    cci_context_unlock_msg_id,
+    
+    cci_context_last_msg_id,
+    
+    /* cc_ccache_t */
+    cci_ccache_first_msg_id,
+    
+    cci_ccache_destroy_msg_id,
+    cci_ccache_set_default_msg_id,
+    cci_ccache_get_credentials_version_msg_id,
+    cci_ccache_get_name_msg_id,
+    cci_ccache_get_principal_msg_id,
+    cci_ccache_set_principal_msg_id,
+    cci_ccache_store_credentials_msg_id,
+    cci_ccache_remove_credentials_msg_id,
+    cci_ccache_new_credentials_iterator_msg_id,
+    cci_ccache_move_msg_id,
+    cci_ccache_lock_msg_id,
+    cci_ccache_unlock_msg_id,
+    cci_ccache_get_last_default_time_msg_id,
+    cci_ccache_get_change_time_msg_id,
+    cci_ccache_wait_for_change_msg_id,
+    cci_ccache_get_kdc_time_offset_msg_id,
+    cci_ccache_set_kdc_time_offset_msg_id,
+    cci_ccache_clear_kdc_time_offset_msg_id,
+    
+    cci_ccache_last_msg_id,
+    
+    /* cc_ccache_iterator_t */
+    cci_ccache_iterator_first_msg_id,
+    
+    cci_ccache_iterator_release_msg_id,
+    cci_ccache_iterator_next_msg_id,
+    cci_ccache_iterator_clone_msg_id,
+    
+    cci_ccache_iterator_last_msg_id,
+    
+    /* cc_credentials_iterator_t */
+    cci_credentials_iterator_first_msg_id,
+    
+    cci_credentials_iterator_release_msg_id,
+    cci_credentials_iterator_next_msg_id,
+    cci_credentials_iterator_clone_msg_id,
+    
+    cci_credentials_iterator_last_msg_id,
+    
+    cci_max_msg_id  /* must be last! */
+};                              
+
+#endif /* CCI_TYPES_H */
diff --git a/src/ccapi/common/mac/cci_mig.defs b/src/ccapi/common/mac/cci_mig.defs
new file mode 100644 (file)
index 0000000..3a57368
--- /dev/null
@@ -0,0 +1,54 @@
+/* $Copyright:
+ *
+ * Copyright 2004-2006 by the Massachusetts Institute of Technology.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require a
+ * specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute
+ * this software and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of M.I.T. not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  Furthermore if you
+ * modify this software you must label your software as modified software
+ * and not distribute it in such a fashion that it might be confused with
+ * the original MIT software. M.I.T. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Individual source code files are copyright MIT, Cygnus Support,
+ * OpenVision, Oracle, Sun Soft, FundsXpress, and others.
+ * 
+ * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira,
+ * and Zephyr are trademarks of the Massachusetts Institute of Technology
+ * (MIT).  No commercial use of these trademarks may be made without prior
+ * written permission of MIT.
+ * 
+ * "Commercial use" means use of a name in a product or other for-profit
+ * manner.  It does NOT prevent a commercial firm from referring to the MIT
+ * trademarks in order to convey information (although in doing so,
+ * recognition of their trademark status should be given).
+ * $
+ */
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+import "cci_mig_types.h";
+
+/* Note the 1024 must be the same as kCCAPIMaxILMsgSize */
+type cci_mipc_inl_request_t = array [ * : 1024 ] of char;
+type cci_mipc_ool_request_t = array [] of char;
+
+type cci_mipc_inl_reply_t = array [ * : 1024 ] of char;
+type cci_mipc_ool_reply_t = array [] of char;
diff --git a/src/ccapi/common/mac/cci_mig_reply.defs b/src/ccapi/common/mac/cci_mig_reply.defs
new file mode 100644 (file)
index 0000000..f500ef9
--- /dev/null
@@ -0,0 +1,58 @@
+/* $Copyright:
+ *
+ * Copyright 2004-2006 by the Massachusetts Institute of Technology.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require a
+ * specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute
+ * this software and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of M.I.T. not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  Furthermore if you
+ * modify this software you must label your software as modified software
+ * and not distribute it in such a fashion that it might be confused with
+ * the original MIT software. M.I.T. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Individual source code files are copyright MIT, Cygnus Support,
+ * OpenVision, Oracle, Sun Soft, FundsXpress, and others.
+ * 
+ * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira,
+ * and Zephyr are trademarks of the Massachusetts Institute of Technology
+ * (MIT).  No commercial use of these trademarks may be made without prior
+ * written permission of MIT.
+ * 
+ * "Commercial use" means use of a name in a product or other for-profit
+ * manner.  It does NOT prevent a commercial firm from referring to the MIT
+ * trademarks in order to convey information (although in doing so,
+ * recognition of their trademark status should be given).
+ * $
+ */
+#include "cci_mig.defs"
+subsystem cci 200;
+
+serverprefix cci_mipc_;
+userprefix ccs_mipc_;
+
+/* ",dealloc" means that the vm_read() memory will be moved to 
+ * the other process rather than copied.  This is necessary on the
+ * client side because we can't know when server has copied our
+ * buffers so we can't vm_deallocate() them ourselves. */
+simpleroutine reply (in_reply_port : mach_port_move_send_once_t;
+                     in_inl_reply  : cci_mipc_inl_reply_t;
+                     in_ool_reply  : cci_mipc_ool_reply_t, dealloc);
diff --git a/src/ccapi/common/mac/cci_mig_request.defs b/src/ccapi/common/mac/cci_mig_request.defs
new file mode 100644 (file)
index 0000000..45887e1
--- /dev/null
@@ -0,0 +1,62 @@
+/* $Copyright:
+ *
+ * Copyright 2004-2006 by the Massachusetts Institute of Technology.
+ * 
+ * All rights reserved.
+ * 
+ * Export of this software from the United States of America may require a
+ * specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute
+ * this software and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of M.I.T. not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  Furthermore if you
+ * modify this software you must label your software as modified software
+ * and not distribute it in such a fashion that it might be confused with
+ * the original MIT software. M.I.T. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Individual source code files are copyright MIT, Cygnus Support,
+ * OpenVision, Oracle, Sun Soft, FundsXpress, and others.
+ * 
+ * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira,
+ * and Zephyr are trademarks of the Massachusetts Institute of Technology
+ * (MIT).  No commercial use of these trademarks may be made without prior
+ * written permission of MIT.
+ * 
+ * "Commercial use" means use of a name in a product or other for-profit
+ * manner.  It does NOT prevent a commercial firm from referring to the MIT
+ * trademarks in order to convey information (although in doing so,
+ * recognition of their trademark status should be given).
+ * $
+ */
+#include "cci_mig.defs"
+
+subsystem ccs 100;
+
+serverprefix ccs_mipc_;
+userprefix cci_mipc_;
+
+routine create_client_connection (in_server_port     : mach_port_t;
+                             out out_connection_port : mach_port_t = MACH_MSG_TYPE_MAKE_SEND);
+
+/* ",dealloc" means that the vm_read() memory will be moved to 
+ * the other process rather than copied.  This is necessary on the
+ * server side because we can't know when client has copied our
+ * buffers so we can't vm_deallocate() them ourselves. */
+
+simpleroutine request (in_connection_port : mach_port_t;
+                       in_reply_port      : mach_port_make_send_once_t;
+                       in_inl_request     : cci_mipc_inl_request_t;
+                       in_ool_request     : cci_mipc_ool_request_t, dealloc);
diff --git a/src/ccapi/common/mac/cci_mig_types.h b/src/ccapi/common/mac/cci_mig_types.h
new file mode 100644 (file)
index 0000000..d82d5ac
--- /dev/null
@@ -0,0 +1,56 @@
+/* $Copyright:
+*
+* Copyright 2004-2006 by the Massachusetts Institute of Technology.
+* 
+* All rights reserved.
+* 
+* Export of this software from the United States of America may require a
+* specific license from the United States Government.  It is the
+* responsibility of any person or organization contemplating export to
+* obtain such a license before exporting.
+* 
+* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute
+* this software and its documentation for any purpose and without fee is
+* hereby granted, provided that the above copyright notice appear in all
+* copies and that both that copyright notice and this permission notice
+* appear in supporting documentation, and that the name of M.I.T. not be
+* used in advertising or publicity pertaining to distribution of the
+* software without specific, written prior permission.  Furthermore if you
+* modify this software you must label your software as modified software
+* and not distribute it in such a fashion that it might be confused with
+* the original MIT software. M.I.T. makes no representations about the
+* suitability of this software for any purpose.  It is provided "as is"
+* without express or implied warranty.
+* 
+* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+* 
+* Individual source code files are copyright MIT, Cygnus Support,
+* OpenVision, Oracle, Sun Soft, FundsXpress, and others.
+* 
+* Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira,
+* and Zephyr are trademarks of the Massachusetts Institute of Technology
+* (MIT).  No commercial use of these trademarks may be made without prior
+* written permission of MIT.
+* 
+* "Commercial use" means use of a name in a product or other for-profit
+* manner.  It does NOT prevent a commercial firm from referring to the MIT
+* trademarks in order to convey information (although in doing so,
+* recognition of their trademark status should be given).
+* $
+*/
+
+#ifndef CCI_MIG_TYPES_H
+#define CCI_MIG_TYPES_H
+
+#include "cci_common.h"
+
+#define kCCAPIMaxILMsgSize 1024
+
+typedef const char  cci_mipc_inl_request_t[kCCAPIMaxILMsgSize];
+typedef const char *cci_mipc_ool_request_t;
+typedef char        cci_mipc_inl_reply_t[kCCAPIMaxILMsgSize];
+typedef char       *cci_mipc_ool_reply_t;
+
+#endif /* CCI_MIG_TYPES_H */
diff --git a/src/ccapi/common/mac/cci_os_debugging.c b/src/ccapi/common/mac/cci_os_debugging.c
new file mode 100644 (file)
index 0000000..f64b839
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+
+#include "cci_os_debugging.h"
+#include <Kerberos/KerberosDebug.h>
+
+/* ------------------------------------------------------------------------ */
+
+inline void cci_os_debug_vprintf (const char *in_format, va_list in_args)
+{
+    dvprintf (in_format, in_args);
+}
diff --git a/src/ccapi/common/mac/cci_os_identifier.c b/src/ccapi/common/mac/cci_os_identifier.c
new file mode 100644 (file)
index 0000000..c01e727
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "cci_common.h"
+#include "cci_os_identifier.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 cci_os_identifier_new_uuid (cci_uuid_string_t *out_uuid_string)
+{
+    cc_int32 err = ccNoError;
+    cci_uuid_string_t uuid_string = NULL;
+    CFUUIDRef uuid = NULL;
+    CFStringRef uuid_stringref = NULL;
+    CFStringEncoding encoding = kCFStringEncodingUTF8;
+    CFIndex length = 0;
+    
+    if (!out_uuid_string) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        uuid = CFUUIDCreate (kCFAllocatorDefault);
+        if (!uuid) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        uuid_stringref = CFUUIDCreateString (kCFAllocatorDefault, uuid); 
+        if (!uuid_stringref) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        length = CFStringGetMaximumSizeForEncoding (CFStringGetLength (uuid_stringref), 
+                                                    encoding) + 1;
+        
+        uuid_string = malloc (length);
+        if (!uuid_string) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        if (!CFStringGetCString (uuid_stringref, uuid_string, length, encoding)) {
+            err = cci_check_error (ccErrNoMem);
+        }        
+    }
+    
+    if (!err) {
+        *out_uuid_string = uuid_string;
+        uuid_string = NULL; /* take ownership */
+    }
+    
+    if (uuid_string   ) { free (uuid_string); }
+    if (uuid_stringref) { CFRelease (uuid_stringref); }
+    if (uuid          ) { CFRelease (uuid); }
+    
+    return cci_check_error (err);
+}
+
diff --git a/src/ccapi/lib/ccapi.exports b/src/ccapi/lib/ccapi.exports
new file mode 100644 (file)
index 0000000..92c859b
--- /dev/null
@@ -0,0 +1 @@
+cc_initialize
diff --git a/src/ccapi/lib/ccapi_ccache.c b/src/ccapi/lib/ccapi_ccache.c
new file mode 100644 (file)
index 0000000..5a97581
--- /dev/null
@@ -0,0 +1,736 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccapi_ccache.h"
+
+#include "ccapi_string.h"
+#include "ccapi_credentials.h"
+#include "ccapi_credentials_iterator.h"
+#include "ccapi_ipc.h"
+
+#if TARGET_OS_MAC
+#warning Workaround for AppleConnect crash causes leak
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+typedef struct cci_ccache_d {
+    cc_ccache_f *functions;
+#if TARGET_OS_MAC
+    cc_ccache_f *vector_functions;
+#endif
+    cci_identifier_t identifier;
+} *cci_ccache_t;
+
+/* ------------------------------------------------------------------------ */
+
+struct cci_ccache_d cci_ccache_initializer = { 
+    NULL 
+    VECTOR_FUNCTIONS_INITIALIZER, 
+    NULL,
+};
+
+cc_ccache_f cci_ccache_f_initializer = { 
+    ccapi_ccache_release,
+    ccapi_ccache_destroy,
+    ccapi_ccache_set_default,
+    ccapi_ccache_get_credentials_version,
+    ccapi_ccache_get_name,
+    ccapi_ccache_get_principal,
+    ccapi_ccache_set_principal,
+    ccapi_ccache_store_credentials,
+    ccapi_ccache_remove_credentials,
+    ccapi_ccache_new_credentials_iterator,
+    ccapi_ccache_move,
+    ccapi_ccache_lock,
+    ccapi_ccache_unlock,
+    ccapi_ccache_get_last_default_time,
+    ccapi_ccache_get_change_time,
+    ccapi_ccache_compare,
+    ccapi_ccache_get_kdc_time_offset,
+    ccapi_ccache_set_kdc_time_offset,
+    ccapi_ccache_clear_kdc_time_offset,
+    ccapi_ccache_wait_for_change
+};
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ccache_new (cc_ccache_t      *out_ccache,
+                         cci_identifier_t  in_identifier)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = NULL;
+    
+    if (!out_ccache   ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+
+    if (!err) {
+        ccache = malloc (sizeof (*ccache));
+        if (ccache) { 
+            *ccache = cci_ccache_initializer;
+        } else { 
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        ccache->functions = malloc (sizeof (*ccache->functions));
+        if (ccache->functions) { 
+            *ccache->functions = cci_ccache_f_initializer;
+        } else { 
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        err = cci_identifier_copy (&ccache->identifier, in_identifier);
+    }
+    
+    if (!err) {
+        *out_ccache = (cc_ccache_t) ccache;
+        ccache = NULL; /* take ownership */
+    }
+    
+    ccapi_ccache_release ((cc_ccache_t) ccache);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ccache_write (cc_ccache_t  in_ccache,
+                           cci_stream_t in_stream)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+    
+    if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+    if (!in_stream) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_write (ccache->identifier, in_stream);
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_release (cc_ccache_t io_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+    
+    if (!io_ccache) { err = ccErrBadParam; }
+    
+    if (!err) {
+        cci_identifier_release (ccache->identifier);
+        
+#if TARGET_OS_MAC
+#warning Workaround for AppleConnect crash causes leak
+        CFBundleRef main_bundle = CFBundleGetMainBundle ();
+        if (main_bundle) {
+            CFStringRef bundle_id = CFBundleGetIdentifier (main_bundle);
+            if (bundle_id) {
+                CFStringRef ac_id = CFSTR("com.apple.ist.ds.appleconnect");
+                if (CFStringCompare (bundle_id, ac_id, 0) == kCFCompareEqualTo) {
+                    return ccNoError;
+                }
+            }
+        }
+#endif
+        free ((char *) ccache->functions);
+        free (ccache);
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_destroy (cc_ccache_t io_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+    
+    if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_destroy_msg_id,
+                             ccache->identifier,
+                             NULL,
+                             NULL);
+    }
+    
+    if (!err) {
+        err = ccapi_ccache_release (io_ccache);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_set_default (cc_ccache_t io_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+    
+    if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_set_default_msg_id,
+                             ccache->identifier,
+                             NULL,
+                             NULL);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_get_credentials_version (cc_ccache_t  in_ccache,
+                                               cc_uint32   *out_credentials_version)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+    cci_stream_t reply = NULL;
+    
+    if (!in_ccache              ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_credentials_version) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_get_credentials_version_msg_id,
+                             ccache->identifier,
+                             NULL,
+                             &reply);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (reply, out_credentials_version);
+    }
+    
+    cci_stream_release (reply);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_get_name (cc_ccache_t  in_ccache,
+                                cc_string_t *out_name)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+    cci_stream_t reply = NULL;
+    char *name = NULL;
+    
+    if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+    if (!out_name ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_get_name_msg_id,
+                             ccache->identifier,
+                             NULL,
+                             &reply);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_string (reply, &name);
+    }
+    
+    if (!err) {
+        err = cci_string_new (out_name, name);
+    }
+    
+    cci_stream_release (reply);
+    free (name);
+        
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_get_principal (cc_ccache_t  in_ccache,
+                                     cc_uint32    in_credentials_version,
+                                     cc_string_t *out_principal)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+    cci_stream_t reply = NULL;
+    char *principal = NULL;
+    
+    if (!in_ccache    ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_principal) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_get_principal_msg_id,
+                             ccache->identifier,
+                             NULL,
+                             &reply);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_string (reply, &principal);
+    }
+    
+    if (!err) {
+        err = cci_string_new (out_principal, principal);
+    }
+    
+    cci_stream_release (reply);
+    free (principal);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_set_principal (cc_ccache_t  io_ccache,
+                                     cc_uint32    in_credentials_version,
+                                     const char  *in_principal)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+    cci_stream_t request = NULL;
+    
+    if (!io_ccache   ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_principal) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_string (request, in_principal);
+    }
+
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_set_principal_msg_id,
+                             ccache->identifier,
+                             request,
+                             NULL);
+    }
+    
+    cci_stream_release (request);
+
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_store_credentials (cc_ccache_t                 io_ccache,
+                                         const cc_credentials_union *in_credentials_union)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+    cci_stream_t request = NULL;
+    
+    if (!io_ccache           ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = cci_cred_union_write (in_credentials_union, request);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_store_credentials_msg_id,
+                             ccache->identifier,
+                             request,
+                             NULL);
+    }
+    
+    cci_stream_release (request);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_remove_credentials (cc_ccache_t      io_ccache,
+                                          cc_credentials_t in_credentials)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+    cci_stream_t request = NULL;
+    
+    if (!io_ccache     ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_credentials) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = cci_credentials_write (in_credentials, request);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_remove_credentials_msg_id,
+                             ccache->identifier,
+                             request,
+                             NULL);
+    }
+    
+    cci_stream_release (request);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_new_credentials_iterator (cc_ccache_t                in_ccache,
+                                                cc_credentials_iterator_t *out_credentials_iterator)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+    cci_stream_t reply = NULL;
+    cci_identifier_t identifier = NULL;
+    
+    if (!in_ccache               ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_new_credentials_iterator_msg_id,
+                             ccache->identifier,
+                             NULL,
+                             &reply);
+    }
+    
+    if (!err) {
+        err =  cci_identifier_read (&identifier, reply);
+    }
+    
+    if (!err) {
+        err = cci_credentials_iterator_new (out_credentials_iterator, identifier);
+    }
+    
+    cci_stream_release (reply);
+    cci_identifier_release (identifier);
+
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+/* Note: message is sent as the destination to avoid extra work on the      */
+/* server when deleting it the source ccache.                               */
+
+cc_int32 ccapi_ccache_move (cc_ccache_t io_source_ccache,
+                            cc_ccache_t io_destination_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t source_ccache = (cci_ccache_t) io_source_ccache;
+    cci_ccache_t destination_ccache = (cci_ccache_t) io_destination_ccache;
+    cci_stream_t request = NULL;
+    
+    if (!io_source_ccache     ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = cci_identifier_write (source_ccache->identifier, request);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_move_msg_id,
+                             destination_ccache->identifier,
+                             request,
+                             NULL);
+    }
+    
+    cci_stream_release (request);
+
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_lock (cc_ccache_t io_ccache,
+                            cc_uint32   in_lock_type,
+                            cc_uint32   in_block)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+    cci_stream_t request = NULL;
+    
+    if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (request, in_lock_type);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (request, in_block);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_lock_msg_id,
+                             ccache->identifier,
+                             request,
+                             NULL);
+    }
+    
+    cci_stream_release (request);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_unlock (cc_ccache_t io_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+    
+    if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_unlock_msg_id,
+                             ccache->identifier,
+                             NULL,
+                             NULL);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_get_last_default_time (cc_ccache_t  in_ccache,
+                                             cc_time_t   *out_last_default_time)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+    cci_stream_t reply = NULL;
+    
+    if (!in_ccache            ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_last_default_time) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_get_last_default_time_msg_id,
+                             ccache->identifier,
+                             NULL,
+                             &reply);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_time (reply, out_last_default_time);
+    }
+    
+    cci_stream_release (reply);
+
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_get_change_time (cc_ccache_t  in_ccache,
+                                       cc_time_t   *out_change_time)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+    cci_stream_t reply = NULL;
+    
+    if (!in_ccache      ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_change_time) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_get_change_time_msg_id,
+                             ccache->identifier,
+                             NULL,
+                             &reply);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_time (reply, out_change_time);
+    }
+    
+    cci_stream_release (reply);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_wait_for_change (cc_ccache_t  in_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+    
+    if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_wait_for_change_msg_id,
+                             ccache->identifier,
+                             NULL, NULL);
+    }
+        
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_compare (cc_ccache_t  in_ccache,
+                               cc_ccache_t  in_compare_to_ccache,
+                               cc_uint32   *out_equal)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+    cci_ccache_t compare_to_ccache = (cci_ccache_t) in_compare_to_ccache;
+    
+    if (!in_ccache           ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_compare_to_ccache) { err = cci_check_error (ccErrBadParam); }
+    if (!out_equal           ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_compare (ccache->identifier, 
+                                      compare_to_ccache->identifier,
+                                      out_equal);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_get_kdc_time_offset (cc_ccache_t  in_ccache,
+                                           cc_uint32    in_credentials_version,
+                                           cc_time_t   *out_time_offset)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) in_ccache;
+    cci_stream_t request = NULL;
+    cci_stream_t reply = NULL;
+    
+    if (!in_ccache      ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_time_offset) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (request, in_credentials_version);
+    }
+
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_get_kdc_time_offset_msg_id,
+                             ccache->identifier,
+                             request,
+                             &reply);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_time (reply, out_time_offset);
+    }
+    
+    cci_stream_release (request);
+    cci_stream_release (reply);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_set_kdc_time_offset (cc_ccache_t io_ccache,
+                                           cc_uint32   in_credentials_version,
+                                           cc_time_t   in_time_offset)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+    cci_stream_t request = NULL;
+    
+    if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (request, in_credentials_version);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_time (request, in_time_offset);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_set_kdc_time_offset_msg_id,
+                             ccache->identifier,
+                             request,
+                             NULL);
+    }
+    
+    cci_stream_release (request);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_clear_kdc_time_offset (cc_ccache_t io_ccache,
+                                             cc_uint32   in_credentials_version)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_t ccache = (cci_ccache_t) io_ccache;
+    cci_stream_t request = NULL;
+    
+    if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (request, in_credentials_version);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_clear_kdc_time_offset_msg_id,
+                             ccache->identifier,
+                             request,
+                             NULL);
+    }
+    
+    cci_stream_release (request);
+    
+    return cci_check_error (err);
+}
diff --git a/src/ccapi/lib/ccapi_ccache.h b/src/ccapi/lib/ccapi_ccache.h
new file mode 100644 (file)
index 0000000..82a9f6c
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCAPI_CCACHE_H
+#define CCAPI_CCACHE_H
+
+#include "cci_common.h"
+
+cc_int32 cci_ccache_new (cc_ccache_t      *out_ccache,
+                         cci_identifier_t  in_identifier);
+
+cc_int32 ccapi_ccache_release (cc_ccache_t io_ccache);
+
+cc_int32 cci_ccache_write (cc_ccache_t  in_ccache,
+                           cci_stream_t in_stream);
+
+cc_int32 ccapi_ccache_destroy (cc_ccache_t io_ccache);
+
+cc_int32 ccapi_ccache_set_default (cc_ccache_t io_ccache);
+
+cc_int32 ccapi_ccache_get_credentials_version (cc_ccache_t  in_ccache,
+                                               cc_uint32   *out_credentials_version);
+
+cc_int32 ccapi_ccache_get_name (cc_ccache_t  in_ccache,
+                                cc_string_t *out_name);
+
+cc_int32 ccapi_ccache_get_principal (cc_ccache_t  in_ccache,
+                                     cc_uint32    in_credentials_version,
+                                     cc_string_t *out_principal);
+
+cc_int32 ccapi_ccache_set_principal (cc_ccache_t  io_ccache,
+                                     cc_uint32    in_credentials_version,
+                                     const char  *in_principal);
+
+cc_int32 ccapi_ccache_store_credentials (cc_ccache_t                 io_ccache,
+                                         const cc_credentials_union *in_credentials_union);
+
+cc_int32 ccapi_ccache_remove_credentials (cc_ccache_t      io_ccache,
+                                          cc_credentials_t in_credentials);
+
+cc_int32 ccapi_ccache_new_credentials_iterator (cc_ccache_t                in_ccache,
+                                                cc_credentials_iterator_t *out_credentials_iterator);
+
+cc_int32 ccapi_ccache_move (cc_ccache_t io_source_ccache,
+                            cc_ccache_t io_destination_ccache);
+
+cc_int32 ccapi_ccache_lock (cc_ccache_t io_ccache,
+                            cc_uint32   in_lock_type,
+                            cc_uint32   in_block);
+
+cc_int32 ccapi_ccache_unlock (cc_ccache_t io_ccache);
+
+cc_int32 ccapi_ccache_get_last_default_time (cc_ccache_t  in_ccache,
+                                             cc_time_t   *out_last_default_time);
+
+cc_int32 ccapi_ccache_get_change_time (cc_ccache_t  in_ccache,
+                                       cc_time_t   *out_change_time);
+
+cc_int32 ccapi_ccache_wait_for_change (cc_ccache_t  in_ccache);
+
+cc_int32 ccapi_ccache_compare (cc_ccache_t  in_ccache,
+                               cc_ccache_t  in_compare_to_ccache,
+                               cc_uint32   *out_equal);
+
+cc_int32 ccapi_ccache_get_kdc_time_offset (cc_ccache_t  in_ccache,
+                                           cc_uint32    in_credentials_version,
+                                           cc_time_t   *out_time_offset);
+
+cc_int32 ccapi_ccache_set_kdc_time_offset (cc_ccache_t io_ccache,
+                                           cc_uint32   in_credentials_version,
+                                           cc_time_t   in_time_offset);
+
+cc_int32 ccapi_ccache_clear_kdc_time_offset (cc_ccache_t io_ccache,
+                                             cc_uint32   in_credentials_version);
+
+#endif /* CCAPI_CCACHE_H */
diff --git a/src/ccapi/lib/ccapi_ccache_iterator.c b/src/ccapi/lib/ccapi_ccache_iterator.c
new file mode 100644 (file)
index 0000000..815da36
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccapi_ccache_iterator.h"
+#include "ccapi_ccache.h"
+#include "ccapi_ipc.h"
+
+/* ------------------------------------------------------------------------ */
+
+typedef struct cci_ccache_iterator_d {
+    cc_ccache_iterator_f *functions;
+#if TARGET_OS_MAC
+    cc_ccache_iterator_f *vector_functions;
+#endif
+    cci_identifier_t identifier;
+} *cci_ccache_iterator_t;
+
+/* ------------------------------------------------------------------------ */
+
+struct cci_ccache_iterator_d cci_ccache_iterator_initializer = { 
+    NULL 
+    VECTOR_FUNCTIONS_INITIALIZER, 
+    NULL
+};
+
+cc_ccache_iterator_f cci_ccache_iterator_f_initializer = { 
+    ccapi_ccache_iterator_release,
+    ccapi_ccache_iterator_next,
+    ccapi_ccache_iterator_clone
+};
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ccache_iterator_new (cc_ccache_iterator_t *out_ccache_iterator,
+                                  cci_identifier_t      in_identifier)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_iterator_t ccache_iterator = NULL;
+
+    if (!in_identifier      ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_ccache_iterator) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        ccache_iterator = malloc (sizeof (*ccache_iterator));
+        if (ccache_iterator) { 
+            *ccache_iterator = cci_ccache_iterator_initializer;
+        } else { 
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        ccache_iterator->functions = malloc (sizeof (*ccache_iterator->functions));
+        if (ccache_iterator->functions) { 
+            *ccache_iterator->functions = cci_ccache_iterator_f_initializer;
+        } else { 
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        err = cci_identifier_copy (&ccache_iterator->identifier, in_identifier);
+    }
+    
+    if (!err) {
+        *out_ccache_iterator = (cc_ccache_iterator_t) ccache_iterator;
+        ccache_iterator = NULL; /* take ownership */
+    }
+    
+    ccapi_ccache_iterator_release ((cc_ccache_iterator_t) ccache_iterator);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ccache_iterator_write (cc_ccache_iterator_t in_ccache_iterator,
+                                   cci_stream_t          in_stream)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator;
+    
+    if (!in_ccache_iterator) { err = cci_check_error (ccErrBadParam); }
+    if (!in_stream         ) { err = cci_check_error (ccErrBadParam); }
+        
+    if (!err) {
+        err =  cci_identifier_write (ccache_iterator->identifier, in_stream);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_iterator_release (cc_ccache_iterator_t io_ccache_iterator)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) io_ccache_iterator;
+    
+    if (!io_ccache_iterator) { err = ccErrBadParam; }
+    
+    if (!err) {
+        free ((char *) ccache_iterator->functions);
+        cci_identifier_release (ccache_iterator->identifier);
+        free (ccache_iterator);
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_iterator_next (cc_ccache_iterator_t  in_ccache_iterator,
+                                     cc_ccache_t          *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator;
+    cci_stream_t reply = NULL;
+    cci_identifier_t identifier = NULL;
+    
+    if (!in_ccache_iterator) { err = cci_check_error (ccErrBadParam); }
+    if (!out_ccache        ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        cc_uint32 initialized = 0;
+
+        err = cci_identifier_is_initialized (ccache_iterator->identifier,
+                                             &initialized);
+
+        if (!err && !initialized) {
+            /* server doesn't actually exist.  Pretend we're empty. */
+            err = cci_check_error (ccIteratorEnd);
+        }
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_ccache_iterator_next_msg_id,
+                             ccache_iterator->identifier,
+                             NULL,
+                             &reply);
+    }
+    
+    if (!err) {
+        err = cci_identifier_read (&identifier, reply);
+    }
+    
+    if (!err) {
+        err = cci_ccache_new (out_ccache, identifier);
+    }
+    
+    cci_stream_release (reply);
+    cci_identifier_release (identifier);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_ccache_iterator_clone (cc_ccache_iterator_t  in_ccache_iterator,
+                                      cc_ccache_iterator_t *out_ccache_iterator)
+{
+    cc_int32 err = ccNoError;
+    cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator;
+    cci_stream_t reply = NULL;
+    cc_uint32 initialized = 0;
+    cci_identifier_t identifier = NULL;
+    
+    if (!in_ccache_iterator ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_ccache_iterator) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_is_initialized (ccache_iterator->identifier,
+                                             &initialized);
+    }
+
+    if (!err) {
+        if (initialized) {
+            err =  cci_ipc_send (cci_ccache_iterator_next_msg_id,
+                                 ccache_iterator->identifier,
+                                 NULL,
+                                 &reply);
+            
+            if (!err) {
+                err =  cci_identifier_read (&identifier, reply);
+            }
+
+        } else {
+            /* server doesn't actually exist.  Make another dummy one. */
+            identifier = cci_identifier_uninitialized;
+        }
+    }
+    
+    if (!err) {
+        err = cci_ccache_iterator_new (out_ccache_iterator, identifier);
+    }
+
+    cci_identifier_release (identifier);
+    cci_stream_release (reply);
+    
+    return cci_check_error (err);
+}
diff --git a/src/ccapi/lib/ccapi_ccache_iterator.h b/src/ccapi/lib/ccapi_ccache_iterator.h
new file mode 100644 (file)
index 0000000..0a5a4f4
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCAPI_CCACHE_ITERATOR_H
+#define CCAPI_CCACHE_ITERATOR_H
+
+#include "cci_common.h"
+
+cc_int32 cci_ccache_iterator_new (cc_ccache_iterator_t *out_ccache_iterator,
+                                  cci_identifier_t      in_identifier);
+
+cc_int32 cci_ccache_iterator_write (cc_ccache_iterator_t in_ccache_iterator,
+                                    cci_stream_t          in_stream);
+
+cc_int32 ccapi_ccache_iterator_release (cc_ccache_iterator_t io_ccache_iterator);
+
+cc_int32 ccapi_ccache_iterator_next (cc_ccache_iterator_t  in_ccache_iterator,
+                                     cc_ccache_t          *out_ccache);
+
+cc_int32 ccapi_ccache_iterator_clone (cc_ccache_iterator_t  in_ccache_iterator,
+                                      cc_ccache_iterator_t *out_ccache_iterator);
+
+#endif /* CCAPI_CCACHE_ITERATOR_H */
diff --git a/src/ccapi/lib/ccapi_context.c b/src/ccapi/lib/ccapi_context.c
new file mode 100644 (file)
index 0000000..7a24f22
--- /dev/null
@@ -0,0 +1,789 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccapi_context.h"
+
+#include "k5-platform.h"
+
+#include "ccapi_ccache.h"
+#include "ccapi_ccache_iterator.h"
+#include "ccapi_string.h"
+#include "ccapi_ipc.h"
+#include "ccapi_context_change_time.h"
+
+#include <CredentialsCache2.h>
+
+typedef struct cci_context_d {
+    cc_context_f *functions;
+#if TARGET_OS_MAC
+    cc_context_f *vector_functions;
+#endif
+    cci_identifier_t identifier;
+    cc_uint32 synchronized;
+} *cci_context_t;
+
+/* ------------------------------------------------------------------------ */
+
+struct cci_context_d cci_context_initializer = { 
+    NULL 
+    VECTOR_FUNCTIONS_INITIALIZER,
+    NULL,
+    0
+};
+
+cc_context_f cci_context_f_initializer = { 
+    ccapi_context_release,
+    ccapi_context_get_change_time,
+    ccapi_context_get_default_ccache_name,
+    ccapi_context_open_ccache,
+    ccapi_context_open_default_ccache,
+    ccapi_context_create_ccache,
+    ccapi_context_create_default_ccache,
+    ccapi_context_create_new_ccache,
+    ccapi_context_new_ccache_iterator,
+    ccapi_context_lock,
+    ccapi_context_unlock,
+    ccapi_context_compare,
+    ccapi_context_wait_for_change
+};
+
+static cc_int32 cci_context_sync (cci_context_t in_context, 
+                                  cc_uint32     in_launch);
+
+#pragma mark -
+
+MAKE_INIT_FUNCTION(cci_thread_init);
+
+/* ------------------------------------------------------------------------ */
+
+static int cci_thread_init (void)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!err) {
+        err = cci_context_change_time_thread_init ();
+    }
+    
+    if (!err) {
+        err = cci_ipc_thread_init ();
+    }
+    
+    return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cc_initialize (cc_context_t  *out_context,
+                        cc_int32       in_version,
+                        cc_int32      *out_supported_version,
+                        char const   **out_vendor)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = NULL;
+    static char *vendor_string = "MIT Kerberos CCAPI";
+    
+    if (!out_context) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = CALL_INIT_FUNCTION (cci_thread_init);
+    }
+    
+    if (!err) {
+        switch (in_version) { 
+            case ccapi_version_2: 
+                err = CC_NOT_SUPP;
+                break;
+                
+            case ccapi_version_3:
+            case ccapi_version_4:
+            case ccapi_version_5:
+            case ccapi_version_6:
+                break;
+            
+            default: 
+                err = ccErrBadAPIVersion;
+                break;
+        }
+    }
+    
+    if (!err) {
+        context = malloc (sizeof (*context));
+        if (context) { 
+            *context = cci_context_initializer;
+        } else { 
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        context->functions = malloc (sizeof (*context->functions));
+        if (context->functions) { 
+            *context->functions = cci_context_f_initializer;
+        } else { 
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        context->identifier = cci_identifier_uninitialized;
+
+        *out_context = (cc_context_t) context;
+        context = NULL; /* take ownership */
+        
+        if (out_supported_version) {
+            *out_supported_version = ccapi_version_max;
+        }
+        
+        if (out_vendor) {
+            *out_vendor = vendor_string;
+        }
+    }
+    
+    ccapi_context_release ((cc_context_t) context);
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_release (cc_context_t in_context)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = (cci_context_t) in_context;
+    
+    if (!in_context) { err = ccErrBadParam; }
+    
+    if (!err) {
+        err = cci_context_sync (context, 0);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send_no_launch (cci_context_release_msg_id,
+                                       context->identifier,
+                                       NULL,
+                                       NULL);
+    }
+    
+    if (!err) {
+        cci_identifier_release (context->identifier);
+        free (context->functions);
+        free (context);
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_get_change_time (cc_context_t  in_context,
+                                        cc_time_t    *out_change_time)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = (cci_context_t) in_context;
+    cci_stream_t reply = NULL;
+    
+    if (!in_context     ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_change_time) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_context_sync (context, 0);
+    }
+
+    if (!err) {
+        err =  cci_ipc_send_no_launch (cci_context_get_change_time_msg_id,
+                                       context->identifier,
+                                       NULL, &reply);
+    }
+    
+    if (!err && cci_stream_size (reply) > 0) {
+        cc_time_t change_time = 0;
+        
+        /* got a response from the server */
+        err = cci_stream_read_time (reply, &change_time);
+        
+        if (!err) {
+            err = cci_context_change_time_update (context->identifier,
+                                                  change_time);
+        }
+    }
+    
+    if (!err) {
+        err = cci_context_change_time_get (out_change_time);
+    }
+    
+    cci_stream_release (reply);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_wait_for_change (cc_context_t  in_context)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = (cci_context_t) in_context;
+    
+    if (!in_context) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_context_sync (context, 0);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send_no_launch (cci_context_wait_for_change_msg_id,
+                                       context->identifier,
+                                       NULL, NULL);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_get_default_ccache_name (cc_context_t  in_context,
+                                                cc_string_t  *out_name)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = (cci_context_t) in_context;
+    cci_stream_t reply = NULL;
+    char *reply_name = NULL;
+    char *name = NULL;
+    
+    if (!in_context) { err = cci_check_error (ccErrBadParam); }
+    if (!out_name  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_context_sync (context, 0);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send_no_launch (cci_context_get_default_ccache_name_msg_id,
+                                       context->identifier,
+                                       NULL,
+                                       &reply);
+    }
+    
+    if (!err) {
+        if (cci_stream_size (reply) > 0) {
+            /* got a response from the server */
+            err = cci_stream_read_string (reply, &reply_name);
+            
+            if (!err) {
+                name = reply_name;
+            }
+        } else {
+            name = k_cci_context_initial_ccache_name;
+        }
+    }
+    
+    if (!err) {
+        err = cci_string_new (out_name, name);
+    }
+    
+    cci_stream_release (reply);
+    free (reply_name);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_open_ccache (cc_context_t  in_context,
+                                    const char   *in_name,
+                                    cc_ccache_t  *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = (cci_context_t) in_context;
+    cci_stream_t request = NULL;
+    cci_stream_t reply = NULL;
+    cci_identifier_t identifier = NULL;
+    
+    if (!in_context  ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_name     ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_ccache  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_string (request, in_name);
+    }
+    
+    if (!err) {
+        err = cci_context_sync (context, 0);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send_no_launch (cci_context_open_ccache_msg_id,
+                                       context->identifier,
+                                       request,
+                                       &reply);
+    }
+    
+    if (!err && !(cci_stream_size (reply) > 0)) {
+        err = ccErrCCacheNotFound;
+    }
+    
+    if (!err) {
+        err = cci_identifier_read (&identifier, reply);
+    }
+    
+    if (!err) {
+        err = cci_ccache_new (out_ccache, identifier);
+    }
+    
+    cci_identifier_release (identifier);
+    cci_stream_release (reply);
+    cci_stream_release (request);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_open_default_ccache (cc_context_t  in_context,
+                                            cc_ccache_t  *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = (cci_context_t) in_context;
+    cci_stream_t reply = NULL;
+    cci_identifier_t identifier = NULL;
+    
+    if (!in_context) { err = cci_check_error (ccErrBadParam); }
+    if (!out_ccache) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_context_sync (context, 0);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send_no_launch (cci_context_open_default_ccache_msg_id,
+                                       context->identifier,
+                                       NULL,
+                                       &reply);
+    }
+    
+    if (!err && !(cci_stream_size (reply) > 0)) {
+        err = ccErrCCacheNotFound;
+    }
+    
+    if (!err) {
+        err = cci_identifier_read (&identifier, reply);
+    }
+    
+    if (!err) {
+        err = cci_ccache_new (out_ccache, identifier);
+    }
+    
+    cci_identifier_release (identifier);
+    cci_stream_release (reply);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_create_ccache (cc_context_t  in_context,
+                                      const char   *in_name,
+                                      cc_uint32     in_cred_vers,
+                                      const char   *in_principal, 
+                                      cc_ccache_t  *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = (cci_context_t) in_context;
+    cci_stream_t request = NULL;
+    cci_stream_t reply = NULL;
+    cci_identifier_t identifier = NULL;
+    
+    if (!in_context  ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_name     ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_principal) { err = cci_check_error (ccErrBadParam); }
+    if (!out_ccache  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_string (request, in_name);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (request, in_cred_vers);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_string (request, in_principal);
+    }
+    
+    if (!err) {
+        err = cci_context_sync (context, 1);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_context_create_ccache_msg_id,
+                             context->identifier,
+                             request,
+                             &reply);
+    }
+    
+    if (!err) {
+        err = cci_identifier_read (&identifier, reply);
+    }
+    
+    if (!err) {
+        err = cci_ccache_new (out_ccache, identifier);
+    }
+    
+    cci_identifier_release (identifier);
+    cci_stream_release (reply);
+    cci_stream_release (request);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_create_default_ccache (cc_context_t  in_context,
+                                              cc_uint32     in_cred_vers,
+                                              const char   *in_principal, 
+                                              cc_ccache_t  *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = (cci_context_t) in_context;
+    cci_stream_t request = NULL;
+    cci_stream_t reply = NULL;
+    cci_identifier_t identifier = NULL;
+    
+    if (!in_context  ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_principal) { err = cci_check_error (ccErrBadParam); }
+    if (!out_ccache  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (request, in_cred_vers);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_string (request, in_principal);
+    }
+    
+    if (!err) {
+        err = cci_context_sync (context, 1);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_context_create_default_ccache_msg_id,
+                             context->identifier,
+                             request,
+                             &reply);
+    }
+    
+    if (!err) {
+        err = cci_identifier_read (&identifier, reply);
+    }
+    
+    if (!err) {
+        err = cci_ccache_new (out_ccache, identifier);
+    }
+    
+    cci_identifier_release (identifier);
+    cci_stream_release (reply);
+    cci_stream_release (request);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_create_new_ccache (cc_context_t in_context,
+                                          cc_uint32    in_cred_vers,
+                                          const char  *in_principal, 
+                                          cc_ccache_t *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = (cci_context_t) in_context;
+    cci_stream_t request = NULL;
+    cci_stream_t reply = NULL;
+    cci_identifier_t identifier = NULL;
+    
+    if (!in_context  ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_principal) { err = cci_check_error (ccErrBadParam); }
+    if (!out_ccache  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (request, in_cred_vers);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_string (request, in_principal);
+    }
+    
+    if (!err) {
+        err = cci_context_sync (context, 1);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_context_create_new_ccache_msg_id,
+                             context->identifier,
+                             request,
+                             &reply);
+    }
+    
+    if (!err) {
+        err = cci_identifier_read (&identifier, reply);
+    }
+    
+    if (!err) {
+        err = cci_ccache_new (out_ccache, identifier);
+    }
+    
+    cci_identifier_release (identifier);
+    cci_stream_release (reply);
+    cci_stream_release (request);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_new_ccache_iterator (cc_context_t          in_context,
+                                            cc_ccache_iterator_t *out_iterator)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = (cci_context_t) in_context;
+    cci_stream_t reply = NULL;
+    cci_identifier_t identifier = NULL;
+    
+    if (!in_context  ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_iterator) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_context_sync (context, 0);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send_no_launch (cci_context_new_ccache_iterator_msg_id,
+                                       context->identifier,
+                                       NULL,
+                                       &reply);
+    }
+    
+    if (!err) {
+        if (cci_stream_size (reply) > 0) {
+            err = cci_identifier_read (&identifier, reply);
+        } else {
+            identifier = cci_identifier_uninitialized;
+        }
+    }
+    
+    if (!err) {
+        err = cci_ccache_iterator_new (out_iterator, identifier);
+    }
+
+    cci_stream_release (reply);
+    cci_identifier_release (identifier);
+
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_lock (cc_context_t in_context,
+                             cc_uint32    in_lock_type,
+                             cc_uint32    in_block)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = (cci_context_t) in_context;
+    cci_stream_t request = NULL;
+    
+    if (!in_context) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&request);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (request, in_lock_type);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (request, in_block);
+    }
+    
+    if (!err) {
+        err = cci_context_sync (context, 1);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_context_lock_msg_id,
+                             context->identifier,
+                             request,
+                             NULL);
+    }
+    
+    cci_stream_release (request);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_unlock (cc_context_t in_context)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = (cci_context_t) in_context;
+    
+    if (!in_context) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_context_sync (context, 1);
+    }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_context_unlock_msg_id,
+                             context->identifier,
+                             NULL,
+                             NULL);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_context_compare (cc_context_t  in_context,
+                                cc_context_t  in_compare_to_context,
+                                cc_uint32    *out_equal)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = (cci_context_t) in_context;
+    cci_context_t compare_to_context = (cci_context_t) in_compare_to_context;
+    
+    if (!in_context           ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_compare_to_context) { err = cci_check_error (ccErrBadParam); }
+    if (!out_equal            ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_context_sync (context, 0);
+    }
+    
+    if (!err) {
+        err = cci_context_sync (compare_to_context, 0);
+    }
+    
+    if (!err) {
+        /* If both contexts can't talk to the server, then 
+         * we assume they are equivalent */
+        err = cci_identifier_compare (context->identifier, 
+                                      compare_to_context->identifier,
+                                      out_equal);
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 cci_context_sync (cci_context_t in_context, 
+                                  cc_uint32     in_launch)
+{
+    cc_int32 err = ccNoError;
+    cci_context_t context = (cci_context_t) in_context;
+    cci_stream_t reply = NULL;
+    cci_identifier_t new_identifier = NULL;
+    
+    if (!in_context) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        /* Use the uninitialized identifier because we may be talking  */
+        /* to a different server which would reject our identifier and */
+        /* the point of this message is to sync with the server's id   */
+        if (in_launch) {
+            err =  cci_ipc_send (cci_context_sync_msg_id,
+                                 cci_identifier_uninitialized,
+                                 NULL,
+                                 &reply);
+        } else {
+            err =  cci_ipc_send_no_launch (cci_context_sync_msg_id,
+                                           cci_identifier_uninitialized,
+                                           NULL,
+                                           &reply);
+        }
+    }
+    
+    if (!err) {
+        if (cci_stream_size (reply) > 0) {
+            err = cci_identifier_read (&new_identifier, reply);
+        } else {
+            new_identifier = cci_identifier_uninitialized;
+        }
+    }
+    
+    if (!err) {
+        cc_uint32 equal = 0;
+
+        err = cci_identifier_compare (context->identifier, new_identifier, &equal);
+
+        if (!err && !equal) {
+            if (context->identifier) {
+                cci_identifier_release (context->identifier);
+            }
+            context->identifier = new_identifier;
+            new_identifier = NULL;  /* take ownership */
+        }
+    }
+        
+    if (!err && context->synchronized) {
+        err = cci_context_change_time_sync (context->identifier);
+    }
+    
+    if (!err && !context->synchronized) {
+        /* Keep state about whether this is the first call to avoid always   */
+        /* modifying the global change time on the context's first ipc call. */
+        context->synchronized = 1;
+    }
+        
+    cci_identifier_release (new_identifier);
+    cci_stream_release (reply);
+    
+    return cci_check_error (err);
+}
+
diff --git a/src/ccapi/lib/ccapi_context.h b/src/ccapi/lib/ccapi_context.h
new file mode 100644 (file)
index 0000000..4ac0b06
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCAPI_CONTEXT_H
+#define CCAPI_CONTEXT_H
+
+#include "cci_common.h"
+
+cc_int32 ccapi_context_release (cc_context_t in_context);
+
+cc_int32 ccapi_context_get_change_time (cc_context_t  in_context,
+                                        cc_time_t    *out_time);
+
+cc_int32 ccapi_context_wait_for_change (cc_context_t  in_context);
+
+cc_int32 ccapi_context_get_default_ccache_name (cc_context_t  in_context,
+                                                cc_string_t  *out_name);
+
+cc_int32 ccapi_context_open_ccache (cc_context_t  in_context,
+                                    const char   *in_name,
+                                    cc_ccache_t  *out_ccache);
+
+cc_int32 ccapi_context_open_default_ccache (cc_context_t  in_context,
+                                            cc_ccache_t  *out_ccache);
+
+cc_int32 ccapi_context_create_ccache (cc_context_t  in_context,
+                                      const char   *in_name,
+                                      cc_uint32     in_cred_vers,
+                                      const char   *in_principal, 
+                                      cc_ccache_t  *out_ccache);
+
+cc_int32 ccapi_context_create_default_ccache (cc_context_t  in_context,
+                                              cc_uint32     in_cred_vers,
+                                              const char   *in_principal, 
+                                              cc_ccache_t  *out_ccache);
+
+cc_int32 ccapi_context_create_new_ccache (cc_context_t in_context,
+                                          cc_uint32    in_cred_vers,
+                                          const char  *in_principal, 
+                                          cc_ccache_t *out_ccache);
+
+cc_int32 ccapi_context_new_ccache_iterator (cc_context_t          in_context,
+                                            cc_ccache_iterator_t *out_iterator);
+
+cc_int32 ccapi_context_lock (cc_context_t in_context,
+                             cc_uint32    in_lock_type,
+                             cc_uint32    in_block);
+
+cc_int32 ccapi_context_unlock (cc_context_t in_context);
+
+cc_int32 ccapi_context_compare (cc_context_t  in_context,
+                                cc_context_t  in_compare_to_context,
+                                cc_uint32    *out_equal);
+
+#endif /* CCAPI_CONTEXT_H */
diff --git a/src/ccapi/lib/ccapi_context_change_time.c b/src/ccapi/lib/ccapi_context_change_time.c
new file mode 100644 (file)
index 0000000..fb5b7dd
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccapi_context_change_time.h"
+#include "cci_common.h"
+
+#include "k5-thread.h"
+
+static cci_identifier_t g_change_time_identifer = NULL;
+static cc_time_t g_change_time = 0;
+static cc_time_t g_change_time_offset = 0;
+static k5_mutex_t g_change_time_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_context_change_time_thread_init (void)
+{
+    return k5_mutex_finish_init(&g_change_time_mutex);
+}
+
+/* ------------------------------------------------------------------------ */
+/* WARNING!  Mutex must be locked when calling this!                        */
+
+static cc_int32 cci_context_change_time_update_identifier (cci_identifier_t  in_new_identifier,
+                                                           cc_uint32        *out_server_ids_match,
+                                                           cc_uint32        *out_old_server_running,
+                                                           cc_uint32        *out_new_server_running)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 server_ids_match = 0;
+    cc_uint32 old_server_running = 0;
+    cc_uint32 new_server_running = 0;
+    
+    if (!in_new_identifier) { err = cci_check_error (err); }
+    
+    if (!err && !g_change_time_identifer) {
+       g_change_time_identifer = cci_identifier_uninitialized;
+    }
+    
+    if (!err) {
+        err = cci_identifier_compare_server_id (g_change_time_identifer,
+                                                in_new_identifier,
+                                                &server_ids_match);
+    }
+    
+    if (!err && out_old_server_running) {
+        err = cci_identifier_is_initialized (g_change_time_identifer, &old_server_running);
+    }
+    
+    if (!err && out_new_server_running) {
+        err = cci_identifier_is_initialized (in_new_identifier, &new_server_running);
+    }
+    
+    if (!err && !server_ids_match) {
+        cci_identifier_t new_change_time_identifer = NULL;
+
+        err = cci_identifier_copy (&new_change_time_identifer, in_new_identifier);
+
+        if (!err) {
+            /* Save the new identifier */
+            if (g_change_time_identifer) {
+                cci_identifier_release (g_change_time_identifer);
+            }
+            g_change_time_identifer = new_change_time_identifer;
+        }
+    }
+    
+    if (!err) {
+        if (out_server_ids_match  ) { *out_server_ids_match = server_ids_match; }
+        if (out_old_server_running) { *out_old_server_running = old_server_running; }
+        if (out_new_server_running) { *out_new_server_running = new_server_running; }
+    }
+    
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_context_change_time_get (cc_time_t *out_change_time)
+{
+    cc_int32 err = ccNoError;
+    
+    err = k5_mutex_lock (&g_change_time_mutex);
+    
+    if (!err) {
+        *out_change_time = g_change_time + g_change_time_offset;
+        k5_mutex_unlock (&g_change_time_mutex);    
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_context_change_time_update (cci_identifier_t in_identifier,
+                                         cc_time_t        in_new_change_time)
+{
+    cc_int32 err = ccNoError;
+    cc_int32 lock_err = err = k5_mutex_lock (&g_change_time_mutex);
+    
+    if (!err) {
+        if (!in_identifier) { err = cci_check_error (err); }
+    }
+    
+    if (!err) {
+        if (g_change_time < in_new_change_time) {
+            /* Only update if it increases the time.  May be a different server. */
+            g_change_time = in_new_change_time;
+            cci_debug_printf ("%s: setting change time to %d", 
+                              __FUNCTION__, in_new_change_time);
+        }
+    }
+    
+    if (!err) {
+        err = cci_context_change_time_update_identifier (in_identifier,
+                                                         NULL, NULL, NULL);
+    }
+    
+    if (!lock_err) {
+        k5_mutex_unlock (&g_change_time_mutex);
+    }
+
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_context_change_time_sync (cci_identifier_t in_new_identifier)
+{
+    cc_int32 err = ccNoError;
+    cc_int32 lock_err = err = k5_mutex_lock (&g_change_time_mutex);
+    cc_uint32 server_ids_match = 0;
+    cc_uint32 server_was_running = 0;
+    cc_uint32 server_is_running = 0;
+    
+    if (!err) {
+        if (!in_new_identifier) { err = cci_check_error (err); }
+    }
+    
+    if (!err) {
+        err = cci_context_change_time_update_identifier (in_new_identifier,
+                                                         &server_ids_match,
+                                                         &server_was_running,
+                                                         &server_is_running);
+    }
+    
+    if (!err && !server_ids_match) {        
+        /* Increment the change time so callers re-read */
+        g_change_time_offset++; 
+        
+        /* If the server died, absorb the offset */
+        if (server_was_running && !server_is_running) {
+            cc_time_t now = time (NULL);
+            
+            g_change_time += g_change_time_offset;
+            g_change_time_offset = 0;
+            
+            /* Make sure the change time increases, ideally with the current time */
+            g_change_time = (g_change_time < now) ? now : g_change_time;
+        }
+        
+        cci_debug_printf ("%s noticed server changed ("
+                          "server_was_running = %d; server_is_running = %d; "
+                          "g_change_time = %d; g_change_time_offset = %d", 
+                          __FUNCTION__, server_was_running, server_is_running, 
+                          g_change_time, g_change_time_offset);            
+    }
+    
+    if (!lock_err) {
+        k5_mutex_unlock (&g_change_time_mutex);
+    }
+    
+    return err;
+}
diff --git a/src/ccapi/lib/ccapi_context_change_time.h b/src/ccapi/lib/ccapi_context_change_time.h
new file mode 100644 (file)
index 0000000..536c492
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCAPI_CONTEXT_CHANGE_TIME_H
+#define CCAPI_CONTEXT_CHANGE_TIME_H
+
+#include "cci_common.h"
+
+cc_int32 cci_context_change_time_thread_init (void);
+
+cc_int32 cci_context_change_time_get (cc_time_t *out_change_time);
+
+cc_int32 cci_context_change_time_update (cci_identifier_t in_identifier,
+                                         cc_time_t        in_new_change_time);
+
+cc_int32 cci_context_change_time_sync (cci_identifier_t in_new_identifier);
+
+#endif /* CCAPI_CONTEXT_CHANGE_TIME_H */
diff --git a/src/ccapi/lib/ccapi_credentials.c b/src/ccapi/lib/ccapi_credentials.c
new file mode 100644 (file)
index 0000000..4e1f48e
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccapi_credentials.h"
+
+#include "ccapi_string.h"
+
+/* ------------------------------------------------------------------------ */
+
+typedef struct cci_credentials_d {
+    cc_credentials_union *data;
+    cc_credentials_f *functions;
+#if TARGET_OS_MAC
+    cc_credentials_f *vector_functions;
+#endif
+    cci_identifier_t identifier;
+} *cci_credentials_t;
+
+/* ------------------------------------------------------------------------ */
+
+struct cci_credentials_d cci_credentials_initializer = { 
+    NULL, 
+    NULL 
+    VECTOR_FUNCTIONS_INITIALIZER, 
+    NULL
+};
+
+cc_credentials_f cci_credentials_f_initializer = { 
+    ccapi_credentials_release,
+    ccapi_credentials_compare
+};
+
+cc_credentials_union cci_cred_union_initializer = {
+    0,
+    { NULL }
+};
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_credentials_read (cc_credentials_t *out_credentials,
+                               cci_stream_t      in_stream)
+{
+    cc_int32 err = ccNoError;
+    cci_credentials_t credentials = NULL;
+    
+    if (!out_credentials) { err = cci_check_error (ccErrBadParam); }
+    if (!in_stream      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        credentials = malloc (sizeof (*credentials));
+        if (credentials) { 
+            *credentials = cci_credentials_initializer;
+        } else { 
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        credentials->functions = malloc (sizeof (*credentials->functions));
+        if (credentials->functions) { 
+            *credentials->functions = cci_credentials_f_initializer;
+        } else { 
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        err = cci_identifier_read (&credentials->identifier, in_stream);
+    }
+    
+    if (!err) {
+        err = cci_cred_union_read (&credentials->data, in_stream);
+    }
+    
+    if (!err) {
+        *out_credentials = (cc_credentials_t) credentials;
+        credentials = NULL; /* take ownership */
+    }
+    
+    if (credentials) { ccapi_credentials_release ((cc_credentials_t) credentials); }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_credentials_write (cc_credentials_t in_credentials,
+                                cci_stream_t     in_stream)
+{
+    cc_int32 err = ccNoError;
+    cci_credentials_t credentials = (cci_credentials_t) in_credentials;
+    
+    if (!in_credentials) { err = cci_check_error (ccErrBadParam); }
+    if (!in_stream     ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_write (credentials->identifier, in_stream);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_credentials_compare (cc_credentials_t  in_credentials,
+                                    cc_credentials_t  in_compare_to_credentials,
+                                    cc_uint32        *out_equal)
+{
+    cc_int32 err = ccNoError;
+    cci_credentials_t credentials = (cci_credentials_t) in_credentials;
+    cci_credentials_t compare_to_credentials = (cci_credentials_t) in_compare_to_credentials;
+    
+    if (!in_credentials           ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_compare_to_credentials) { err = cci_check_error (ccErrBadParam); }
+    if (!out_equal                ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_compare (credentials->identifier, 
+                                      compare_to_credentials->identifier,
+                                      out_equal);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_credentials_release (cc_credentials_t io_credentials)
+{
+    cc_int32 err = ccNoError;
+    cci_credentials_t credentials = (cci_credentials_t) io_credentials;
+    
+    if (!io_credentials) { err = ccErrBadParam; }
+    
+    if (!err) {
+        cci_cred_union_release (credentials->data);
+        free ((char *) credentials->functions);
+        cci_identifier_release (credentials->identifier);
+        free (credentials);
+    }
+    
+    return err;
+}
diff --git a/src/ccapi/lib/ccapi_credentials.h b/src/ccapi/lib/ccapi_credentials.h
new file mode 100644 (file)
index 0000000..bde0b2c
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCAPI_CREDENTIALS_H
+#define CCAPI_CREDENTIALS_H
+
+#include "cci_common.h"
+
+cc_int32 cci_credentials_read (cc_credentials_t *out_credentials,
+                               cci_stream_t      in_stream);
+
+cc_int32 cci_credentials_write (cc_credentials_t in_credentials,
+                                cci_stream_t     in_stream);
+
+cc_int32 ccapi_credentials_compare (cc_credentials_t  in_credentials,
+                                    cc_credentials_t  in_compare_to_credentials,
+                                    cc_uint32        *out_equal);
+
+cc_int32 ccapi_credentials_release (cc_credentials_t io_credentials);
+
+#endif /* CCAPI_CREDENTIALS_H */
diff --git a/src/ccapi/lib/ccapi_credentials_iterator.c b/src/ccapi/lib/ccapi_credentials_iterator.c
new file mode 100644 (file)
index 0000000..a99e52b
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccapi_credentials_iterator.h"
+#include "ccapi_credentials.h"
+#include "ccapi_ipc.h"
+
+/* ------------------------------------------------------------------------ */
+
+typedef struct cci_credentials_iterator_d {
+    cc_credentials_iterator_f *functions;
+#if TARGET_OS_MAC
+    cc_credentials_iterator_f *vector_functions;
+#endif
+    cci_identifier_t identifier;
+} *cci_credentials_iterator_t;
+
+/* ------------------------------------------------------------------------ */
+
+struct cci_credentials_iterator_d cci_credentials_iterator_initializer = { 
+    NULL 
+    VECTOR_FUNCTIONS_INITIALIZER, 
+    NULL
+};
+
+cc_credentials_iterator_f cci_credentials_iterator_f_initializer = { 
+    ccapi_credentials_iterator_release,
+    ccapi_credentials_iterator_next,
+    ccapi_credentials_iterator_clone
+};
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_credentials_iterator_new (cc_credentials_iterator_t *out_credentials_iterator,
+                                       cci_identifier_t           in_identifier)
+{
+    cc_int32 err = ccNoError;
+    cci_credentials_iterator_t credentials_iterator = NULL;
+    
+    if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier           ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        credentials_iterator = malloc (sizeof (*credentials_iterator));
+        if (credentials_iterator) { 
+            *credentials_iterator = cci_credentials_iterator_initializer;
+        } else { 
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        credentials_iterator->functions = malloc (sizeof (*credentials_iterator->functions));
+        if (credentials_iterator->functions) { 
+            *credentials_iterator->functions = cci_credentials_iterator_f_initializer;
+        } else { 
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        err = cci_identifier_copy (&credentials_iterator->identifier, in_identifier);
+    }
+    
+    if (!err) {
+        *out_credentials_iterator = (cc_credentials_iterator_t) credentials_iterator;
+        credentials_iterator = NULL; /* take ownership */
+    }
+    
+    if (credentials_iterator) { ccapi_credentials_iterator_release ((cc_credentials_iterator_t) credentials_iterator); }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_credentials_iterator_write (cc_credentials_iterator_t in_credentials_iterator,
+                                         cci_stream_t              in_stream)
+{
+    cc_int32 err = ccNoError;
+    cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator;
+    
+    if (!in_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+    if (!in_stream         ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_write (credentials_iterator->identifier, in_stream);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_credentials_iterator_release (cc_credentials_iterator_t io_credentials_iterator)
+{
+    cc_int32 err = ccNoError;
+    cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) io_credentials_iterator;
+    
+    if (!io_credentials_iterator) { err = ccErrBadParam; }
+    
+    if (!err) {
+        free ((char *) credentials_iterator->functions);
+        cci_identifier_release (credentials_iterator->identifier);
+        free (credentials_iterator);
+    }
+    
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_credentials_iterator_next (cc_credentials_iterator_t  in_credentials_iterator,
+                                          cc_credentials_t          *out_credentials)
+{
+    cc_int32 err = ccNoError;
+    cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator;
+    cci_stream_t reply = NULL;
+    
+    if (!in_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+    if (!out_credentials        ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_credentials_iterator_next_msg_id,
+                             credentials_iterator->identifier,
+                             NULL,
+                             &reply);
+    }
+    
+    if (!err) {
+        err = cci_credentials_read (out_credentials, reply);
+    }
+    
+    cci_stream_release (reply);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_credentials_iterator_clone (cc_credentials_iterator_t  in_credentials_iterator,
+                                           cc_credentials_iterator_t *out_credentials_iterator)
+{
+    cc_int32 err = ccNoError;
+    cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator;
+    cci_stream_t reply = NULL;
+    cci_identifier_t identifier = NULL;
+        
+    if (!in_credentials_iterator ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err =  cci_ipc_send (cci_credentials_iterator_next_msg_id,
+                             credentials_iterator->identifier,
+                             NULL,
+                             &reply);
+    }
+    
+    if (!err) {
+        err =  cci_identifier_read (&identifier, reply);
+    }
+    
+    if (!err) {
+        err = cci_credentials_iterator_new (out_credentials_iterator, identifier);
+    }
+    
+    cci_stream_release (reply);
+    cci_identifier_release (identifier);
+    
+    return cci_check_error (err);
+}
diff --git a/src/ccapi/lib/ccapi_credentials_iterator.h b/src/ccapi/lib/ccapi_credentials_iterator.h
new file mode 100644 (file)
index 0000000..7ffbd23
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCAPI_CREDENTIALS_ITERATOR_H
+#define CCAPI_CREDENTIALS_ITERATOR_H
+
+#include "cci_common.h"
+
+cc_int32 cci_credentials_iterator_new (cc_credentials_iterator_t *out_credentials_iterator,
+                                       cci_identifier_t           in_identifier);
+
+cc_int32 cci_credentials_iterator_write (cc_credentials_iterator_t in_credentials_iterator,
+                                         cci_stream_t              in_stream);
+
+cc_int32 ccapi_credentials_iterator_release (cc_credentials_iterator_t io_credentials_iterator);
+
+cc_int32 ccapi_credentials_iterator_next (cc_credentials_iterator_t  in_credentials_iterator,
+                                          cc_credentials_t          *out_credentials);
+
+cc_int32 ccapi_credentials_iterator_clone (cc_credentials_iterator_t  in_credentials_iterator,
+                                           cc_credentials_iterator_t *out_credentials_iterator);
+
+#endif /* CCAPI_CREDENTIALS_ITERATOR_H */
diff --git a/src/ccapi/lib/ccapi_err.et b/src/ccapi/lib/ccapi_err.et
new file mode 100644 (file)
index 0000000..44cd2d0
--- /dev/null
@@ -0,0 +1,74 @@
+#
+# $Header$
+#
+# Copyright 1998-2006 Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# Export of this software from the United States of America may
+# require a specific license from the United States Government.
+# It is the responsibility of any person or organization contemplating
+# export to obtain such a license before exporting.
+#
+# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+# distribute this software and its documentation for any purpose and
+# without fee is hereby granted, provided that the above copyright
+# notice appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation, and that
+# the name of M.I.T. not be used in advertising or publicity pertaining
+# to distribution of the software without specific, written prior
+# permission.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# M.I.T. makes no representations about the suitability of
+# this software for any purpose.  It is provided "as is" without express
+# or implied warranty.
+#
+
+error_table_base 201
+error_table_manager "Credentials Cache"
+error_table CAPI
+
+# 201
+error_code ccIteratorEnd,                       "Reached end of iterator"
+error_code ccErrBadParam,                       "Invalid argument"
+error_code ccErrNoMem,                          "Out of memory"
+error_code ccErrInvalidContext,                 "Invalid credentials cache context"
+error_code ccErrInvalidCCache,                  "Invalid credentials cache"
+
+# 206
+index 5
+error_code ccErrInvalidString,                  "Invalid credentials cache string"
+error_code ccErrInvalidCredentials,             "Invalid credentials"
+error_code ccErrInvalidCCacheIterator,          "Invalid credentials cache iterator"
+error_code ccErrInvalidCredentialsIterator,     "Invalid credentials iterator"
+error_code ccErrInvalidLock,                    "Invalid iterator"
+
+# 211
+index 10
+error_code ccErrBadName,                        "Invalid credentials cache name"
+error_code ccErrBadCredentialsVersion,          "Invalid credentials cache version (not 4 or 5)"
+error_code ccErrBadAPIVersion,                  "Invalid CCAPI version"
+error_code ccErrContextLocked,                  "Credentials cache context is already locked"
+error_code ccErrContextUnlocked,                "Credentials cache context is already unlocked"
+
+# 216
+index 15
+error_code ccErrCCacheLocked,                   "Credentials cache is already locked"
+error_code ccErrCCacheUnlocked,                 "Credentials cache is already unlocked"
+error_code ccErrBadLockType,                    "Invalid credentials cache lock type"
+error_code ccErrNeverDefault,                   "Credentials cache has never been the default cache"
+error_code ccErrCredentialsNotFound,            "Credentials not found"
+
+# 221
+index 20
+error_code ccErrCCacheNotFound,                 "Credentials cache not found"
+error_code ccErrContextNotFound,                "Credentials cache context not found"
+error_code ccErrServerUnavailable,              "Credentials cache server unavailable"
+error_code ccErrServerInsecure,                 "Credentials cache server in this bootstrap is owned by another user"
+error_code ccErrServerCantBecomeUID,            "Credentials cache server failed to change effective uids"
+
+# 226
+index 25
+error_code ccErrTimeOffsetNotSet,               "Credentials cache time offset not set"
+
+end
diff --git a/src/ccapi/lib/ccapi_ipc.c b/src/ccapi/lib/ccapi_ipc.c
new file mode 100644 (file)
index 0000000..4d2e431
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccapi_ipc.h"
+#include "ccapi_os_ipc.h"
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ipc_thread_init (void)
+{
+    return cci_os_ipc_thread_init ();
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 _cci_ipc_send (enum cci_msg_id_t  in_request_name,
+                               cc_int32           in_launch_server,
+                               cci_identifier_t   in_identifier,
+                               cci_stream_t       in_request_data,
+                               cci_stream_t      *out_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cci_stream_t request = NULL;
+    cci_stream_t reply = NULL;
+    cc_int32 reply_error = 0;
+    
+    if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+    /* in_request_data may be NULL */
+    /* out_reply_data may be NULL */
+    
+    if (!err) {
+        err = cci_message_new_request_header (&request,
+                                              in_request_name,
+                                              in_identifier);
+    }
+    
+    if (!err && in_request_data) {
+        err = cci_stream_write (request, 
+                                cci_stream_data (in_request_data), 
+                                cci_stream_size (in_request_data));
+    }
+    
+    if (!err) {
+        err = cci_os_ipc (in_launch_server, request, &reply);
+
+        if (!err && cci_stream_size (reply) > 0) {
+            err = cci_message_read_reply_header (reply, &reply_error);
+        }
+    }
+    
+    if (!err && reply_error) { 
+        err = reply_error;
+    }
+    
+    if (!err && out_reply_data) {
+        *out_reply_data = reply;
+        reply = NULL; /* take ownership */
+    }
+    
+    cci_stream_release (request);
+    cci_stream_release (reply);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ipc_send (enum cci_msg_id_t  in_request_name,
+                       cci_identifier_t   in_identifier,
+                       cci_stream_t       in_request_data,
+                       cci_stream_t      *out_reply_data)
+{
+    return cci_check_error (_cci_ipc_send (in_request_name, 1,
+                                           in_identifier,
+                                           in_request_data,
+                                           out_reply_data));
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_ipc_send_no_launch (enum cci_msg_id_t  in_request_name,
+                                 cci_identifier_t   in_identifier,
+                                 cci_stream_t       in_request_data,
+                                 cci_stream_t      *out_reply_data)
+{
+    return cci_check_error (_cci_ipc_send (in_request_name, 0,
+                                           in_identifier,
+                                           in_request_data,
+                                           out_reply_data));
+}
diff --git a/src/ccapi/lib/ccapi_ipc.h b/src/ccapi/lib/ccapi_ipc.h
new file mode 100644 (file)
index 0000000..73c5b24
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCAPI_IPC_H
+#define CCAPI_IPC_H
+
+#include "cci_common.h"
+
+cc_int32 cci_ipc_thread_init (void);
+
+cc_int32 cci_ipc_send (enum cci_msg_id_t  in_request_name,
+                       cci_identifier_t   in_identifier,
+                       cci_stream_t       in_request_data,
+                       cci_stream_t      *out_reply_data);
+
+cc_int32 cci_ipc_send_no_launch (enum cci_msg_id_t  in_request_name,
+                                 cci_identifier_t   in_identifier,
+                                 cci_stream_t       in_request_data,
+                                 cci_stream_t      *out_reply_data);
+
+#endif /* CCAPI_IPC_H */
diff --git a/src/ccapi/lib/ccapi_os_ipc.h b/src/ccapi/lib/ccapi_os_ipc.h
new file mode 100644 (file)
index 0000000..8cce06c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCAPI_OS_IPC_H
+#define CCAPI_OS_IPC_H
+
+#include "cci_common.h"
+
+inline cc_int32 cci_os_ipc_thread_init (void);
+
+cc_int32 cci_os_ipc (cc_int32      in_launch_server,
+                     cci_stream_t  in_request_stream,
+                     cci_stream_t *out_reply_stream);
+
+#endif /* CCAPI_OS_IPC_H */
diff --git a/src/ccapi/lib/ccapi_string.c b/src/ccapi/lib/ccapi_string.c
new file mode 100644 (file)
index 0000000..4acd9a8
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccapi_string.h"
+
+/* ------------------------------------------------------------------------ */
+
+cc_string_d cci_string_d_initializer = { 
+    NULL, 
+    NULL 
+    VECTOR_FUNCTIONS_INITIALIZER };
+
+cc_string_f cci_string_f_initializer = { 
+    ccapi_string_release 
+};
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_string_new (cc_string_t *out_string,
+                         char        *in_cstring)
+{
+    cc_int32 err = ccNoError;
+    cc_string_t string = NULL;
+    
+    if (!out_string) { err = cci_check_error (ccErrBadParam); }
+    if (!in_cstring) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        string = malloc (sizeof (*string));
+        if (string) { 
+            *string = cci_string_d_initializer;
+        } else { 
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+
+    if (!err) {
+        string->functions = malloc (sizeof (*string->functions));
+        if (string->functions) { 
+            *((cc_string_f *) string->functions) = cci_string_f_initializer;
+        } else { 
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        string->data = malloc (strlen (in_cstring) + 1);
+        if (string->data) { 
+            strcpy ((char *)string->data, in_cstring);
+        } else { 
+            err = cci_check_error (ccErrNoMem); 
+        }
+        
+    }
+    
+    if (!err) {
+        *out_string = string;
+        string = NULL; /* take ownership */
+    }
+    
+    if (string) { ccapi_string_release (string); }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccapi_string_release (cc_string_t in_string)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_string) { err = ccErrBadParam; }
+    
+    if (!err) {
+        free ((char *) in_string->data);
+        free ((char *) in_string->functions);
+        free (in_string);
+    }
+    
+    return err;
+}
diff --git a/src/ccapi/lib/ccapi_string.h b/src/ccapi/lib/ccapi_string.h
new file mode 100644 (file)
index 0000000..dec7a7c
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCAPI_STRING_H
+#define CCAPI_STRING_H
+
+#include "cci_common.h"
+
+cc_int32 cci_string_new (cc_string_t *out_string,
+                         char        *in_cstring);
+
+cc_int32 ccapi_string_release (cc_string_t in_string);
+
+#endif /* CCAPI_STRING_H */
diff --git a/src/ccapi/lib/ccapi_v2.c b/src/ccapi/lib/ccapi_v2.c
new file mode 100644 (file)
index 0000000..0036c70
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "cci_common.h"
+#include <CredentialsCache2.h>
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_shutdown (apiCB **io_context) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_get_NC_info (apiCB    *in_context,
+                          infoNC ***out_info)
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_get_change_time (apiCB     *in_context,
+                              cc_time_t *out_change_time) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cc_open (apiCB       *in_context,
+                  const char  *in_name,
+                  cc_int32     in_version,
+                  cc_uint32    in_flags,
+                  ccache_p   **out_ccache) 
+{    
+    return CC_NOT_SUPP;
+}    
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_create (apiCB       *in_context,
+                     const char  *in_name,
+                     const char  *in_principal,
+                     cc_int32     in_version,
+                     cc_uint32    in_flags,
+                     ccache_p   **out_ccache) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_close (apiCB     *in_context,
+                    ccache_p **io_ccache) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_destroy (apiCB     *in_context,
+                      ccache_p **io_ccache) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_seq_fetch_NCs_begin (apiCB       *in_context,
+                                  ccache_cit **out_iterator) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+// CCache iterators need to return some ccaches twice (when v3 ccache has
+// two kinds of credentials). To do that, we use a single v3 iterator, but
+// sometimes don't advance it.
+
+cc_result cc_seq_fetch_NCs_next (apiCB       *in_context,
+                                 ccache_p   **out_ccache,
+                                 ccache_cit  *in_iterator) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_seq_fetch_NCs_end (apiCB       *in_context,
+                                ccache_cit **io_iterator) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_get_name (apiCB     *in_context,
+                       ccache_p  *in_ccache,
+                       char     **out_name) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_get_cred_version (apiCB    *in_context,
+                               ccache_p *in_ccache,
+                               cc_int32 *out_version) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_set_principal (apiCB    *in_context,
+                            ccache_p *io_ccache,
+                            cc_int32  in_version,
+                            char     *in_principal) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_get_principal (apiCB      *in_context,
+                            ccache_p   *in_ccache,
+                            char      **out_principal) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_store (apiCB      *in_context,
+                    ccache_p   *io_ccache,
+                    cred_union  in_credentials) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_remove_cred (apiCB      *in_context,
+                          ccache_p   *in_ccache,
+                          cred_union  in_credentials) 
+{
+    return CC_NOT_SUPP;
+}      
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_seq_fetch_creds_begin (apiCB           *in_context,
+                                    const ccache_p  *in_ccache,
+                                    ccache_cit     **out_iterator) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_seq_fetch_creds_next (apiCB       *in_context,
+                                   cred_union **out_creds,
+                                   ccache_cit  *in_iterator) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_seq_fetch_creds_end (apiCB       *in_context,
+                                  ccache_cit **io_iterator) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_free_principal (apiCB  *in_context,
+                             char  **io_principal) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_free_name (apiCB  *in_context,
+                        char  **io_name) 
+{    
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_free_creds (apiCB       *in_context,
+                         cred_union **io_credentials) 
+{
+    return CC_NOT_SUPP;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_result cc_free_NC_info (apiCB    *in_context,
+                           infoNC ***io_info) 
+{    
+    return CC_NOT_SUPP;
+}
diff --git a/src/ccapi/lib/ccapi_v2.exports b/src/ccapi/lib/ccapi_v2.exports
new file mode 100644 (file)
index 0000000..efa9fce
--- /dev/null
@@ -0,0 +1,23 @@
+cc_shutdown
+cc_create
+cc_close
+cc_destroy
+cc_get_change_time
+cc_open
+cc_store
+cc_remove_cred
+cc_set_principal
+cc_get_principal
+cc_get_cred_version
+cc_get_name
+cc_seq_fetch_NCs_begin
+cc_seq_fetch_NCs_next
+cc_seq_fetch_NCs_end
+cc_seq_fetch_creds_begin
+cc_seq_fetch_creds_next
+cc_seq_fetch_creds_end
+cc_get_NC_info
+cc_free_principal
+cc_free_name
+cc_free_creds
+cc_free_NC_info
diff --git a/src/ccapi/lib/mac/ccapi_os_ipc.c b/src/ccapi/lib/mac/ccapi_os_ipc.c
new file mode 100644 (file)
index 0000000..ea3b548
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccapi_os_ipc.h"
+
+#include <Kerberos/kipc_client.h>
+#include "cci_mig_request.h"
+#include "cci_mig_replyServer.h"
+#include "k5-thread.h"
+
+#define cci_server_bundle_id "edu.mit.Kerberos.CCacheServer"
+#define cci_server_path "/System/Library/CoreServices/CCacheServer.app/Contents/MacOS/CCacheServer"
+
+static pthread_key_t g_request_port_key = 0;
+static pthread_key_t g_reply_stream_key = 0;
+static pthread_key_t g_server_died_key = 0;
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 cci_os_ipc_thread_init (void)
+{
+    cc_int32 err = ccNoError;
+
+    err = pthread_key_create (&g_request_port_key, free);
+    
+    if (!err) {
+        err = pthread_key_create (&g_reply_stream_key, NULL);
+    }
+    
+    if (!err) {
+        err = pthread_key_create (&g_server_died_key, NULL);
+    }
+    
+    return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static boolean_t cci_server_demux (mach_msg_header_t *request, 
+                                   mach_msg_header_t *reply) 
+{
+    boolean_t handled = false;
+    
+    if (!handled && request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
+        cc_int32 *server_died = pthread_getspecific (g_server_died_key);
+        if (!server_died) { 
+            *server_died = 1;
+        }
+        
+        handled = 1; /* server died */
+    }
+    
+    if (!handled) {
+        handled = cci_server (request, reply);
+    }
+    
+    return handled;    
+}
+
+/* ------------------------------------------------------------------------ */
+
+kern_return_t cci_mipc_reply (mach_port_t             in_reply_port,
+                              cci_mipc_inl_reply_t    in_inl_reply,
+                              mach_msg_type_number_t  in_inl_replyCnt,
+                              cci_mipc_ool_reply_t    in_ool_reply,
+                              mach_msg_type_number_t  in_ool_replyCnt)
+{
+    kern_return_t err = KERN_SUCCESS;
+    cci_stream_t reply_stream = NULL;
+    
+    if (!err) {
+        reply_stream = pthread_getspecific (g_reply_stream_key);
+        if (!reply_stream) { err = cci_check_error (ccErrBadInternalMessage); }
+    }
+    
+    if (!err) {
+        if (in_inl_replyCnt) {
+            err = cci_stream_write (reply_stream, in_inl_reply, in_inl_replyCnt);
+            
+        } else if (in_ool_replyCnt) {
+            err = cci_stream_write (reply_stream, in_ool_reply, in_ool_replyCnt);
+            
+        } else {
+            err = cci_check_error (ccErrBadInternalMessage);
+        }
+    }
+    
+    if (in_ool_replyCnt) { vm_deallocate (mach_task_self (), (vm_address_t) in_ool_reply, in_ool_replyCnt); }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_os_ipc (cc_int32      in_launch_server,
+                     cci_stream_t  in_request_stream,
+                     cci_stream_t *out_reply_stream)
+{
+    cc_int32 err = ccNoError;
+    cc_int32 done = 0;
+    cc_int32 try_count = 0;
+    cc_int32 server_died = 0;
+    mach_port_t server_port = MACH_PORT_NULL;
+    mach_port_t *request_port = NULL;
+    mach_port_t reply_port = MACH_PORT_NULL;
+    const char *inl_request = NULL; /* char * so we can pass the buffer in directly */
+    mach_msg_type_number_t inl_request_length = 0;
+    cci_mipc_ool_request_t ool_request = NULL;
+    mach_msg_type_number_t ool_request_length = 0;
+    cci_stream_t reply_stream = NULL;
+    
+    if (!in_request_stream) { err = cci_check_error (ccErrBadParam); }
+    if (!out_reply_stream ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = kipc_client_lookup_server (cci_server_bundle_id, cci_server_path, 
+                                         in_launch_server, &server_port);
+    }
+    
+    if (!err) {
+        /* depending on how big the message is, use the fast inline buffer or  
+        * the slow dynamically allocated buffer */
+        mach_msg_type_number_t request_length = cci_stream_size (in_request_stream);
+        
+        if (request_length > kCCAPIMaxILMsgSize) {
+            cci_debug_printf ("%s choosing out of line buffer (size is %d)", 
+                              __FUNCTION__, request_length);
+            
+            err = vm_read (mach_task_self (), 
+                           (vm_address_t) cci_stream_data (in_request_stream), request_length, 
+                           (vm_address_t *) &ool_request, &ool_request_length);        
+        } else {
+            //cci_debug_printf ("%s choosing in line buffer (size is %d)",
+            //                  __FUNCTION__, request_length);
+            
+            inl_request_length = request_length;
+            inl_request = cci_stream_data (in_request_stream);
+        }
+    }
+    
+    if (!err) {
+        request_port = pthread_getspecific (g_request_port_key);
+        
+        if (!request_port) {
+            request_port = malloc (sizeof (mach_port_t));
+            if (!request_port) { err = cci_check_error (ccErrNoMem); }
+            
+            if (!err) {
+                *request_port = MACH_PORT_NULL;
+                err = pthread_setspecific (g_request_port_key, request_port);
+            }
+        }
+    }
+    
+    if (!err) {
+        err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &reply_port);
+    }
+
+    while (!err && !done) {
+        if (!err && !MACH_PORT_VALID (*request_port)) {
+            err = cci_mipc_create_client_connection (server_port, request_port);
+        }
+        
+        if (!err) {
+            err = cci_mipc_request (*request_port, reply_port,
+                                    inl_request, inl_request_length,
+                                    ool_request, ool_request_length);
+            
+        }
+        
+        if (err == MACH_SEND_INVALID_DEST) {
+            if (request_port && MACH_PORT_VALID (*request_port)) {
+                mach_port_mod_refs (mach_task_self(), *request_port, MACH_PORT_RIGHT_SEND, -1 );
+                *request_port = MACH_PORT_NULL;
+            }    
+            
+            if (try_count < 2) { 
+                try_count++;
+                err = ccNoError;
+            }
+        } else {
+            /* Talked to server, though we may have gotten an error */
+            done = 1;
+            
+            /* Because we use ",dealloc" ool_request will be freed by mach. 
+            * Don't double free it. */
+            ool_request = NULL; 
+            ool_request_length = 0;                
+        }            
+    }
+    
+    if (!err) {
+        err = cci_stream_new (&reply_stream);
+    }
+    
+    if (!err) {
+        err = pthread_setspecific (g_reply_stream_key, reply_stream);
+    }
+    
+    if (!err) {
+        err = pthread_setspecific (g_server_died_key, &server_died);
+    }
+    
+    if (!err) {
+        mach_port_t old_notification_target = MACH_PORT_NULL;
+
+        /* request no-senders notification so we can get a message when server dies */
+        err = mach_port_request_notification (mach_task_self (), reply_port, 
+                                              MACH_NOTIFY_NO_SENDERS, 1, reply_port, 
+                                              MACH_MSG_TYPE_MAKE_SEND_ONCE, 
+                                              &old_notification_target );
+    }
+    
+    if (!err) {
+        err = mach_msg_server_once (cci_server_demux, kkipc_max_message_size, 
+                                    reply_port, MACH_MSG_TIMEOUT_NONE);
+    }
+    
+    if (!err && server_died) {
+        err = cci_check_error (ccErrServerUnavailable);
+    }
+    
+    if (err == BOOTSTRAP_UNKNOWN_SERVICE && !in_launch_server) {
+        err = ccNoError;  /* If the server is not running just return an empty stream. */
+    }
+    
+    if (!err) {
+        *out_reply_stream = reply_stream;
+        reply_stream = NULL;
+    }
+    
+    pthread_setspecific (g_reply_stream_key, NULL);
+    pthread_setspecific (g_server_died_key, NULL);
+    if (MACH_PORT_VALID (reply_port)) { mach_port_deallocate (mach_task_self (), reply_port); }
+    if (ool_request_length          ) { vm_deallocate (mach_task_self (), (vm_address_t) ool_request, ool_request_length); }
+    if (reply_stream                ) { cci_stream_release (reply_stream); }
+    
+    return cci_check_error (err);    
+}
diff --git a/src/ccapi/lib/mac/ccapi_vector.c b/src/ccapi/lib/mac/ccapi_vector.c
new file mode 100644 (file)
index 0000000..ea749c0
--- /dev/null
@@ -0,0 +1,839 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccapi_vector.h"
+
+#include "ccapi_context.h"
+#include "ccapi_string.h"
+#include "ccapi_ccache.h"
+#include "ccapi_credentials.h"
+#include "ccapi_ccache_iterator.h"
+#include "ccapi_credentials_iterator.h"
+
+/* ------------------------------------------------------------------------ */
+
+static void cci_swap_string_functions (cc_string_t io_string)
+{
+    cc_string_f temp = *(io_string->functions);
+    *((cc_string_f *)io_string->functions) = *(io_string->vector_functions);
+    *((cc_string_f *)io_string->vector_functions) = temp;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void cci_swap_context_functions (cc_context_t io_context)
+{
+    cc_context_f temp = *(io_context->functions);
+    *((cc_context_f *)io_context->functions) = *(io_context->vector_functions);
+    *((cc_context_f *)io_context->vector_functions) = temp;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void cci_swap_ccache_functions (cc_ccache_t io_ccache)
+{
+    cc_ccache_f temp = *(io_ccache->functions);
+    *((cc_ccache_f *)io_ccache->functions) = *(io_ccache->vector_functions);
+    *((cc_ccache_f *)io_ccache->vector_functions) = temp;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void cci_swap_credentials_functions (cc_credentials_t io_credentials)
+{
+    cc_credentials_f temp = *(io_credentials->functions);
+    *((cc_credentials_f *)io_credentials->functions) = *(io_credentials->otherFunctions);
+    *((cc_credentials_f *)io_credentials->otherFunctions) = temp;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void cci_swap_ccache_iterator_functions (cc_ccache_iterator_t io_ccache_iterator)
+{
+    cc_ccache_iterator_f temp = *(io_ccache_iterator->functions);
+    *((cc_ccache_iterator_f *)io_ccache_iterator->functions) = *(io_ccache_iterator->vector_functions);
+    *((cc_ccache_iterator_f *)io_ccache_iterator->vector_functions) = temp;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void cci_swap_credentials_iterator_functions (cc_credentials_iterator_t io_credentials_iterator)
+{
+    cc_credentials_iterator_f temp = *(io_credentials_iterator->functions);
+    *((cc_credentials_iterator_f *)io_credentials_iterator->functions) = *(io_credentials_iterator->vector_functions);
+    *((cc_credentials_iterator_f *)io_credentials_iterator->vector_functions) = temp;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_initialize_vector (cc_context_t  *out_context,
+                                 cc_int32       in_version,
+                                 cc_int32      *out_supported_version,
+                                 char const   **out_vendor)
+{
+    return cc_initialize (out_context, in_version, out_supported_version, out_vendor);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_string_release_vector (cc_string_t in_string)
+{
+    cci_swap_string_functions (in_string);
+    return ccapi_string_release (in_string);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_release_vector (cc_context_t io_context)
+{
+    cci_swap_context_functions (io_context);
+    return ccapi_context_release (io_context);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_get_change_time_vector (cc_context_t  in_context,
+                                              cc_time_t    *out_change_time)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = ccapi_context_get_change_time (in_context, out_change_time);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_get_default_ccache_name_vector (cc_context_t  in_context,
+                                                      cc_string_t  *out_name)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = ccapi_context_get_default_ccache_name (in_context, out_name);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_open_ccache_vector (cc_context_t  in_context,
+                                          const char   *in_name,
+                                          cc_ccache_t  *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = ccapi_context_open_ccache (in_context, in_name, out_ccache);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_open_default_ccache_vector (cc_context_t  in_context,
+                                                  cc_ccache_t  *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = ccapi_context_open_default_ccache (in_context, out_ccache);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_create_ccache_vector (cc_context_t  in_context,
+                                            const char   *in_name,
+                                            cc_uint32     in_cred_vers,
+                                            const char   *in_principal, 
+                                            cc_ccache_t  *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = ccapi_context_create_ccache (in_context, in_name, in_cred_vers, in_principal, out_ccache);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_create_default_ccache_vector (cc_context_t  in_context,
+                                                    cc_uint32     in_cred_vers,
+                                                    const char   *in_principal, 
+                                                    cc_ccache_t  *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = ccapi_context_create_default_ccache (in_context, in_cred_vers, in_principal, out_ccache);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_create_new_ccache_vector (cc_context_t in_context,
+                                                cc_uint32    in_cred_vers,
+                                                const char  *in_principal, 
+                                                cc_ccache_t *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = ccapi_context_create_new_ccache (in_context, in_cred_vers, in_principal, out_ccache);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_new_ccache_iterator_vector (cc_context_t          in_context,
+                                                  cc_ccache_iterator_t *out_iterator)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = ccapi_context_new_ccache_iterator (in_context, out_iterator);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_lock_vector (cc_context_t in_context,
+                                   cc_uint32    in_lock_type,
+                                   cc_uint32    in_block)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = ccapi_context_lock (in_context, in_lock_type, in_block);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_unlock_vector (cc_context_t in_context)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = ccapi_context_unlock (in_context);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_context_compare_vector (cc_context_t  in_context,
+                                      cc_context_t  in_compare_to_context,
+                                      cc_uint32    *out_equal)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = ccapi_context_compare (in_context, in_compare_to_context, out_equal);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_release_vector (cc_ccache_t io_ccache)
+{
+    cci_swap_ccache_functions (io_ccache);
+    return ccapi_ccache_release (io_ccache);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_destroy_vector (cc_ccache_t io_ccache)
+{
+    cci_swap_ccache_functions (io_ccache);
+    return ccapi_ccache_destroy (io_ccache);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_set_default_vector (cc_ccache_t io_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_functions (io_ccache);
+    err = ccapi_ccache_set_default (io_ccache);
+    cci_swap_ccache_functions (io_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 __cc_ccache_get_credentials_version_vector (cc_ccache_t  in_ccache,
+                                                      cc_uint32   *out_credentials_version)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_functions (in_ccache);
+    err = ccapi_ccache_get_credentials_version (in_ccache, out_credentials_version);
+    cci_swap_ccache_functions (in_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_get_name_vector (cc_ccache_t  in_ccache,
+                                      cc_string_t *out_name)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_functions (in_ccache);
+    err = ccapi_ccache_get_name (in_ccache, out_name);
+    cci_swap_ccache_functions (in_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_get_principal_vector (cc_ccache_t  in_ccache,
+                                           cc_uint32    in_credentials_version,
+                                           cc_string_t *out_principal)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_functions (in_ccache);
+    err = ccapi_ccache_get_principal (in_ccache, in_credentials_version, out_principal);
+    cci_swap_ccache_functions (in_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_set_principal_vector (cc_ccache_t  io_ccache,
+                                           cc_uint32    in_credentials_version,
+                                           const char  *in_principal)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_functions (io_ccache);
+    err = ccapi_ccache_set_principal (io_ccache, in_credentials_version, in_principal);
+    cci_swap_ccache_functions (io_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_store_credentials_vector (cc_ccache_t                 io_ccache,
+                                               const cc_credentials_union *in_credentials_union)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_functions (io_ccache);
+    err = ccapi_ccache_store_credentials (io_ccache, in_credentials_union);
+    cci_swap_ccache_functions (io_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_remove_credentials_vector (cc_ccache_t      io_ccache,
+                                                cc_credentials_t in_credentials)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_functions (io_ccache);
+    cci_swap_credentials_functions (in_credentials);
+    err = ccapi_ccache_remove_credentials (io_ccache, in_credentials);
+    cci_swap_ccache_functions (io_ccache);
+    cci_swap_credentials_functions (in_credentials);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_new_credentials_iterator_vector (cc_ccache_t                in_ccache,
+                                                      cc_credentials_iterator_t *out_credentials_iterator)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_functions (in_ccache);
+    err = ccapi_ccache_new_credentials_iterator (in_ccache, out_credentials_iterator);
+    cci_swap_ccache_functions (in_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_move_vector (cc_ccache_t io_source_ccache,
+                                  cc_ccache_t io_destination_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_functions (io_source_ccache);
+    cci_swap_ccache_functions (io_destination_ccache);
+    err = ccapi_ccache_move (io_source_ccache, io_destination_ccache);
+    cci_swap_ccache_functions (io_source_ccache);
+    cci_swap_ccache_functions (io_destination_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_lock_vector (cc_ccache_t io_ccache,
+                                  cc_uint32   in_lock_type,
+                                  cc_uint32   in_block)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_functions (io_ccache);
+    err = ccapi_ccache_lock (io_ccache, in_lock_type, in_block);
+    cci_swap_ccache_functions (io_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_unlock_vector (cc_ccache_t io_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_functions (io_ccache);
+    err = ccapi_ccache_unlock (io_ccache);
+    cci_swap_ccache_functions (io_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_get_last_default_time_vector (cc_ccache_t  in_ccache,
+                                                   cc_time_t   *out_last_default_time)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_functions (in_ccache);
+    err = ccapi_ccache_get_last_default_time (in_ccache, out_last_default_time);
+    cci_swap_ccache_functions (in_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_get_change_time_vector (cc_ccache_t  in_ccache,
+                                             cc_time_t   *out_change_time)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_functions (in_ccache);
+    err = ccapi_ccache_get_change_time (in_ccache, out_change_time);
+    cci_swap_ccache_functions (in_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_compare_vector (cc_ccache_t  in_ccache,
+                                     cc_ccache_t  in_compare_to_ccache,
+                                     cc_uint32   *out_equal)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_functions (in_ccache);
+    cci_swap_ccache_functions (in_compare_to_ccache);
+    err = ccapi_ccache_compare (in_ccache, in_compare_to_ccache, out_equal);
+    cci_swap_ccache_functions (in_ccache);
+    cci_swap_ccache_functions (in_compare_to_ccache);
+    return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_credentials_release_vector (cc_credentials_t io_credentials)
+{
+    cci_swap_credentials_functions (io_credentials);
+    return ccapi_credentials_release (io_credentials);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_credentials_compare_vector (cc_credentials_t  in_credentials,
+                                          cc_credentials_t  in_compare_to_credentials,
+                                          cc_uint32        *out_equal)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_credentials_functions (in_credentials);
+    cci_swap_credentials_functions (in_compare_to_credentials);
+    err = ccapi_credentials_compare (in_credentials, in_compare_to_credentials, out_equal);
+    cci_swap_credentials_functions (in_credentials);
+    cci_swap_credentials_functions (in_compare_to_credentials);
+    return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_iterator_release_vector (cc_ccache_iterator_t io_ccache_iterator)
+{
+    cci_swap_ccache_iterator_functions (io_ccache_iterator);
+    return ccapi_ccache_iterator_release (io_ccache_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_ccache_iterator_next_vector (cc_ccache_iterator_t  in_ccache_iterator,
+                                           cc_ccache_t          *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_ccache_iterator_functions (in_ccache_iterator);
+    err = ccapi_ccache_iterator_next (in_ccache_iterator, out_ccache);
+    cci_swap_ccache_iterator_functions (in_ccache_iterator);
+    return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_credentials_iterator_release_vector (cc_credentials_iterator_t io_credentials_iterator)
+{
+    cci_swap_credentials_iterator_functions (io_credentials_iterator);
+    return ccapi_credentials_iterator_release (io_credentials_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_credentials_iterator_next_vector (cc_credentials_iterator_t  in_credentials_iterator,
+                                                cc_credentials_t          *out_credentials)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_credentials_iterator_functions (in_credentials_iterator);
+    err = ccapi_credentials_iterator_next (in_credentials_iterator, out_credentials);
+    cci_swap_credentials_iterator_functions (in_credentials_iterator);
+    return err;
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_shutdown_vector (apiCB **io_context)
+{
+    cci_swap_context_functions (*io_context);
+    return cc_shutdown (io_context);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_get_NC_info_vector (apiCB    *in_context,
+                                  infoNC ***out_info)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = cc_get_NC_info (in_context, out_info);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_get_change_time_vector (apiCB     *in_context,
+                                      cc_time_t *out_change_time)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = cc_get_change_time (in_context, out_change_time);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_open_vector (apiCB       *in_context,
+                           const char  *in_name,
+                           cc_int32     in_version,
+                           cc_uint32    in_flags,
+                           ccache_p   **out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = cc_open (in_context, in_name, in_version, in_flags, out_ccache);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_create_vector (apiCB       *in_context,
+                             const char  *in_name,
+                             const char  *in_principal,
+                             cc_int32     in_version,
+                             cc_uint32    in_flags,
+                             ccache_p   **out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = cc_create (in_context, in_name, in_principal, in_version, in_flags, out_ccache);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_close_vector (apiCB     *in_context,
+                            ccache_p **io_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions (*io_ccache);
+    err = cc_close (in_context, io_ccache);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_destroy_vector (apiCB     *in_context,
+                              ccache_p **io_ccache)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions (*io_ccache);
+    err = cc_destroy (in_context, io_ccache);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_seq_fetch_NCs_begin_vector (apiCB       *in_context,
+                                          ccache_cit **out_iterator)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = cc_seq_fetch_NCs_begin (in_context, out_iterator);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_seq_fetch_NCs_next_vector (apiCB       *in_context,
+                                         ccache_p   **out_ccache,
+                                         ccache_cit  *in_iterator) 
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_iterator_functions ((ccache_cit_ccache *)in_iterator);
+    err = cc_seq_fetch_NCs_next (in_context, out_ccache, in_iterator);
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_iterator_functions ((ccache_cit_ccache *)in_iterator);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_seq_fetch_NCs_end_vector (apiCB       *in_context,
+                                        ccache_cit **io_iterator)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_iterator_functions ((ccache_cit_ccache *) *io_iterator);
+    err = cc_seq_fetch_NCs_end (in_context, io_iterator);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_get_name_vector (apiCB     *in_context,
+                               ccache_p  *in_ccache,
+                               char     **out_name) 
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions (in_ccache);
+    err = cc_get_name (in_context, in_ccache, out_name);
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions (in_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_get_cred_version_vector (apiCB    *in_context,
+                                       ccache_p *in_ccache,
+                                       cc_int32 *out_version) 
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions (in_ccache);
+    err = cc_get_cred_version (in_context, in_ccache, out_version);
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions (in_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_set_principal_vector (apiCB    *in_context,
+                                    ccache_p *io_ccache,
+                                    cc_int32  in_version,
+                                    char     *in_principal) 
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions (io_ccache);
+    err = cc_set_principal (in_context, io_ccache, in_version, in_principal);
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions (io_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_get_principal_vector (apiCB      *in_context,
+                                    ccache_p   *in_ccache,
+                                    char      **out_principal)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions (in_ccache);
+    err = cc_get_principal (in_context, in_ccache, out_principal);
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions (in_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_store_vector (apiCB      *in_context,
+                            ccache_p   *io_ccache,
+                            cred_union  in_credentials)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions (io_ccache);
+    err = cc_store (in_context, io_ccache, in_credentials);
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions (io_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_remove_cred_vector (apiCB      *in_context,
+                                  ccache_p   *in_ccache,
+                                  cred_union  in_credentials) 
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions (in_ccache);
+    err = cc_remove_cred (in_context, in_ccache, in_credentials);
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions (in_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_seq_fetch_creds_begin_vector (apiCB           *in_context,
+                                            const ccache_p  *in_ccache,
+                                            ccache_cit     **out_iterator) 
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions ((ccache_p *)in_ccache);
+    err = cc_seq_fetch_creds_begin (in_context, in_ccache, out_iterator);
+    cci_swap_context_functions (in_context);
+    cci_swap_ccache_functions ((ccache_p *)in_ccache);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_seq_fetch_creds_next_vector (apiCB       *in_context,
+                                           cred_union **out_creds,
+                                           ccache_cit  *in_iterator) 
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    cci_swap_credentials_iterator_functions ((ccache_cit_creds *)in_iterator);
+    err = cc_seq_fetch_creds_next (in_context, out_creds, in_iterator);
+    cci_swap_context_functions (in_context);
+    cci_swap_credentials_iterator_functions ((ccache_cit_creds *)in_iterator);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_seq_fetch_creds_end_vector (apiCB       *in_context,
+                                          ccache_cit **io_iterator) 
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    cci_swap_credentials_iterator_functions ((ccache_cit_creds *) *io_iterator);
+    err = cc_seq_fetch_creds_end (in_context, io_iterator);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_free_principal_vector (apiCB  *in_context,
+                                     char  **io_principal) 
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = cc_free_principal (in_context, io_principal);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_free_name_vector (apiCB  *in_context,
+                                char  **io_name) 
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = cc_free_name (in_context, io_name);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_free_creds_vector (apiCB       *in_context,
+                                 cred_union **io_credentials)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = cc_free_creds (in_context, io_credentials);
+    cci_swap_context_functions (in_context);
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 __cc_free_NC_info_vector (apiCB    *in_context,
+                                   infoNC ***io_info)
+{
+    cc_int32 err = ccNoError;
+    cci_swap_context_functions (in_context);
+    err = cc_free_NC_info (in_context, io_info);
+    cci_swap_context_functions (in_context);
+    return err;
+}
diff --git a/src/ccapi/lib/mac/ccapi_vector.exports b/src/ccapi/lib/mac/ccapi_vector.exports
new file mode 100644 (file)
index 0000000..0f02e41
--- /dev/null
@@ -0,0 +1,59 @@
+__cc_context_release_vector
+__cc_context_get_change_time_vector
+__cc_context_get_default_ccache_name_vector
+__cc_context_open_ccache_vector
+__cc_context_open_default_ccache_vector
+__cc_context_create_ccache_vector
+__cc_context_create_default_ccache_vector
+__cc_context_create_new_ccache_vector
+__cc_context_new_ccache_iterator_vector
+__cc_context_lock_vector
+__cc_context_unlock_vector
+__cc_context_compare_vector
+__cc_ccache_release_vector
+__cc_ccache_destroy_vector
+__cc_ccache_set_default_vector
+__cc_ccache_get_credentials_version_vector
+__cc_ccache_get_name_vector
+__cc_ccache_get_principal_vector
+__cc_ccache_set_principal_vector
+__cc_ccache_store_credentials_vector
+__cc_ccache_remove_credentials_vector
+__cc_ccache_new_credentials_iterator_vector
+__cc_ccache_move_vector
+__cc_ccache_lock_vector
+__cc_ccache_unlock_vector
+__cc_ccache_get_last_default_time_vector
+__cc_ccache_get_change_time_vector
+__cc_ccache_compare_vector
+__cc_string_release_vector
+__cc_credentials_release_vector
+__cc_credentials_compare_vector
+__cc_ccache_iterator_release_vector
+__cc_ccache_iterator_next_vector
+__cc_credentials_iterator_release_vector
+__cc_credentials_iterator_next_vector
+__cc_initialize_vector
+__cc_shutdown_vector
+__cc_get_NC_info_vector
+__cc_get_change_time_vector
+__cc_open_vector
+__cc_create_vector
+__cc_close_vector
+__cc_destroy_vector
+__cc_seq_fetch_NCs_begin_vector
+__cc_seq_fetch_NCs_next_vector
+__cc_seq_fetch_NCs_end_vector
+__cc_get_name_vector
+__cc_get_cred_version_vector
+__cc_set_principal_vector
+__cc_get_principal_vector
+__cc_store_vector
+__cc_remove_cred_vector
+__cc_seq_fetch_creds_begin_vector
+__cc_seq_fetch_creds_next_vector
+__cc_seq_fetch_creds_end_vector
+__cc_free_principal_vector
+__cc_free_name_vector
+__cc_free_creds_vector
+__cc_free_NC_info_vector
diff --git a/src/ccapi/lib/mac/ccapi_vector.h b/src/ccapi/lib/mac/ccapi_vector.h
new file mode 100644 (file)
index 0000000..80840f1
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <CredentialsCache2.h>
+
+
+cc_int32 __cc_initialize_vector (cc_context_t  *out_context,
+                                 cc_int32       in_version,
+                                 cc_int32      *out_supported_version,
+                                 char const   **out_vendor);
+
+cc_int32 __cc_string_release_vector (cc_string_t in_string);
+
+cc_int32 __cc_context_release_vector (cc_context_t io_context);
+
+cc_int32 __cc_context_get_change_time_vector (cc_context_t  in_context,
+                                              cc_time_t    *out_change_time);
+
+cc_int32 __cc_context_get_default_ccache_name_vector (cc_context_t  in_context,
+                                                      cc_string_t  *out_name);
+
+cc_int32 __cc_context_open_ccache_vector (cc_context_t  in_context,
+                                          const char   *in_name,
+                                          cc_ccache_t  *out_ccache);
+
+cc_int32 __cc_context_open_default_ccache_vector (cc_context_t  in_context,
+                                                  cc_ccache_t  *out_ccache);
+
+cc_int32 __cc_context_create_ccache_vector (cc_context_t  in_context,
+                                            const char   *in_name,
+                                            cc_uint32     in_cred_vers,
+                                            const char   *in_principal, 
+                                            cc_ccache_t  *out_ccache);
+
+cc_int32 __cc_context_create_default_ccache_vector (cc_context_t  in_context,
+                                                    cc_uint32     in_cred_vers,
+                                                    const char   *in_principal, 
+                                                    cc_ccache_t  *out_ccache);
+
+cc_int32 __cc_context_create_new_ccache_vector (cc_context_t in_context,
+                                                cc_uint32    in_cred_vers,
+                                                const char  *in_principal, 
+                                                cc_ccache_t *out_ccache);
+
+cc_int32 __cc_context_new_ccache_iterator_vector (cc_context_t          in_context,
+                                                  cc_ccache_iterator_t *out_iterator);
+
+cc_int32 __cc_context_lock_vector (cc_context_t in_context,
+                                   cc_uint32    in_lock_type,
+                                   cc_uint32    in_block);
+
+cc_int32 __cc_context_unlock_vector (cc_context_t in_context);
+
+cc_int32 __cc_context_compare_vector (cc_context_t  in_context,
+                                      cc_context_t  in_compare_to_context,
+                                      cc_uint32    *out_equal);
+
+cc_int32 __cc_ccache_release_vector (cc_ccache_t io_ccache);
+
+cc_int32 __cc_ccache_destroy_vector (cc_ccache_t io_ccache);
+
+cc_int32 __cc_ccache_set_default_vector (cc_ccache_t io_ccache);
+
+cc_uint32 __cc_ccache_get_credentials_version_vector (cc_ccache_t  in_ccache,
+                                                      cc_uint32   *out_credentials_version);
+
+cc_int32 __cc_ccache_get_name_vector (cc_ccache_t  in_ccache,
+                                      cc_string_t *out_name);
+
+cc_int32 __cc_ccache_get_principal_vector (cc_ccache_t  in_ccache,
+                                           cc_uint32    in_credentials_version,
+                                           cc_string_t *out_principal);
+
+cc_int32 __cc_ccache_set_principal_vector (cc_ccache_t  io_ccache,
+                                           cc_uint32    in_credentials_version,
+                                           const char  *in_principal);
+
+cc_int32 __cc_ccache_store_credentials_vector (cc_ccache_t                 io_ccache,
+                                               const cc_credentials_union *in_credentials_union);
+
+cc_int32 __cc_ccache_remove_credentials_vector (cc_ccache_t      io_ccache,
+                                                cc_credentials_t in_credentials);
+
+cc_int32 __cc_ccache_new_credentials_iterator_vector (cc_ccache_t                in_ccache,
+                                                      cc_credentials_iterator_t *out_credentials_iterator);
+
+cc_int32 __cc_ccache_move_vector (cc_ccache_t io_source_ccache,
+                                  cc_ccache_t io_destination_ccache);
+
+cc_int32 __cc_ccache_lock_vector (cc_ccache_t io_ccache,
+                                  cc_uint32   in_lock_type,
+                                  cc_uint32   in_block);
+
+cc_int32 __cc_ccache_unlock_vector (cc_ccache_t io_ccache);
+
+cc_int32 __cc_ccache_get_last_default_time_vector (cc_ccache_t  in_ccache,
+                                                   cc_time_t   *out_last_default_time);
+
+cc_int32 __cc_ccache_get_change_time_vector (cc_ccache_t  in_ccache,
+                                             cc_time_t   *out_change_time);
+
+cc_int32 __cc_ccache_compare_vector (cc_ccache_t  in_ccache,
+                                     cc_ccache_t  in_compare_to_ccache,
+                                     cc_uint32   *out_equal);
+
+cc_int32 __cc_credentials_release_vector (cc_credentials_t io_credentials);
+
+cc_int32 __cc_credentials_compare_vector (cc_credentials_t  in_credentials,
+                                          cc_credentials_t  in_compare_to_credentials,
+                                          cc_uint32        *out_equal);
+
+cc_int32 __cc_ccache_iterator_release_vector (cc_ccache_iterator_t io_ccache_iterator);
+
+cc_int32 __cc_ccache_iterator_next_vector (cc_ccache_iterator_t  in_ccache_iterator,
+                                           cc_ccache_t          *out_ccache);
+
+cc_int32 __cc_credentials_iterator_release_vector (cc_credentials_iterator_t io_credentials_iterator);
+
+cc_int32 __cc_credentials_iterator_next_vector (cc_credentials_iterator_t  in_credentials_iterator,
+                                                cc_credentials_t          *out_credentials);
+
+cc_int32 __cc_shutdown_vector (apiCB **io_context);
+
+cc_int32 __cc_get_NC_info_vector (apiCB    *in_context,
+                                  infoNC ***out_info);
+
+cc_int32 __cc_get_change_time_vector (apiCB     *in_context,
+                                      cc_time_t *out_change_time);
+
+cc_int32 __cc_open_vector (apiCB       *in_context,
+                           const char  *in_name,
+                           cc_int32     in_version,
+                           cc_uint32    in_flags,
+                           ccache_p   **out_ccache);
+
+cc_int32 __cc_create_vector (apiCB       *in_context,
+                             const char  *in_name,
+                             const char  *in_principal,
+                             cc_int32     in_version,
+                             cc_uint32    in_flags,
+                             ccache_p   **out_ccache);
+
+cc_int32 __cc_close_vector (apiCB     *in_context,
+                            ccache_p **io_ccache);
+
+cc_int32 __cc_destroy_vector (apiCB     *in_context,
+                              ccache_p **io_ccache);
+
+cc_int32 __cc_seq_fetch_NCs_begin_vector (apiCB       *in_context,
+                                          ccache_cit **out_iterator);
+
+cc_int32 __cc_seq_fetch_NCs_next_vector (apiCB       *in_context,
+                                         ccache_p   **out_ccache,
+                                         ccache_cit  *in_iterator); 
+
+cc_int32 __cc_seq_fetch_NCs_end_vector (apiCB       *in_context,
+                                        ccache_cit **io_iterator);
+
+cc_int32 __cc_get_name_vector (apiCB     *in_context,
+                               ccache_p  *in_ccache,
+                               char     **out_name); 
+
+cc_int32 __cc_get_cred_version_vector (apiCB    *in_context,
+                                       ccache_p *in_ccache,
+                                       cc_int32 *out_version); 
+
+cc_int32 __cc_set_principal_vector (apiCB    *in_context,
+                                    ccache_p *io_ccache,
+                                    cc_int32  in_version,
+                                    char     *in_principal); 
+
+cc_int32 __cc_get_principal_vector (apiCB      *in_context,
+                                    ccache_p   *in_ccache,
+                                    char      **out_principal);
+
+cc_int32 __cc_store_vector (apiCB      *in_context,
+                            ccache_p   *io_ccache,
+                            cred_union  in_credentials);
+
+cc_int32 __cc_remove_cred_vector (apiCB      *in_context,
+                                  ccache_p   *in_ccache,
+                                  cred_union  in_credentials); 
+
+cc_int32 __cc_seq_fetch_creds_begin_vector (apiCB           *in_context,
+                                            const ccache_p  *in_ccache,
+                                            ccache_cit     **out_iterator); 
+
+cc_int32 __cc_seq_fetch_creds_next_vector (apiCB       *in_context,
+                                           cred_union **out_creds,
+                                           ccache_cit  *in_iterator); 
+
+cc_int32 __cc_seq_fetch_creds_end_vector (apiCB       *in_context,
+                                          ccache_cit **io_iterator); 
+
+cc_int32 __cc_free_principal_vector (apiCB  *in_context,
+                                     char  **io_principal); 
+
+cc_int32 __cc_free_name_vector (apiCB  *in_context,
+                                char  **io_name); 
+
+cc_int32 __cc_free_creds_vector (apiCB       *in_context,
+                                 cred_union **io_credentials);
+
+cc_int32 __cc_free_NC_info_vector (apiCB    *in_context,
+                                   infoNC ***io_info);
diff --git a/src/ccapi/server/ccs_array.c b/src/ccapi/server/ccs_array.c
new file mode 100644 (file)
index 0000000..c798c7a
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+#include "cci_array_internal.h"
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_pipe_object_release (void *io_pipe)
+{
+    return cci_check_error (ccs_pipe_release ((ccs_pipe_t) io_pipe));    
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_pipe_array_new (ccs_pipe_array_t *out_array)
+{
+    return cci_array_new (out_array, ccs_pipe_object_release);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_pipe_array_release (ccs_pipe_array_t io_array)
+{
+    return cci_array_release (io_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_uint64 ccs_pipe_array_count (ccs_pipe_array_t in_array)
+{
+    return cci_array_count (in_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline ccs_pipe_t ccs_pipe_array_object_at_index (ccs_pipe_array_t io_array,
+                                                  cc_uint64        in_position)
+{
+    return cci_array_object_at_index (io_array, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_pipe_array_insert (ccs_pipe_array_t io_array,
+                                       ccs_pipe_t       in_pipe,
+                                       cc_uint64        in_position)
+{
+    return cci_array_insert (io_array, in_pipe, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_pipe_array_remove (ccs_pipe_array_t io_array,
+                                       cc_uint64        in_position)
+{
+    return cci_array_remove (io_array, in_position);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_lock_object_release (void *io_lock)
+{
+    return cci_check_error (ccs_lock_release ((ccs_lock_t) io_lock));    
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_lock_array_new (ccs_lock_array_t *out_array)
+{
+    return cci_array_new (out_array, ccs_lock_object_release);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_lock_array_release (ccs_lock_array_t io_array)
+{
+    return cci_array_release (io_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_uint64 ccs_lock_array_count (ccs_lock_array_t in_array)
+{
+    return cci_array_count (in_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline ccs_lock_t ccs_lock_array_object_at_index (ccs_lock_array_t io_array,
+                                                  cc_uint64        in_position)
+{
+    return cci_array_object_at_index (io_array, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_lock_array_insert (ccs_lock_array_t io_array,
+                                       ccs_lock_t       in_lock,
+                                       cc_uint64        in_position)
+{
+    return cci_array_insert (io_array, in_lock, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_lock_array_remove (ccs_lock_array_t io_array,
+                                       cc_uint64        in_position)
+{
+    return cci_array_remove (io_array, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+inline cc_int32 ccs_lock_array_move (ccs_lock_array_t  io_array,
+                                     cc_uint64         in_position,
+                                     cc_uint64         in_new_position,
+                                     cc_uint64        *out_real_new_position)
+{
+    return cci_array_move (io_array, in_position, in_new_position, out_real_new_position);
+}
diff --git a/src/ccapi/server/ccs_array.h b/src/ccapi/server/ccs_array.h
new file mode 100644 (file)
index 0000000..865647c
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_ARRAY_H
+#define CCS_ARRAY_H
+
+#include "ccs_types.h"
+
+inline cc_int32 ccs_pipe_array_new (ccs_pipe_array_t *out_array);
+
+inline cc_int32 ccs_pipe_array_release (ccs_pipe_array_t io_array);
+
+inline cc_uint64 ccs_pipe_array_count (ccs_pipe_array_t in_array);
+
+inline ccs_pipe_t ccs_pipe_array_object_at_index (ccs_pipe_array_t io_array,
+                                                  cc_uint64        in_position);
+
+inline cc_int32 ccs_pipe_array_insert (ccs_pipe_array_t io_array,
+                                       ccs_pipe_t       in_pipe,
+                                       cc_uint64        in_position);
+
+inline cc_int32 ccs_pipe_array_remove (ccs_pipe_array_t io_array,
+                                       cc_uint64        in_position);
+
+#pragma mark -
+
+inline cc_int32 ccs_lock_array_new (ccs_lock_array_t *out_array);
+
+inline cc_int32 ccs_lock_array_release (ccs_lock_array_t io_array);
+
+inline cc_uint64 ccs_lock_array_count (ccs_lock_array_t in_array);
+
+inline ccs_lock_t ccs_lock_array_object_at_index (ccs_lock_array_t io_array,
+                                                  cc_uint64        in_position);
+
+inline cc_int32 ccs_lock_array_insert (ccs_lock_array_t io_array,
+                                       ccs_lock_t       in_lock,
+                                       cc_uint64        in_position);
+
+inline cc_int32 ccs_lock_array_remove (ccs_lock_array_t io_array,
+                                       cc_uint64        in_position);
+
+inline cc_int32 ccs_lock_array_move (ccs_lock_array_t  io_array,
+                                     cc_uint64         in_position,
+                                     cc_uint64         in_new_position,
+                                     cc_uint64        *out_real_new_position);
+
+#endif /* CCS_ARRAY_H */
diff --git a/src/ccapi/server/ccs_cache_collection.c b/src/ccapi/server/ccs_cache_collection.c
new file mode 100644 (file)
index 0000000..4927aaa
--- /dev/null
@@ -0,0 +1,949 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+
+struct ccs_cache_collection_d {
+    cc_time_t last_changed_time;
+    cc_uint64 next_unique_name;
+    cci_identifier_t identifier;
+    ccs_lock_state_t lock_state;
+    ccs_ccache_list_t ccaches;
+};
+
+struct ccs_cache_collection_d ccs_cache_collection_initializer = { 0, 0, NULL, NULL, NULL };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_new (ccs_cache_collection_t *out_cache_collection)
+{
+    cc_int32 err = ccNoError;
+    ccs_cache_collection_t cache_collection = NULL;
+    
+    if (!out_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        cache_collection = malloc (sizeof (*cache_collection));
+        if (cache_collection) { 
+            *cache_collection = ccs_cache_collection_initializer;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        err = ccs_server_new_identifier (&cache_collection->identifier);
+    }
+    
+    if (!err) {
+        err = ccs_lock_state_new (&cache_collection->lock_state,
+                                  ccErrInvalidContext,
+                                  ccErrContextLocked,
+                                  ccErrContextUnlocked);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_list_new (&cache_collection->ccaches);
+    }
+    
+    if (!err) {
+        err = ccs_cache_collection_changed (cache_collection);
+    }
+    
+    if (!err) {
+        *out_cache_collection = cache_collection;
+        cache_collection = NULL;
+    }
+    
+    ccs_cache_collection_release (cache_collection);
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_release (ccs_cache_collection_t io_cache_collection)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_cache_collection) { err = ccErrBadParam; }
+    
+    if (!err) {
+        cci_identifier_release (io_cache_collection->identifier);
+        ccs_lock_state_release (io_cache_collection->lock_state);
+        ccs_ccache_list_release (io_cache_collection->ccaches);
+        free (io_cache_collection);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_compare_identifier (ccs_cache_collection_t  in_cache_collection,
+                                                         cci_identifier_t        in_identifier,
+                                                         cc_uint32              *out_equal)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier      ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_equal          ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_compare (in_cache_collection->identifier, 
+                                      in_identifier, 
+                                      out_equal);
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_changed (ccs_cache_collection_t io_cache_collection)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+
+    if (!err) {
+        cc_time_t now = time (NULL);
+        
+        if (io_cache_collection->last_changed_time < now) {
+            io_cache_collection->last_changed_time = now;
+        } else {
+            io_cache_collection->last_changed_time++;
+        }
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_find_ccache_by_name (ccs_cache_collection_t  in_cache_collection,
+                                                          const char             *in_name,
+                                                          ccs_ccache_t           *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    ccs_ccache_list_iterator_t iterator = NULL;
+    
+    if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_name            ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_ccache         ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches, &iterator);
+    }
+    
+    while (!err) {
+        ccs_ccache_t ccache = NULL;
+        
+        err = ccs_ccache_list_iterator_next (iterator, &ccache);
+        
+        if (!err) {
+            cc_uint32 equal = 0;
+            
+            err = ccs_ccache_compare_name (ccache, in_name, &equal);
+            
+            if (!err && equal) {
+                *out_ccache = ccache;
+                break;
+            }
+        }
+    }
+    if (err == ccIteratorEnd) { err = ccErrCCacheNotFound; }
+    
+    if (iterator) { ccs_ccache_list_iterator_release (iterator); }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_find_ccache (ccs_cache_collection_t  in_cache_collection,
+                                           cci_identifier_t        in_identifier,
+                                           ccs_ccache_t           *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier      ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_ccache         ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_ccache_list_find (in_cache_collection->ccaches,
+                                    in_identifier, out_ccache);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_collection_move_ccache (ccs_cache_collection_t io_cache_collection,
+                                            cci_identifier_t       in_source_identifier,
+                                            ccs_ccache_t           io_destination_ccache)
+{
+    cc_int32 err = ccNoError;
+    ccs_ccache_t source_ccache = NULL;
+    
+    if (!io_cache_collection  ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_source_identifier ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_cache_collection_find_ccache (io_cache_collection,
+                                                in_source_identifier, 
+                                                &source_ccache);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_swap_contents (source_ccache, io_destination_ccache);
+    }
+    
+    if (!err) {
+        err = ccs_cache_collection_destroy_ccache (io_cache_collection,
+                                                   in_source_identifier);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_destroy_ccache (ccs_cache_collection_t  io_cache_collection,
+                                              cci_identifier_t        in_identifier)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_ccache_list_remove (io_cache_collection->ccaches,
+                                      in_identifier);
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_find_ccache_iterator (ccs_cache_collection_t  in_cache_collection,
+                                                    cci_identifier_t        in_identifier,
+                                                    ccs_ccache_iterator_t  *out_ccache_iterator)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier      ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_ccache_iterator) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_ccache_list_find_iterator (in_cache_collection->ccaches,
+                                             in_identifier,
+                                             out_ccache_iterator);
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_find_credentials_iterator (ccs_cache_collection_t      in_cache_collection,
+                                                         cci_identifier_t            in_identifier,
+                                                         ccs_ccache_t               *out_ccache,
+                                                         ccs_credentials_iterator_t *out_credentials_iterator)
+{
+    cc_int32 err = ccNoError;
+    ccs_ccache_list_iterator_t iterator = NULL;
+    
+    if (!in_cache_collection     ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier           ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches, &iterator);
+    }
+    
+    while (!err) {
+        ccs_ccache_t ccache = NULL;
+        
+        err = ccs_ccache_list_iterator_next (iterator, &ccache);
+        
+        if (!err) {
+            cc_int32 terr = ccs_ccache_find_credentials_iterator (ccache, 
+                                                                  in_identifier,
+                                                                  out_credentials_iterator);
+            if (!terr) { 
+                *out_ccache = ccache;
+                break; 
+            }
+        }
+    }
+    if (err == ccIteratorEnd) { err = cci_check_error (ccErrInvalidCredentialsIterator); }
+    
+    if (iterator) { ccs_ccache_list_iterator_release (iterator); }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_get_next_unique_ccache_name (ccs_cache_collection_t   io_cache_collection,
+                                                                  char                   **out_name)
+{
+    cc_int32 err = ccNoError;
+    cc_uint64 count = 0;
+    char *name = NULL;
+    
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!out_name           ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_cache_collection_list_count (io_cache_collection->ccaches, &count);
+    }
+    
+    if (!err) {
+        if (count > 0) {
+            while (!err) {
+                int ret = asprintf (&name, "%lld", io_cache_collection->next_unique_name++);
+                if (ret < 0 || !name) { err = cci_check_error (ccErrNoMem); }
+                
+                if (!err) {
+                    ccs_ccache_t ccache = NULL;  /* temporary to hold ccache pointer */
+                    err = ccs_cache_collection_find_ccache_by_name (io_cache_collection, 
+                                                                    name, &ccache);
+                }
+                
+                if (err == ccErrCCacheNotFound) { 
+                    err = ccNoError;
+                    break;   /* found a unique one */
+                }
+            }
+        } else {
+            name = strdup (k_cci_context_initial_ccache_name);
+            if (!name) { err = cci_check_error (ccErrNoMem); }
+        }
+    }
+    
+    if (!err) {
+        *out_name = name; 
+        name = NULL;
+    }
+
+    free (name);
+
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_get_default_ccache (ccs_cache_collection_t  in_cache_collection, 
+                                                         ccs_ccache_t           *out_ccache)
+{
+    cc_int32 err = ccNoError;
+    cc_uint64 count = 0;
+    
+    if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!out_ccache         ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_ccache_list_count (in_cache_collection->ccaches, &count);
+    }
+    
+    if (!err) {
+        if (count > 0) {
+            /* First ccache is the default */
+            ccs_ccache_list_iterator_t iterator = NULL;
+            
+            err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches,
+                                                &iterator);
+            
+            if (!err) {
+                err = ccs_ccache_list_iterator_next (iterator, out_ccache);
+            }
+            
+            ccs_ccache_list_iterator_release (iterator);
+            
+        } else {
+            err = cci_check_error (ccErrCCacheNotFound);
+        }
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_set_default_ccache (ccs_cache_collection_t  io_cache_collection, 
+                                                  cci_identifier_t        in_identifier)
+{
+    cc_int32 err = ccNoError;
+    ccs_ccache_t old_default = NULL;
+    ccs_ccache_t new_default = NULL;
+    
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_cache_collection_get_default_ccache (io_cache_collection, 
+                                                       &old_default);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_list_push_front (io_cache_collection->ccaches,
+                                          in_identifier);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_notify_default_state_changed (old_default,
+                                                       io_cache_collection,
+                                                       FALSE /* no longer default */);
+    }
+    
+    if (!err) {
+        err = ccs_cache_collection_get_default_ccache (io_cache_collection, 
+                                                       &new_default);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_notify_default_state_changed (new_default,
+                                                       io_cache_collection,
+                                                       TRUE /* now default */);
+    }
+    
+    if (!err) {
+        err = ccs_cache_collection_changed (io_cache_collection);
+    }
+
+    return cci_check_error (err);
+}
+
+#pragma mark -
+#pragma mark -- IPC Messages --
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_context_release (ccs_cache_collection_t io_cache_collection,
+                                                       cci_stream_t           in_request_data,
+                                                       cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        /* Currently does nothing */
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_sync (ccs_cache_collection_t io_cache_collection,
+                                            cci_stream_t           in_request_data,
+                                            cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_write (io_cache_collection->identifier, io_reply_data);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_get_change_time (ccs_cache_collection_t io_cache_collection,
+                                                       cci_stream_t           in_request_data,
+                                                       cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write_time (io_reply_data, io_cache_collection->last_changed_time);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_get_default_ccache_name (ccs_cache_collection_t io_cache_collection,
+                                                               cci_stream_t           in_request_data,
+                                                               cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cc_uint64 count = 0;
+    
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_cache_collection_list_count (io_cache_collection->ccaches, &count);
+    }
+    
+    if (!err) {
+        if (count > 0) {
+            ccs_ccache_t ccache = NULL;
+
+            err = ccs_cache_collection_get_default_ccache (io_cache_collection, &ccache);
+            
+            if (!err) {
+                err = ccs_ccache_write_name (ccache, io_reply_data);
+            }
+        } else {
+            err = cci_stream_write_string (io_reply_data, 
+                                           k_cci_context_initial_ccache_name);
+        }
+    }
+
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_open_ccache (ccs_cache_collection_t io_cache_collection,
+                                                   cci_stream_t           in_request_data,
+                                                   cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    char *name = NULL;
+    ccs_ccache_t ccache = NULL;
+    
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_string (in_request_data, &name);
+    }
+    
+    if (!err) {
+        err = ccs_cache_collection_find_ccache_by_name (io_cache_collection,
+                                                        name, &ccache);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_write (ccache, io_reply_data);
+    }
+    
+    free (name);
+        
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_open_default_ccache (ccs_cache_collection_t io_cache_collection,
+                                                           cci_stream_t           in_request_data,
+                                                           cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    ccs_ccache_t ccache = NULL;
+    
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+         err = ccs_cache_collection_get_default_ccache (io_cache_collection, 
+                                                        &ccache);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_write (ccache, io_reply_data);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_create_ccache (ccs_cache_collection_t io_cache_collection,
+                                                    cci_stream_t           in_request_data,
+                                                    cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    char *name = NULL;
+    cc_uint32 cred_vers;
+    char *principal = NULL;
+    ccs_ccache_t ccache = NULL;
+    
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_string (in_request_data, &name);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (in_request_data, &cred_vers);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_string (in_request_data, &principal);
+    }
+    
+    if (!err) {
+        cc_int32 terr = ccs_cache_collection_find_ccache_by_name (io_cache_collection,
+                                                                  name,
+                                                                  &ccache);
+        
+        if (!terr) {
+            err = ccs_ccache_reset (ccache, cred_vers, principal);
+            
+        } else {
+            err = ccs_ccache_new (&ccache, cred_vers, name, principal, 
+                                  io_cache_collection->ccaches);
+        }
+    }
+    
+    if (!err) {
+        err = ccs_ccache_write (ccache, io_reply_data);
+    }
+    
+    if (!err) {
+        err = ccs_cache_collection_changed (io_cache_collection);
+    }
+    
+    free (name);
+    free (principal);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_create_default_ccache (ccs_cache_collection_t io_cache_collection,
+                                                            cci_stream_t           in_request_data,
+                                                            cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 cred_vers;
+    char *principal = NULL;
+    ccs_ccache_t ccache = NULL;
+    
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (in_request_data, &cred_vers);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_string (in_request_data, &principal);
+    }
+    
+    if (!err) {
+        err = ccs_cache_collection_get_default_ccache (io_cache_collection,
+                                                       &ccache);
+        
+        if (!err) {
+            err = ccs_ccache_reset (ccache, cred_vers, principal);
+
+        } else if (err == ccErrCCacheNotFound) {
+            char *name = NULL;
+            
+            err = ccs_cache_collection_get_next_unique_ccache_name (io_cache_collection, 
+                                                                    &name);
+            
+            if (!err) {
+                err = ccs_ccache_new (&ccache, cred_vers, name, principal, 
+                                      io_cache_collection->ccaches);
+            }
+            
+            free (name);
+        }
+    }
+    
+    if (!err) {
+        err = ccs_ccache_write (ccache, io_reply_data);
+    }
+    
+    if (!err) {
+        err = ccs_cache_collection_changed (io_cache_collection);
+    }
+    
+    free (principal);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_create_new_ccache (ccs_cache_collection_t io_cache_collection,
+                                                        cci_stream_t           in_request_data,
+                                                        cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 cred_vers;
+    char *principal = NULL;
+    char *name = NULL;
+    ccs_ccache_t ccache = NULL;
+    
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (in_request_data, &cred_vers);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_string (in_request_data, &principal);
+    }
+    
+    if (!err) {
+        err = ccs_cache_collection_get_next_unique_ccache_name (io_cache_collection, 
+                                                                &name);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_new (&ccache, cred_vers, name, principal, 
+                              io_cache_collection->ccaches);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_write (ccache, io_reply_data);
+    }
+    
+    if (!err) {
+        err = ccs_cache_collection_changed (io_cache_collection);
+    }
+    
+    free (name);
+    free (principal);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static  cc_int32 ccs_cache_collection_new_ccache_iterator (ccs_cache_collection_t io_cache_collection,
+                                                           cci_stream_t           in_request_data,
+                                                           cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    ccs_ccache_iterator_t ccache_iterator = NULL;
+    
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_ccache_list_new_iterator (io_cache_collection->ccaches,
+                                            &ccache_iterator);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_list_iterator_write (ccache_iterator, io_reply_data);
+    }
+        
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_lock (ccs_pipe_t              in_client_pipe,
+                                           ccs_pipe_t              in_reply_pipe,
+                                           ccs_cache_collection_t  io_cache_collection,
+                                           cci_stream_t            in_request_data,
+                                           cc_uint32              *out_will_block,
+                                           cci_stream_t            io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 lock_type;
+    cc_uint32 block;
+    
+    if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection            ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data                ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_will_block                 ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data                  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (in_request_data, &lock_type);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (in_request_data, &block);
+    }
+    
+    if (!err) {
+        err = ccs_lock_state_add (io_cache_collection->lock_state, 
+                                  in_client_pipe, in_reply_pipe, 
+                                  lock_type, block, out_will_block);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_unlock (ccs_pipe_t             in_client_pipe,
+                                             ccs_cache_collection_t io_cache_collection,
+                                             cci_stream_t           in_request_data,
+                                             cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection            ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data                ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data                  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_lock_state_remove (io_cache_collection->lock_state, 
+                                     in_client_pipe);
+    }
+    
+    return cci_check_error (err);    
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+ cc_int32 ccs_cache_collection_handle_message (ccs_pipe_t              in_client_pipe,
+                                               ccs_pipe_t              in_reply_pipe,
+                                               ccs_cache_collection_t  io_cache_collection,
+                                               enum cci_msg_id_t       in_request_name,
+                                               cci_stream_t            in_request_data,
+                                               cc_uint32              *out_will_block,
+                                               cci_stream_t           *out_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 will_block = 0;
+    cci_stream_t reply_data = NULL;
+     
+    if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection            ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data                ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_will_block                 ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_reply_data                 ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&reply_data);
+    }
+    
+    if (!err) {
+        if (in_request_name == cci_context_release_msg_id) {
+            err = ccs_cache_collection_context_release (io_cache_collection,
+                                                        in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_context_sync_msg_id) {
+            err = ccs_cache_collection_sync (io_cache_collection,
+                                             in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_context_get_change_time_msg_id) {
+            err = ccs_cache_collection_get_change_time (io_cache_collection,
+                                                        in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_context_get_default_ccache_name_msg_id) {
+            err = ccs_cache_collection_get_default_ccache_name (io_cache_collection,
+                                                                in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_context_open_ccache_msg_id) {
+            err = ccs_cache_collection_open_ccache (io_cache_collection,
+                                                    in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_context_open_default_ccache_msg_id) {
+            err = ccs_cache_collection_open_default_ccache (io_cache_collection,
+                                                            in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_context_create_ccache_msg_id) {
+            err = ccs_cache_collection_create_ccache (io_cache_collection,
+                                                      in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_context_create_default_ccache_msg_id) {
+            err = ccs_cache_collection_create_default_ccache (io_cache_collection,
+                                                              in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_context_create_new_ccache_msg_id) {
+            err = ccs_cache_collection_create_new_ccache (io_cache_collection,
+                                                          in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_context_new_ccache_iterator_msg_id) {
+            err = ccs_cache_collection_new_ccache_iterator (io_cache_collection,
+                                                            in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_context_lock_msg_id) {
+            err = ccs_cache_collection_lock (in_client_pipe, in_reply_pipe, 
+                                             io_cache_collection,
+                                             in_request_data, 
+                                             &will_block, reply_data);
+            
+        } else if (in_request_name == cci_context_unlock_msg_id) {
+            err = ccs_cache_collection_unlock (in_client_pipe, io_cache_collection,
+                                               in_request_data, reply_data);
+           
+        } else {
+            err = ccErrBadInternalMessage;
+        }
+    }
+    
+    if (!err) {
+        *out_will_block = will_block;
+        *out_reply_data = reply_data;
+        reply_data = NULL; /* take ownership */
+    }
+    
+    cci_stream_release (reply_data);
+    
+    return cci_check_error (err);
+}
diff --git a/src/ccapi/server/ccs_cache_collection.h b/src/ccapi/server/ccs_cache_collection.h
new file mode 100644 (file)
index 0000000..4d663f9
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_CACHE_COLLECTION_H
+#define CCS_CACHE_COLLECTION_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_cache_collection_new (ccs_cache_collection_t *out_cache_collection);
+
+inline cc_int32 ccs_cache_collection_release (ccs_cache_collection_t io_cache_collection);
+
+inline cc_int32 ccs_cache_collection_compare_identifier (ccs_cache_collection_t  in_cache_collection,
+                                                         cci_identifier_t        in_identifier,
+                                                         cc_uint32              *out_equal);
+
+cc_int32 ccs_cache_collection_changed (ccs_cache_collection_t io_cache_collection);
+
+cc_int32 ccs_cache_collection_set_default_ccache (ccs_cache_collection_t  in_cache_collection, 
+                                                  cci_identifier_t        in_identifier);
+
+cc_int32 ccs_cache_collection_find_ccache (ccs_cache_collection_t  in_cache_collection,
+                                           cci_identifier_t        in_identifier,
+                                           ccs_ccache_t           *out_ccache);
+
+cc_int32 ccs_ccache_collection_move_ccache (ccs_cache_collection_t io_cache_collection,
+                                            cci_identifier_t       in_source_identifier,
+                                            ccs_ccache_t           io_destination_ccache);
+
+cc_int32 ccs_cache_collection_destroy_ccache (ccs_cache_collection_t  in_cache_collection,
+                                              cci_identifier_t        in_identifier);
+
+cc_int32 ccs_cache_collection_find_ccache_iterator (ccs_cache_collection_t  in_cache_collection,
+                                                    cci_identifier_t        in_identifier,
+                                                    ccs_ccache_iterator_t  *out_ccache_iterator);
+
+cc_int32 ccs_cache_collection_find_credentials_iterator (ccs_cache_collection_t      in_cache_collection,
+                                                         cci_identifier_t            in_identifier,
+                                                         ccs_ccache_t               *out_ccache,
+                                                         ccs_credentials_iterator_t *out_credentials_iterator);
+
+cc_int32 ccs_cache_collection_handle_message (ccs_pipe_t              in_client_pipe,
+                                              ccs_pipe_t              in_reply_pipe,
+                                              ccs_cache_collection_t  io_cache_collection,
+                                              enum cci_msg_id_t       in_request_name,
+                                              cci_stream_t            in_request_data,
+                                              cc_uint32              *out_will_block,
+                                              cci_stream_t           *out_reply_data);
+
+#endif /* CCS_CACHE_COLLECTION_H */
diff --git a/src/ccapi/server/ccs_ccache.c b/src/ccapi/server/ccs_ccache.c
new file mode 100644 (file)
index 0000000..aaeed97
--- /dev/null
@@ -0,0 +1,1002 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+
+struct ccs_ccache_d {
+    cci_identifier_t identifier;
+    ccs_lock_state_t lock_state;
+    cc_uint32 cred_vers;
+    char *name;
+    char *principal;
+    cc_time_t last_default_time;
+    cc_time_t last_changed_time;
+    cc_uint32 kdc_time_offset_v4_valid;
+    cc_time_t kdc_time_offset_v4;
+    cc_uint32 kdc_time_offset_v5_valid;
+    cc_time_t kdc_time_offset_v5;
+    ccs_credentials_list_t credentials;
+};
+
+struct ccs_ccache_d ccs_ccache_initializer = { NULL, NULL, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, NULL };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_new (ccs_ccache_t      *out_ccache,
+                         cc_uint32          in_cred_vers,
+                         const char        *in_name,
+                         const char        *in_principal,
+                         ccs_ccache_list_t  io_ccache_list)
+{
+    cc_int32 err = ccNoError;
+    ccs_ccache_t ccache = NULL;
+    
+    if (!out_ccache  ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_name     ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_principal) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        ccache = malloc (sizeof (*ccache));
+        if (ccache) { 
+            *ccache = ccs_ccache_initializer;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        err = ccs_server_new_identifier (&ccache->identifier);
+    }
+    
+    if (!err) {
+        err = ccs_lock_state_new (&ccache->lock_state,
+                                  ccErrInvalidCCache,
+                                  ccErrCCacheLocked,
+                                  ccErrCCacheUnlocked);
+    }
+    
+    if (!err) {
+        ccache->cred_vers = in_cred_vers;
+
+        if (in_cred_vers != cc_credentials_v4 &&
+            in_cred_vers != cc_credentials_v5) {
+            err = cci_check_error (ccErrBadCredentialsVersion);
+        }      
+    }
+    
+    if (!err) {
+        ccache->name = strdup (in_name);
+        if (!ccache->name) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        ccache->principal = strdup (in_principal);
+        if (!ccache->principal) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        err = ccs_credentials_list_new (&ccache->credentials);
+    }
+    
+    if (!err) {
+        cc_uint64 now = time (NULL);
+        cc_uint64 count = 0;
+        
+        err = ccs_ccache_list_count (io_ccache_list, &count);
+        
+        if (!err) {
+            /* first cache is default */
+            ccache->last_default_time = (count == 0) ? now : 0;
+            ccache->last_changed_time = now;
+        }
+    }
+        
+    if (!err) {
+        /* Add self to the list of ccaches */
+        err = ccs_ccache_list_add (io_ccache_list, ccache);
+    }
+    
+    if (!err) {
+        *out_ccache = ccache;
+        ccache = NULL;
+    }
+    
+    ccs_ccache_release (ccache);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_reset (ccs_ccache_t  io_ccache,
+                           cc_uint32     in_cred_vers,
+                           const char   *in_principal)
+{
+    cc_int32 err = ccNoError;
+    char *principal = NULL;
+    ccs_credentials_list_t credentials = NULL;
+    
+    if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        if (in_cred_vers != cc_credentials_v4 &&
+            in_cred_vers != cc_credentials_v5) {
+            err = cci_check_error (ccErrBadCredentialsVersion);
+        }
+    }
+    
+    if (!err) {
+        principal = strdup (in_principal);
+        if (!io_ccache->principal) { err = cci_check_error (ccErrNoMem); }
+    }
+    
+    if (!err) {
+        err = ccs_credentials_list_new (&credentials);
+    }
+    
+    if (!err) {
+        io_ccache->cred_vers = in_cred_vers;
+
+        free (io_ccache->principal);
+        io_ccache->principal = principal;
+        principal = NULL; /* take ownership */
+        
+        ccs_credentials_list_release (io_ccache->credentials);
+        io_ccache->credentials = credentials;
+        credentials = NULL; /* take ownership */
+        
+    }
+    
+    free (principal);
+    ccs_credentials_list_release (credentials);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_swap_contents (ccs_ccache_t io_source_ccache, 
+                                   ccs_ccache_t io_destination_ccache)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_source_ccache     ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        struct ccs_ccache_d temp_ccache = *io_destination_ccache;
+        
+        /* swap everything */
+        *io_destination_ccache = *io_source_ccache;
+        *io_source_ccache = temp_ccache;
+        
+        /* swap back the name and identifier */
+        io_source_ccache->identifier = io_destination_ccache->identifier;
+        io_destination_ccache->identifier = temp_ccache.identifier;
+        
+        io_source_ccache->name = io_destination_ccache->name;
+        io_destination_ccache->name = temp_ccache.name;
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_release (ccs_ccache_t io_ccache)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccache) { err = ccErrBadParam; }
+    
+    if (!err) {
+        cci_identifier_release (io_ccache->identifier);
+        ccs_lock_state_release (io_ccache->lock_state);
+        free (io_ccache->name);
+        free (io_ccache->principal);
+        ccs_credentials_list_release (io_ccache->credentials);
+        free (io_ccache);
+    }
+    
+    return cci_check_error (err);    
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_compare_identifier (ccs_ccache_t      in_ccache,
+                                               cci_identifier_t  in_identifier,
+                                               cc_uint32        *out_equal)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_ccache    ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!out_equal    ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_compare (in_ccache->identifier, 
+                                      in_identifier, 
+                                      out_equal);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_compare_name (ccs_ccache_t  in_ccache,
+                                  const char   *in_name,
+                                  cc_uint32    *out_equal)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+    if (!in_name  ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_equal) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_equal = (strcmp (in_ccache->name, in_name) == 0);
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_changed (ccs_ccache_t           io_ccache,
+                                    ccs_cache_collection_t io_cache_collection)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        cc_time_t now = time (NULL);
+        
+        if (io_ccache->last_changed_time < now) {
+            io_ccache->last_changed_time = now;
+        } else {
+            io_ccache->last_changed_time++;
+        }
+    }
+    
+    if (!err) {
+        err = ccs_cache_collection_changed (io_cache_collection);
+    }
+    
+    return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_notify_default_state_changed (ccs_ccache_t           io_ccache,
+                                                  ccs_cache_collection_t io_cache_collection,
+                                                  cc_uint32              in_new_default_state)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err && in_new_default_state) {
+        cc_time_t now = time (NULL);
+        
+        if (io_ccache->last_default_time < now) {
+            io_ccache->last_default_time = now;
+        } else {
+            io_ccache->last_default_time++;
+        }
+    }
+    
+    if (!err) {
+        err = ccs_ccache_changed (io_ccache, io_cache_collection);
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_find_credentials_iterator (ccs_ccache_t                in_ccache,
+                                               cci_identifier_t            in_identifier,
+                                               ccs_credentials_iterator_t *out_credentials_iterator)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_ccache               ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier           ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_credentials_list_find_iterator (in_ccache->credentials,
+                                                  in_identifier,
+                                                  out_credentials_iterator);
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_write (ccs_ccache_t in_ccache,
+                           cci_stream_t io_stream)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_write (in_ccache->identifier, io_stream);
+    }
+    
+    return cci_check_error (err);    
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_write_name (ccs_ccache_t in_ccache,
+                                cci_stream_t io_stream)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+    if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write_string (io_stream, in_ccache->name);
+    }
+    
+    return cci_check_error (err);    
+}
+
+#pragma mark -
+#pragma mark -- IPC Messages --
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_destroy (ccs_ccache_t           io_ccache,
+                                    ccs_cache_collection_t io_cache_collection,
+                                    cci_stream_t           in_request_data,
+                                    cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_cache_collection_destroy_ccache (io_cache_collection, 
+                                                   io_ccache->identifier);
+    }
+    
+    if (!err) {
+        /* ccache has been destroyed so just mark the cache collection */
+        err = ccs_cache_collection_changed (io_cache_collection);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_set_default (ccs_ccache_t           io_ccache,
+                                        ccs_cache_collection_t io_cache_collection,
+                                        cci_stream_t           in_request_data,
+                                        cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_cache_collection_set_default_ccache (io_cache_collection, 
+                                                       io_ccache->identifier);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_credentials_version (ccs_ccache_t           io_ccache,
+                                                    ccs_cache_collection_t io_cache_collection,
+                                                    cci_stream_t           in_request_data,
+                                                    cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write_uint32 (io_reply_data, io_ccache->cred_vers);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_name (ccs_ccache_t           io_ccache,
+                                     ccs_cache_collection_t io_cache_collection,
+                                     cci_stream_t           in_request_data,
+                                     cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write_string (io_reply_data, io_ccache->name);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_principal (ccs_ccache_t           io_ccache,
+                                          ccs_cache_collection_t io_cache_collection,
+                                          cci_stream_t           in_request_data,
+                                          cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write_string (io_reply_data, io_ccache->principal);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_set_principal (ccs_ccache_t           io_ccache,
+                                          ccs_cache_collection_t io_cache_collection,
+                                          cci_stream_t           in_request_data,
+                                          cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    char *principal = NULL;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_string (io_reply_data, &principal);
+    }
+    
+    if (!err) {
+        free (io_ccache->principal);
+        io_ccache->principal = principal;
+        principal = NULL;
+
+        err = ccs_ccache_changed (io_ccache, io_cache_collection);
+    }
+        
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_store_credentials (ccs_ccache_t           io_ccache,
+                                              ccs_cache_collection_t io_cache_collection,
+                                              cci_stream_t           in_request_data,
+                                              cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    ccs_credentials_t credentials = NULL;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_credentials_new (&credentials, in_request_data, 
+                                   io_ccache->credentials);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_changed (io_ccache, io_cache_collection);
+    }
+    
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_remove_credentials (ccs_ccache_t           io_ccache,
+                                               ccs_cache_collection_t io_cache_collection,
+                                               cci_stream_t           in_request_data,
+                                               cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cci_identifier_t credentials_identifier = NULL;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_read (&credentials_identifier, in_request_data);
+    }
+    
+    if (!err) {
+        err = ccs_credentials_list_remove (io_ccache->credentials, credentials_identifier);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_changed (io_ccache, io_cache_collection);
+    }
+    
+    cci_identifier_release (credentials_identifier);
+        
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_new_credentials_iterator (ccs_ccache_t           io_ccache,
+                                                     ccs_cache_collection_t io_cache_collection,
+                                                     cci_stream_t           in_request_data,
+                                                     cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    ccs_credentials_iterator_t credentials_iterator = NULL;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_credentials_list_new_iterator (io_ccache->credentials,
+                                                 &credentials_iterator);
+    }
+    
+    if (!err) {
+        err = ccs_credentials_list_iterator_write (credentials_iterator, io_reply_data);
+    }
+        
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_move (ccs_ccache_t           io_ccache,
+                                 ccs_cache_collection_t io_cache_collection,
+                                 cci_stream_t           in_request_data,
+                                 cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cci_identifier_t source_identifier = NULL;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        /* Note: message is sent as the destination ccache to avoid     */
+        /* extra work on the server when deleting it the source ccache. */
+        err = cci_identifier_read (&source_identifier, in_request_data);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_collection_move_ccache (io_cache_collection,
+                                                 source_identifier, 
+                                                 io_ccache);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_changed (io_ccache, io_cache_collection);
+    }
+    
+    cci_identifier_release (source_identifier);
+        
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_lock (ccs_pipe_t             in_client_pipe,
+                                 ccs_pipe_t             in_reply_pipe,
+                                 ccs_ccache_t           io_ccache,
+                                 ccs_cache_collection_t io_cache_collection,
+                                 cci_stream_t           in_request_data,
+                                 cc_uint32              *out_will_block,
+                                 cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 lock_type;
+    cc_uint32 block;
+    
+    if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!io_ccache                      ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection            ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data                ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_will_block                 ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data                  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (in_request_data, &lock_type);
+    }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (in_request_data, &block);
+    }
+    
+    if (!err) {
+        err = ccs_lock_state_add (io_ccache->lock_state, 
+                                  in_client_pipe, in_reply_pipe, 
+                                  lock_type, block, out_will_block);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_unlock (ccs_pipe_t             in_client_pipe,
+                                   ccs_ccache_t           io_ccache,
+                                   ccs_cache_collection_t io_cache_collection,
+                                   cci_stream_t           in_request_data,
+                                   cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!io_ccache                      ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection            ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data                ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data                  ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_lock_state_remove (io_ccache->lock_state, in_client_pipe);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_last_default_time (ccs_ccache_t           io_ccache,
+                                                  ccs_cache_collection_t io_cache_collection,
+                                                  cci_stream_t           in_request_data,
+                                                  cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err && io_ccache->last_default_time == 0) {
+        err = cci_check_error (ccErrNeverDefault);
+    }
+    
+    if (!err) {
+        err = cci_stream_write_time (io_reply_data, io_ccache->last_default_time);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_change_time (ccs_ccache_t           io_ccache,
+                                            ccs_cache_collection_t io_cache_collection,
+                                            cci_stream_t           in_request_data,
+                                            cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_write_time (io_reply_data, io_ccache->last_changed_time);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_kdc_time_offset (ccs_ccache_t           io_ccache,
+                                                ccs_cache_collection_t io_cache_collection,
+                                                cci_stream_t           in_request_data,
+                                                cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 cred_vers = 0;
+        
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (in_request_data, &cred_vers);
+    }
+    
+    if (!err) {
+        if (cred_vers == cc_credentials_v4) {
+            if (io_ccache->kdc_time_offset_v4_valid) {
+                err = cci_stream_write_time (io_reply_data, io_ccache->kdc_time_offset_v4);
+            } else {
+                err = cci_check_error (ccErrTimeOffsetNotSet);
+            }
+            
+        } else if (cred_vers == cc_credentials_v5) {
+            if (io_ccache->kdc_time_offset_v5_valid) {
+                err = cci_stream_write_time (io_reply_data, io_ccache->kdc_time_offset_v5);
+            } else {
+                err = cci_check_error (ccErrTimeOffsetNotSet);
+            }
+            
+        } else {
+            err = cci_check_error (ccErrBadCredentialsVersion);
+        }
+    }
+        
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_set_kdc_time_offset (ccs_ccache_t           io_ccache,
+                                                ccs_cache_collection_t io_cache_collection,
+                                                cci_stream_t           in_request_data,
+                                                cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 cred_vers = 0;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (in_request_data, &cred_vers);
+    }
+    
+    if (!err) {
+        if (cred_vers == cc_credentials_v4) {
+            err = cci_stream_read_time (in_request_data, &io_ccache->kdc_time_offset_v4);
+            
+            if (!err) {
+                io_ccache->kdc_time_offset_v4_valid = 1;
+            }
+        } else if (cred_vers == cc_credentials_v5) {
+            err = cci_stream_read_time (in_request_data, &io_ccache->kdc_time_offset_v5);
+            
+            if (!err) {
+                io_ccache->kdc_time_offset_v5_valid = 1;
+            }
+        } else {
+            err = cci_check_error (ccErrBadCredentialsVersion);
+        }
+    }
+    
+    if (!err) {
+        err = ccs_ccache_changed (io_ccache, io_cache_collection);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_clear_kdc_time_offset (ccs_ccache_t           io_ccache,
+                                                  ccs_cache_collection_t io_cache_collection,
+                                                  cci_stream_t           in_request_data,
+                                                  cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 cred_vers = 0;
+    
+    if (!io_ccache          ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_read_uint32 (in_request_data, &cred_vers);
+    }
+    
+    if (!err) {
+        if (cred_vers == cc_credentials_v4) {
+            io_ccache->kdc_time_offset_v4 = 0;
+            io_ccache->kdc_time_offset_v4_valid = 0;
+            
+        } else if (cred_vers == cc_credentials_v5) {
+            io_ccache->kdc_time_offset_v5 = 0;
+            io_ccache->kdc_time_offset_v5_valid = 0;
+            
+        } else {
+            err = cci_check_error (ccErrBadCredentialsVersion);
+        }
+    }
+        
+    if (!err) {
+        err = ccs_ccache_changed (io_ccache, io_cache_collection);
+    }
+    
+    return cci_check_error (err);    
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_handle_message (ccs_pipe_t              in_client_pipe,
+                                    ccs_pipe_t              in_reply_pipe,
+                                    ccs_ccache_t            io_ccache,
+                                    ccs_cache_collection_t  io_cache_collection,
+                                    enum cci_msg_id_t       in_request_name,
+                                    cci_stream_t            in_request_data,
+                                    cc_uint32              *out_will_block,
+                                    cci_stream_t           *out_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 will_block = 0;
+    cci_stream_t reply_data = NULL;
+    
+    if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection            ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data                ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_will_block                 ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_reply_data                 ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&reply_data);
+    }
+    
+    if (!err) {
+        if (in_request_name == cci_ccache_destroy_msg_id) {
+            err = ccs_ccache_destroy (io_ccache, io_cache_collection,
+                                      in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_ccache_set_default_msg_id) {
+            err = ccs_ccache_set_default (io_ccache, io_cache_collection,
+                                          in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_ccache_get_credentials_version_msg_id) {
+            err = ccs_ccache_get_credentials_version (io_ccache, io_cache_collection,
+                                                      in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_ccache_get_name_msg_id) {
+            err = ccs_ccache_get_name (io_ccache, io_cache_collection,
+                                       in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_ccache_get_principal_msg_id) {
+            err = ccs_ccache_get_principal (io_ccache, io_cache_collection,
+                                            in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_ccache_set_principal_msg_id) {
+            err = ccs_ccache_set_principal (io_ccache, io_cache_collection,
+                                            in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_ccache_store_credentials_msg_id) {
+            err = ccs_ccache_store_credentials (io_ccache, io_cache_collection,
+                                                in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_ccache_remove_credentials_msg_id) {
+            err = ccs_ccache_remove_credentials (io_ccache, io_cache_collection,
+                                                 in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_ccache_new_credentials_iterator_msg_id) {
+            err = ccs_ccache_new_credentials_iterator (io_ccache, io_cache_collection,
+                                                       in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_ccache_move_msg_id) {
+            err = ccs_ccache_move (io_ccache, io_cache_collection,
+                                   in_request_data, reply_data);
+                                       
+        } else if (in_request_name == cci_ccache_lock_msg_id) {
+            err = ccs_ccache_lock (in_client_pipe, in_reply_pipe, 
+                                   io_ccache, io_cache_collection,
+                                   in_request_data, 
+                                   &will_block, reply_data);
+            
+        } else if (in_request_name == cci_ccache_unlock_msg_id) {
+            err = ccs_ccache_unlock (in_client_pipe, 
+                                     io_ccache, io_cache_collection,
+                                     in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_ccache_get_last_default_time_msg_id) {
+            err = ccs_ccache_get_last_default_time (io_ccache, io_cache_collection,
+                                                    in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_ccache_get_change_time_msg_id) {
+            err = ccs_ccache_get_change_time (io_ccache, io_cache_collection,
+                                              in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_ccache_get_kdc_time_offset_msg_id) {
+            err = ccs_ccache_get_kdc_time_offset (io_ccache, io_cache_collection,
+                                                  in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_ccache_set_kdc_time_offset_msg_id) {
+            err = ccs_ccache_set_kdc_time_offset (io_ccache, io_cache_collection,
+                                                  in_request_data, reply_data);
+            
+        } else if (in_request_name == cci_ccache_clear_kdc_time_offset_msg_id) {
+            err = ccs_ccache_clear_kdc_time_offset (io_ccache, io_cache_collection,
+                                                    in_request_data, reply_data);
+            
+        } else {
+            err = ccErrBadInternalMessage;
+        }
+    }
+    
+    if (!err) {
+        *out_will_block = will_block;
+        *out_reply_data = reply_data;
+        reply_data = NULL; /* take ownership */
+    }
+    
+    cci_stream_release (reply_data);
+    
+    return cci_check_error (err);
+}
+
diff --git a/src/ccapi/server/ccs_ccache.h b/src/ccapi/server/ccs_ccache.h
new file mode 100644 (file)
index 0000000..837c6b4
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_CCACHE_H
+#define CCS_CCACHE_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_ccache_new (ccs_ccache_t      *out_ccache,
+                         cc_uint32          in_cred_vers,
+                         const char        *in_name,
+                         const char        *in_principal,
+                         ccs_ccache_list_t  io_ccache_list);
+
+cc_int32 ccs_ccache_reset (ccs_ccache_t  io_ccache,
+                           cc_uint32     in_cred_vers,
+                           const char   *in_principal);
+
+cc_int32 ccs_ccache_swap_contents (ccs_ccache_t io_source_ccache, 
+                                   ccs_ccache_t io_destination_ccache);
+
+inline cc_int32 ccs_ccache_release (ccs_ccache_t io_ccache);
+
+inline cc_int32 ccs_ccache_compare_identifier (ccs_ccache_t      in_ccache,
+                                        cci_identifier_t  in_identifier,
+                                        cc_uint32        *out_equal);
+
+cc_int32 ccs_ccache_compare_name (ccs_ccache_t  in_ccache,
+                                  const char   *in_name,
+                                  cc_uint32    *out_equal);
+
+cc_int32 ccs_ccache_notify_default_state_changed (ccs_ccache_t           io_ccache,
+                                                  ccs_cache_collection_t io_cache_collection,
+                                                  cc_uint32              in_new_default_state);
+
+cc_int32 ccs_ccache_find_credentials_iterator (ccs_ccache_t                in_ccache,
+                                               cci_identifier_t            in_identifier,
+                                               ccs_credentials_iterator_t *out_credentials_iterator);
+
+cc_int32 ccs_ccache_write (ccs_ccache_t in_ccache,
+                           cci_stream_t io_stream);
+
+cc_int32 ccs_ccache_write_name (ccs_ccache_t in_ccache,
+                                cci_stream_t io_stream);
+
+cc_int32 ccs_ccache_handle_message (ccs_pipe_t              in_client_pipe,
+                                    ccs_pipe_t              in_reply_pipe,
+                                    ccs_ccache_t            io_ccache,
+                                    ccs_cache_collection_t  io_cache_collection,
+                                    enum cci_msg_id_t       in_request_name,
+                                    cci_stream_t            in_request_data,
+                                    cc_uint32              *out_will_block,
+                                    cci_stream_t           *out_reply_data);
+
+#endif /* CCS_CCACHE_H */
diff --git a/src/ccapi/server/ccs_ccache_iterator.c b/src/ccapi/server/ccs_ccache_iterator.c
new file mode 100644 (file)
index 0000000..77d83f1
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+
+/* ------------------------------------------------------------------------ */
+
+static  cc_int32 ccs_ccache_iterator_release (ccs_ccache_iterator_t  io_ccache_iterator,
+                                              ccs_cache_collection_t io_cache_collection,
+                                              cci_stream_t           in_request_data,
+                                              cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_ccache_iterator ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_ccache_list_iterator_release (io_ccache_iterator);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static  cc_int32 ccs_ccache_iterator_next (ccs_ccache_iterator_t  io_ccache_iterator,
+                                           ccs_cache_collection_t io_cache_collection,
+                                           cci_stream_t           in_request_data,
+                                           cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    ccs_ccache_t ccache = NULL;
+    
+    if (!io_ccache_iterator ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_ccache_list_iterator_next (io_ccache_iterator, &ccache);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_write (ccache, io_reply_data);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static  cc_int32 ccs_ccache_iterator_clone (ccs_ccache_iterator_t  io_ccache_iterator,
+                                            ccs_cache_collection_t io_cache_collection,
+                                            cci_stream_t           in_request_data,
+                                            cci_stream_t           io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    ccs_ccache_iterator_t ccache_iterator = NULL;
+    
+    if (!io_ccache_iterator ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data    ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_ccache_list_iterator_clone (io_ccache_iterator,
+                                              &ccache_iterator);
+    }
+    
+    if (!err) {
+        err = ccs_ccache_list_iterator_write (ccache_iterator, io_reply_data);
+    }
+        
+    return cci_check_error (err);    
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+ cc_int32 ccs_ccache_iterator_handle_message (ccs_ccache_iterator_t  io_ccache_iterator,
+                                              ccs_cache_collection_t io_cache_collection,
+                                              enum cci_msg_id_t      in_request_name,
+                                              cci_stream_t           in_request_data,
+                                              cci_stream_t          *out_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cci_stream_t reply_data = NULL;
+    
+    if (!in_request_data) { err = cci_check_error (ccErrBadParam); }
+    if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&reply_data);
+    }
+    
+    if (!err) {
+        if (in_request_name == cci_ccache_iterator_release_msg_id) {
+            err = ccs_ccache_iterator_release (io_ccache_iterator,
+                                               io_cache_collection,
+                                               in_request_data, 
+                                               reply_data);
+            
+        } else if (in_request_name == cci_ccache_iterator_next_msg_id) {
+            err = ccs_ccache_iterator_next (io_ccache_iterator,
+                                            io_cache_collection,
+                                            in_request_data, 
+                                            reply_data);
+            
+        } else if (in_request_name == cci_ccache_iterator_clone_msg_id) {
+            err = ccs_ccache_iterator_clone (io_ccache_iterator,
+                                             io_cache_collection,
+                                             in_request_data, 
+                                             reply_data);
+            
+        } else {
+            err = ccErrBadInternalMessage;
+        }
+    }
+    
+    if (!err) {
+        *out_reply_data = reply_data;
+        reply_data = NULL; /* take ownership */
+    }
+    
+    cci_stream_release (reply_data);
+    
+    return cci_check_error (err);
+}
+
diff --git a/src/ccapi/server/ccs_ccache_iterator.h b/src/ccapi/server/ccs_ccache_iterator.h
new file mode 100644 (file)
index 0000000..8ec361a
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_CCACHE_ITERATOR_H
+#define CCS_CCACHE_ITERATOR_H
+
+#include "ccs_types.h"
+
+ cc_int32 ccs_ccache_iterator_handle_message (ccs_ccache_iterator_t  io_ccache_iterator,
+                                              ccs_cache_collection_t io_cache_collection,
+                                              enum cci_msg_id_t      in_request_name,
+                                              cci_stream_t           in_request_data,
+                                              cci_stream_t          *out_reply_data);
+
+#endif /* CCS_CCACHE_ITERATOR_H */
diff --git a/src/ccapi/server/ccs_common.h b/src/ccapi/server/ccs_common.h
new file mode 100644 (file)
index 0000000..f035780
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_COMMON_H
+#define CCS_COMMON_H
+
+#include "cci_common.h"
+
+#include "ccs_array.h"
+#include "ccs_list.h"
+#include "ccs_cache_collection.h"
+#include "ccs_ccache_iterator.h"
+#include "ccs_ccache.h"
+#include "ccs_credentials_iterator.h"
+#include "ccs_credentials.h"
+#include "ccs_lock.h"
+#include "ccs_lock_state.h"
+#include "ccs_pipe.h"
+#include "ccs_server.h"
+
+#endif /* CCS_COMMON_H */
diff --git a/src/ccapi/server/ccs_credentials.c b/src/ccapi/server/ccs_credentials.c
new file mode 100644 (file)
index 0000000..7cb6483
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+
+struct ccs_credentials_d {
+    cc_credentials_union *cred_union;
+    cci_identifier_t identifier;
+};
+
+struct ccs_credentials_d ccs_credentials_initializer = { NULL, NULL };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_credentials_new (ccs_credentials_t      *out_credentials,
+                              cci_stream_t            in_stream,
+                              ccs_credentials_list_t  io_credentials_list)
+{
+    cc_int32 err = ccNoError;
+    ccs_credentials_t credentials = NULL;
+    
+    if (!out_credentials) { err = cci_check_error (ccErrBadParam); }
+    if (!in_stream      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        credentials = malloc (sizeof (*credentials));
+        if (credentials) { 
+            *credentials = ccs_credentials_initializer;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        err = cci_cred_union_read (&credentials->cred_union, in_stream);
+    }
+    
+    if (!err) {
+        err = ccs_server_new_identifier (&credentials->identifier);
+    }
+    
+    if (!err) {
+        err = ccs_credentials_list_add (io_credentials_list, credentials);
+    }
+    
+    if (!err) {
+        *out_credentials = credentials;
+        credentials = NULL;
+    }
+    
+    ccs_credentials_release (credentials);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_release (ccs_credentials_t io_credentials)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_credentials) { err = ccErrBadParam; }
+    
+    if (!err) {
+        cci_cred_union_release (io_credentials->cred_union);
+        cci_identifier_release (io_credentials->identifier);
+        free (io_credentials);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_credentials_write (ccs_credentials_t in_credentials,
+                                cci_stream_t      io_stream)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_credentials) { err = cci_check_error (ccErrBadParam); }
+    if (!io_stream     ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_write (in_credentials->identifier, io_stream);
+    }
+    
+    if (!err) {
+        err = cci_cred_union_write (in_credentials->cred_union, io_stream);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_compare_identifier (ccs_credentials_t  in_credentials,
+                                                    cci_identifier_t   in_identifier,
+                                                    cc_uint32         *out_equal)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_credentials) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_equal     ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_compare (in_credentials->identifier, 
+                                      in_identifier, 
+                                      out_equal);
+    }
+    
+    return cci_check_error (err);
+}
diff --git a/src/ccapi/server/ccs_credentials.h b/src/ccapi/server/ccs_credentials.h
new file mode 100644 (file)
index 0000000..e4dbb69
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_CREDENTIALS_H
+#define CCS_CREDENTIALS_H
+
+#include "ccs_types.h"
+
+
+cc_int32 ccs_credentials_new (ccs_credentials_t      *out_credentials,
+                              cci_stream_t            in_stream,
+                              ccs_credentials_list_t  io_credentials_list);
+
+inline cc_int32 ccs_credentials_release (ccs_credentials_t io_credentials);
+
+cc_int32 ccs_credentials_write (ccs_credentials_t in_credentials,
+                                cci_stream_t      io_stream);
+
+inline cc_int32 ccs_credentials_compare_identifier (ccs_credentials_t  in_credentials,
+                                                    cci_identifier_t   in_identifier,
+                                                    cc_uint32         *out_equal);
+
+#endif /* CCS_CREDENTIALS_H */
diff --git a/src/ccapi/server/ccs_credentials_iterator.c b/src/ccapi/server/ccs_credentials_iterator.c
new file mode 100644 (file)
index 0000000..f95dc48
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+
+/* ------------------------------------------------------------------------ */
+
+static  cc_int32 ccs_credentials_iterator_release (ccs_credentials_iterator_t io_credentials_iterator,
+                                                   ccs_ccache_t               io_ccache,
+                                                   cci_stream_t               in_request_data,
+                                                   cci_stream_t               io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+    if (!io_ccache              ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data        ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data          ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_credentials_list_iterator_release (io_credentials_iterator);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static  cc_int32 ccs_credentials_iterator_next (ccs_credentials_iterator_t io_credentials_iterator,
+                                                ccs_ccache_t               io_ccache,
+                                                cci_stream_t               in_request_data,
+                                                cci_stream_t               io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    ccs_credentials_t credentials = NULL;
+    
+    if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+    if (!io_ccache              ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data        ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data          ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_credentials_list_iterator_next (io_credentials_iterator,
+                                                  &credentials);
+    }
+    
+    if (!err) {
+        err = ccs_credentials_write (credentials, io_reply_data);
+    }
+        
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static  cc_int32 ccs_credentials_iterator_clone (ccs_credentials_iterator_t io_credentials_iterator,
+                                                 ccs_ccache_t               io_ccache,
+                                                 cci_stream_t               in_request_data,
+                                                 cci_stream_t               io_reply_data)
+{
+    cc_int32 err = ccNoError;
+    ccs_credentials_iterator_t credentials_iterator = NULL;
+    
+    if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+    if (!io_ccache              ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data        ) { err = cci_check_error (ccErrBadParam); }
+    if (!io_reply_data          ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_credentials_list_iterator_clone (io_credentials_iterator,
+                                                   &credentials_iterator);
+    }
+    
+    if (!err) {
+        err = ccs_credentials_list_iterator_write (credentials_iterator, 
+                                                   io_reply_data);
+    }
+        
+    return cci_check_error (err);    
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+ cc_int32 ccs_credentials_iterator_handle_message (ccs_credentials_iterator_t  io_credentials_iterator,
+                                                   ccs_ccache_t                io_ccache,
+                                                   enum cci_msg_id_t           in_request_name,
+                                                   cci_stream_t                in_request_data,
+                                                   cci_stream_t               *out_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cci_stream_t reply_data = NULL;
+    
+    if (!in_request_data) { err = cci_check_error (ccErrBadParam); }
+    if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_stream_new (&reply_data);
+    }
+    
+    if (!err) {
+        if (in_request_name == cci_credentials_iterator_release_msg_id) {
+            err = ccs_credentials_iterator_release (io_credentials_iterator,
+                                                    io_ccache,
+                                                    in_request_data,
+                                                    reply_data);
+            
+        } else if (in_request_name == cci_credentials_iterator_next_msg_id) {
+            err = ccs_credentials_iterator_next (io_credentials_iterator,
+                                                 io_ccache,
+                                                 in_request_data,
+                                                 reply_data);
+            
+        } else if (in_request_name == cci_credentials_iterator_clone_msg_id) {
+            err = ccs_credentials_iterator_clone (io_credentials_iterator,
+                                                  io_ccache,
+                                                  in_request_data,
+                                                  reply_data);
+            
+        } else {
+            err = ccErrBadInternalMessage;
+        }
+    }
+    
+    if (!err) {
+        *out_reply_data = reply_data;
+        reply_data = NULL; /* take ownership */
+    }
+    
+    cci_stream_release (reply_data);
+    
+    return cci_check_error (err);
+}
+
diff --git a/src/ccapi/server/ccs_credentials_iterator.h b/src/ccapi/server/ccs_credentials_iterator.h
new file mode 100644 (file)
index 0000000..af3cf1a
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_CREDENTIALS_ITERATOR_H
+#define CCS_CREDENTIALS_ITERATOR_H
+
+#include "ccs_types.h"
+
+ cc_int32 ccs_credentials_iterator_handle_message (ccs_credentials_iterator_t  io_credentials_iterator,
+                                                   ccs_ccache_t                io_ccache,
+                                                   enum cci_msg_id_t           in_request_name,
+                                                   cci_stream_t                in_request_data,
+                                                   cci_stream_t               *out_reply_data);
+
+#endif /* CCS_CREDENTIALS_ITERATOR_H */
diff --git a/src/ccapi/server/ccs_list.c b/src/ccapi/server/ccs_list.c
new file mode 100644 (file)
index 0000000..17355c0
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+#include "ccs_list_internal.h"
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_list_object_release (void *io_object)
+{
+    return cci_check_error (ccs_cache_collection_release ((ccs_cache_collection_t) io_object));
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_list_object_compare_identifier (void             *in_cache_collection,
+                                                                     cci_identifier_t  in_identifier,
+                                                                     cc_uint32        *out_equal)
+{
+    return ccs_cache_collection_compare_identifier ((ccs_cache_collection_t) in_cache_collection,
+                                                    in_identifier,
+                                                    out_equal);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_list_new (ccs_cache_collection_list_t *out_list)
+{
+    return ccs_list_new (out_list, 
+                         ccErrInvalidContext,
+                         ccErrInvalidContext,
+                         ccs_cache_collection_list_object_compare_identifier,
+                         ccs_cache_collection_list_object_release);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_list_count (ccs_cache_collection_list_t  in_list,
+                                                 cc_uint64                   *out_count)
+{
+    return ccs_list_count (in_list, out_count);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_list_find (ccs_cache_collection_list_t  in_list,
+                                                cci_identifier_t             in_identifier,
+                                                ccs_cache_collection_t       *out_cache_collection)
+{
+    return ccs_list_find (in_list, in_identifier, (ccs_object_t *) out_cache_collection);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_list_add (ccs_cache_collection_list_t io_list,
+                                               ccs_cache_collection_t      in_cache_collection)
+{
+    return ccs_list_add (io_list, in_cache_collection);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_list_remove (ccs_cache_collection_list_t io_list,
+                                                  cci_identifier_t            in_identifier)
+{
+    return ccs_list_remove (io_list, in_identifier);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_list_release (ccs_cache_collection_list_t io_list)
+{
+    return ccs_list_release (io_list);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_list_object_release (void *io_ccache)
+{
+    return cci_check_error (ccs_ccache_release ((ccs_ccache_t) io_ccache));
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_list_object_compare_identifier (void             *in_ccache,
+                                                           cci_identifier_t  in_identifier,
+                                                           cc_uint32        *out_equal)
+{
+    return ccs_ccache_compare_identifier ((ccs_ccache_t) in_ccache,
+                                          in_identifier,
+                                          out_equal);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_new (ccs_ccache_list_t *out_list)
+{
+    return ccs_list_new (out_list, 
+                         ccErrInvalidCCache,
+                         ccErrInvalidCCacheIterator,
+                         ccs_ccache_list_object_compare_identifier,
+                         ccs_ccache_list_object_release);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_new_iterator (ccs_ccache_list_t           in_list,
+                                              ccs_ccache_list_iterator_t *out_list_iterator)
+{
+    return ccs_list_new_iterator (in_list, out_list_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_count (ccs_ccache_list_t  in_list,
+                                       cc_uint64         *out_count)
+{
+    return ccs_list_count (in_list, out_count);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_find (ccs_ccache_list_t  in_list,
+                                      cci_identifier_t   in_identifier,
+                                      ccs_ccache_t      *out_ccache)
+{
+    return ccs_list_find (in_list, in_identifier, (ccs_object_t *) out_ccache);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_find_iterator (ccs_ccache_list_t           in_list,
+                                               cci_identifier_t            in_identifier,
+                                               ccs_ccache_list_iterator_t *out_list_iterator)
+{
+    return ccs_list_find_iterator (in_list, in_identifier, 
+                                   (ccs_list_iterator_t *) out_list_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_add (ccs_ccache_list_t io_list,
+                                     ccs_ccache_t      in_ccache)
+{
+    return ccs_list_add (io_list, in_ccache);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_remove (ccs_ccache_list_t io_list,
+                                        cci_identifier_t  in_identifier)
+{
+    return ccs_list_remove (io_list, in_identifier);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_push_front (ccs_ccache_list_t io_list,
+                                            cci_identifier_t  in_identifier)
+{
+    return ccs_list_push_front (io_list, in_identifier);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_release (ccs_ccache_list_t io_list)
+{
+    return ccs_list_release (io_list);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_iterator_write (ccs_ccache_list_iterator_t in_list_iterator,
+                                                cci_stream_t               in_stream)
+{
+    return ccs_list_iterator_write (in_list_iterator, in_stream);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_iterator_clone (ccs_ccache_list_iterator_t  in_list_iterator,
+                                                ccs_ccache_list_iterator_t *out_list_iterator)
+{
+    return ccs_list_iterator_clone (in_list_iterator, out_list_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_iterator_next (ccs_ccache_list_iterator_t  io_list_iterator,
+                                               ccs_ccache_t               *out_ccache)
+{
+    return ccs_list_iterator_next (io_list_iterator, (ccs_object_t *) out_ccache);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_iterator_release (ccs_ccache_list_iterator_t io_list_iterator)
+{
+    return ccs_list_iterator_release (io_list_iterator);
+}
+
+#pragma mark-
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_credentials_list_object_release (void *io_object)
+{
+    return cci_check_error (ccs_credentials_release ((ccs_credentials_t) io_object));
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_credentials_list_object_compare_identifier (void             *in_credentials,
+                                                                cci_identifier_t  in_identifier,
+                                                                cc_uint32        *out_equal)
+{
+    return ccs_credentials_compare_identifier ((ccs_credentials_t) in_credentials,
+                                               in_identifier,
+                                               out_equal);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_new (ccs_credentials_list_t *out_list)
+{
+    return ccs_list_new (out_list, 
+                         ccErrInvalidCredentials, 
+                         ccErrInvalidCredentialsIterator,
+                         ccs_credentials_list_object_compare_identifier,
+                         ccs_credentials_list_object_release);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_new_iterator (ccs_credentials_list_t              in_list,
+                                                   ccs_credentials_list_iterator_t    *out_list_iterator)
+{
+    return ccs_list_new_iterator (in_list, out_list_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_count (ccs_credentials_list_t  in_list,
+                                            cc_uint64              *out_count)
+{
+    return ccs_list_count (in_list, out_count);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_find (ccs_credentials_list_t  in_list,
+                                           cci_identifier_t        in_identifier,
+                                           ccs_credentials_t      *out_credentials)
+{
+    return ccs_list_find (in_list, in_identifier, (ccs_object_t *) out_credentials);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_find_iterator (ccs_credentials_list_t           in_list,
+                                                    cci_identifier_t                 in_identifier,
+                                                    ccs_credentials_list_iterator_t *out_list_iterator)
+{
+    return ccs_list_find_iterator (in_list, in_identifier, 
+                                   (ccs_list_iterator_t *) out_list_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_add (ccs_credentials_list_t io_list,
+                                          ccs_credentials_t      in_credential)
+{
+    return ccs_list_add (io_list, in_credential);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_remove (ccs_credentials_list_t io_list,
+                                             cci_identifier_t       in_identifier)
+{
+    return ccs_list_remove (io_list, in_identifier);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_release (ccs_credentials_list_t io_list)
+{
+    return ccs_list_release (io_list);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_iterator_write (ccs_credentials_list_iterator_t in_list_iterator,
+                                                     cci_stream_t                    in_stream)
+{
+    return ccs_list_iterator_write (in_list_iterator, in_stream);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_iterator_clone (ccs_credentials_list_iterator_t  in_list_iterator,
+                                                     ccs_credentials_list_iterator_t *out_list_iterator)
+{
+    return ccs_list_iterator_clone (in_list_iterator, out_list_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_iterator_next (ccs_credentials_list_iterator_t  io_list_iterator,
+                                                    ccs_credentials_t               *out_credential)
+{
+    return ccs_list_iterator_next (io_list_iterator, (ccs_object_t *) out_credential);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_iterator_release (ccs_credentials_list_iterator_t io_list_iterator)
+{
+    return ccs_list_iterator_release (io_list_iterator);
+}
diff --git a/src/ccapi/server/ccs_list.h b/src/ccapi/server/ccs_list.h
new file mode 100644 (file)
index 0000000..435821a
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_LIST_H
+#define CCS_LIST_H
+
+
+#include "ccs_types.h"
+
+cc_int32 ccs_cache_collection_list_new (ccs_cache_collection_list_t *out_list);
+
+cc_int32 ccs_cache_collection_list_count (ccs_cache_collection_list_t  in_list,
+                                          cc_uint64                   *out_count);
+
+cc_int32 ccs_cache_collection_list_find (ccs_cache_collection_list_t  in_list,
+                                         cci_identifier_t             in_identifier,
+                                         ccs_cache_collection_t       *out_cache_collection);
+
+cc_int32 ccs_cache_collection_list_add (ccs_cache_collection_list_t io_list,
+                                        ccs_cache_collection_t      in_cache_collection);
+
+cc_int32 ccs_cache_collection_list_remove (ccs_cache_collection_list_t io_list,
+                                           cci_identifier_t            in_identifier);
+
+cc_int32 ccs_cache_collection_list_release (ccs_cache_collection_list_t io_list);
+
+#pragma mark -
+
+cc_int32 ccs_ccache_list_new (ccs_ccache_list_t *out_list);
+
+cc_int32 ccs_ccache_list_new_iterator (ccs_ccache_list_t           in_list,
+                                       ccs_ccache_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_ccache_list_count (ccs_ccache_list_t  in_list,
+                                cc_uint64         *out_count);
+
+cc_int32 ccs_ccache_list_find (ccs_ccache_list_t  in_list,
+                               cci_identifier_t   in_identifier,
+                               ccs_ccache_t      *out_ccache);
+
+cc_int32 ccs_ccache_list_find_iterator (ccs_ccache_list_t           in_list,
+                                        cci_identifier_t            in_identifier,
+                                        ccs_ccache_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_ccache_list_add (ccs_ccache_list_t io_list,
+                              ccs_ccache_t      in_ccache);
+
+cc_int32 ccs_ccache_list_remove (ccs_ccache_list_t io_list,
+                                 cci_identifier_t  in_identifier);
+
+cc_int32 ccs_ccache_list_push_front (ccs_ccache_list_t io_list,
+                                     cci_identifier_t  in_identifier);
+
+cc_int32 ccs_ccache_list_release (ccs_ccache_list_t io_list);
+
+
+cc_int32 ccs_ccache_list_iterator_write (ccs_ccache_list_iterator_t in_list_iterator,
+                                         cci_stream_t               in_stream);
+
+cc_int32 ccs_ccache_list_iterator_clone (ccs_ccache_list_iterator_t  in_list_iterator,
+                                         ccs_ccache_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_ccache_list_iterator_next (ccs_ccache_list_iterator_t  io_list_iterator,
+                                        ccs_ccache_t               *out_ccache);
+
+cc_int32 ccs_ccache_list_iterator_release (ccs_ccache_list_iterator_t io_list_iterator);
+
+#pragma mark -
+
+cc_int32 ccs_credentials_list_new (ccs_credentials_list_t *out_list);
+
+cc_int32 ccs_credentials_list_new_iterator (ccs_credentials_list_t           in_list,
+                                            ccs_credentials_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_credentials_list_count (ccs_credentials_list_t  in_list,
+                                     cc_uint64              *out_count);
+
+cc_int32 ccs_credentials_list_find (ccs_credentials_list_t  in_list,
+                                    cci_identifier_t        in_identifier,
+                                    ccs_credentials_t      *out_credentials);
+
+cc_int32 ccs_credentials_list_find_iterator (ccs_credentials_list_t           in_list,
+                                             cci_identifier_t                 in_identifier,
+                                             ccs_credentials_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_credentials_list_add (ccs_credentials_list_t io_list,
+                                   ccs_credentials_t      in_credential);
+
+cc_int32 ccs_credentials_list_remove (ccs_credentials_list_t io_list,
+                                      cci_identifier_t       in_identifier);
+
+cc_int32 ccs_credentials_list_release (ccs_credentials_list_t io_list);
+
+
+cc_int32 ccs_credentials_list_iterator_write (ccs_credentials_list_iterator_t in_list_iterator,
+                                              cci_stream_t                    in_stream);
+
+cc_int32 ccs_credentials_list_iterator_clone (ccs_credentials_list_iterator_t  in_list_iterator,
+                                              ccs_credentials_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_credentials_list_iterator_next (ccs_credentials_list_iterator_t  io_list_iterator,
+                                             ccs_credentials_t               *out_credential);
+
+cc_int32 ccs_credentials_list_iterator_release (ccs_credentials_list_iterator_t io_list_iterator);
+
+#endif /* CCS_LIST_H */
diff --git a/src/ccapi/server/ccs_list_internal.c b/src/ccapi/server/ccs_list_internal.c
new file mode 100644 (file)
index 0000000..a930fba
--- /dev/null
@@ -0,0 +1,612 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_list_internal.h"
+#include "cci_array_internal.h"
+#include "cci_identifier.h"
+#include "ccs_server.h"
+
+typedef enum {
+    ccs_list_action_insert,
+    ccs_list_action_remove,
+    ccs_list_action_push_front
+} ccs_list_action_enum;
+
+/* ------------------------------------------------------------------------ */
+
+struct ccs_list_d {
+    cci_array_t objects;
+    cci_array_t iterators;
+
+    cc_int32 object_not_found_err;
+    cc_int32 iterator_not_found_err;
+
+    ccs_object_compare_identifier_t object_compare_identifier;
+};
+
+struct ccs_list_d ccs_list_initializer = { NULL, NULL, -1, -1, NULL };
+
+/* ------------------------------------------------------------------------ */
+
+struct ccs_list_iterator_d {
+    cci_identifier_t identifier;
+    ccs_list_t list;
+    cc_uint64 current;
+};
+
+struct ccs_list_iterator_d ccs_list_iterator_initializer = { NULL, NULL, 0 };
+
+static cc_int32 ccs_list_iterator_new (ccs_list_iterator_t *out_list_iterator,
+                                       ccs_list_t           in_list);
+
+static cc_int32 ccs_list_iterator_object_release (cci_array_object_t io_list_iterator);
+
+static cc_int32 ccs_list_iterator_update (ccs_list_iterator_t  io_list_iterator,
+                                          ccs_list_action_enum in_action,
+                                          cc_uint64 in_object_index);
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_new (ccs_list_t                      *out_list,
+                       cc_int32                         in_object_not_found_err,
+                       cc_int32                         in_iterator_not_found_err,
+                       ccs_object_compare_identifier_t  in_object_compare_identifier,
+                       ccs_object_release_t             in_object_release)
+{
+    cc_int32 err = ccNoError;
+    ccs_list_t list = NULL;
+    
+    if (!out_list) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        list = malloc (sizeof (*list));
+        if (list) { 
+            *list = ccs_list_initializer;
+            list->object_not_found_err = in_object_not_found_err;
+            list->iterator_not_found_err = in_iterator_not_found_err;
+            list->object_compare_identifier = in_object_compare_identifier;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        err = cci_array_new (&list->objects, in_object_release);
+    }
+    
+    if (!err) {
+        err = cci_array_new (&list->iterators, ccs_list_iterator_object_release);
+    }
+    
+    if (!err) {
+        *out_list = list;
+        list = NULL;
+    }
+    
+    ccs_list_release (list);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_release (ccs_list_t io_list)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_list) { err = ccErrBadParam; }
+    
+    if (!err) {
+        cc_uint64 i;
+        
+        for (i = 0; i < cci_array_count (io_list->iterators); i++) {
+            ccs_list_iterator_release (cci_array_object_at_index (io_list->iterators, i));
+        }
+        free (io_list->iterators);
+        cci_array_release (io_list->objects);
+        free (io_list);
+    }
+    
+    return err;        
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_new_iterator (ccs_list_t           io_list,
+                                ccs_list_iterator_t *out_list_iterator)
+{
+    return cci_check_error (ccs_list_iterator_new (out_list_iterator, io_list));
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_release_iterator (ccs_list_t       io_list,
+                                    cci_identifier_t in_identifier)
+{
+    cc_int32 err = ccNoError;
+    ccs_list_iterator_t iterator = NULL;
+    
+    if (!io_list      ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_list_find_iterator (io_list, in_identifier, &iterator);
+    }
+    
+    if (!err) {
+        err = ccs_list_iterator_release (iterator);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_count (ccs_list_t  in_list,
+                         cc_uint64  *out_count)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_list  ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_count) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_count = cci_array_count (in_list->objects);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_list_find_index (ccs_list_t        in_list,
+                                     cci_identifier_t  in_identifier,
+                                     cc_uint64        *out_object_index)
+{
+    cc_int32 err = ccNoError;
+    cc_int32 found = 0;
+    
+    if (!in_list         ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier   ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_object_index) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err && !found) {
+        cc_uint64 i;
+        
+        for (i = 0; !err && i < cci_array_count (in_list->objects); i++) {
+            cc_uint32 equal = 0;
+            cci_array_object_t object = cci_array_object_at_index (in_list->objects, i);
+            
+            err = in_list->object_compare_identifier (object, in_identifier, &equal);
+            
+            if (!err && equal) {
+                found = 1;
+                *out_object_index = i;
+            }
+        }        
+    }
+    
+    if (!err && !found) {
+        err = cci_check_error (in_list->object_not_found_err); 
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+cc_int32 ccs_list_find (ccs_list_t        in_list,
+                        cci_identifier_t  in_identifier,
+                        ccs_object_t     *out_object)
+{
+    cc_int32 err = ccNoError;
+    cc_uint64 i;
+    
+    if (!in_list      ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+    if (!out_object   ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_list_find_index (in_list, in_identifier, &i);
+    }
+    
+    if (!err) {
+        *out_object = cci_array_object_at_index (in_list->objects, i);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_list_find_iterator_index (ccs_list_t        in_list,
+                                              cci_identifier_t  in_identifier,
+                                              cc_uint64        *out_object_index)
+{
+    cc_int32 err = ccNoError;
+    cc_int32 found = 0;
+    
+    if (!in_list         ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier   ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_object_index) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err && !found) {
+        cc_uint64 i;
+        
+        for (i = 0; !err && i < cci_array_count (in_list->iterators); i++) {
+            cc_uint32 equal = 0;
+            ccs_list_iterator_t iterator = cci_array_object_at_index (in_list->iterators, i);
+            
+            err = cci_identifier_compare (iterator->identifier, in_identifier, &equal);
+            
+            if (!err && equal) {
+                found = 1;
+                *out_object_index = i;
+            }
+        }        
+    }
+    
+    if (!err && !found) {
+        err = cci_check_error (in_list->object_not_found_err); 
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_find_iterator (ccs_list_t           in_list,
+                                 cci_identifier_t     in_identifier,
+                                 ccs_list_iterator_t *out_list_iterator)
+{
+    cc_int32 err = ccNoError;
+    cc_uint64 i;
+    
+    if (!in_list          ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier    ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_list_iterator) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_list_find_iterator_index (in_list, in_identifier, &i);
+    }
+    
+    if (!err) {
+        *out_list_iterator = cci_array_object_at_index (in_list->iterators, i);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_add (ccs_list_t   io_list,
+                       ccs_object_t in_object)
+{
+    cc_int32 err = ccNoError;
+    cc_uint64 add_index;
+    
+    if (!io_list  ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_object) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        add_index = cci_array_count (io_list->objects);
+        
+        err = cci_array_insert (io_list->objects, in_object, add_index);
+    }
+    
+    if (!err) {
+        /* Fixup iterator indexes */
+        cc_uint64 i;
+        
+        for (i = 0; !err && i < cci_array_count (io_list->iterators); i++) {
+            ccs_list_iterator_t iterator = cci_array_object_at_index (io_list->iterators, i);
+            
+            err = ccs_list_iterator_update (iterator, ccs_list_action_insert, add_index);
+        }        
+    }    
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_remove (ccs_list_t       io_list,
+                          cci_identifier_t in_identifier)
+{
+    cc_int32 err = ccNoError;
+    cc_uint64 remove_index;
+    
+    if (!io_list      ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_list_find_index (io_list, in_identifier, &remove_index);
+    }
+    
+    if (!err) {
+        err = cci_array_remove (io_list->objects, remove_index);
+    }
+    
+    if (!err) {
+        /* Fixup iterator indexes */
+        cc_uint64 i;
+        
+        for (i = 0; !err && i < cci_array_count (io_list->iterators); i++) {
+            ccs_list_iterator_t iterator = cci_array_object_at_index (io_list->iterators, i);
+            
+            err = ccs_list_iterator_update (iterator, ccs_list_action_remove, remove_index);
+        }        
+    }    
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_push_front (ccs_list_t       io_list,
+                              cci_identifier_t in_identifier)
+{
+    cc_int32 err = ccNoError;
+    cc_uint64 push_front_index;
+    
+    if (!io_list      ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_list_find_index (io_list, in_identifier, &push_front_index);
+    }
+    
+    if (!err) {
+        err = cci_array_push_front (io_list->objects, push_front_index);        
+    }
+    
+    if (!err) {
+        /* Fixup iterator indexes */
+        cc_uint64 i;
+        
+        for (i = 0; !err && i < cci_array_count (io_list->iterators); i++) {
+            ccs_list_iterator_t iterator = cci_array_object_at_index (io_list->iterators, i);
+            
+            err = ccs_list_iterator_update (iterator, 
+                                            ccs_list_action_push_front, 
+                                            push_front_index);
+        }        
+    }    
+    
+    return cci_check_error (err);    
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_list_iterator_new (ccs_list_iterator_t *out_list_iterator,
+                                       ccs_list_t           io_list)
+{
+    cc_int32 err = ccNoError;
+    ccs_list_iterator_t list_iterator = NULL;
+    
+    if (!out_list_iterator) { err = cci_check_error (ccErrBadParam); }
+    if (!io_list          ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        list_iterator = malloc (sizeof (*list_iterator));
+        if (list_iterator) { 
+            *list_iterator = ccs_list_iterator_initializer;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        err = ccs_server_new_identifier (&list_iterator->identifier);
+    }
+
+    if (!err) {
+        list_iterator->list = io_list;
+        list_iterator->current = 0;
+        
+        err = cci_array_insert (io_list->iterators, 
+                                list_iterator, cci_array_count (io_list->iterators));
+    }
+
+    if (!err) {
+        *out_list_iterator = list_iterator;
+        list_iterator = NULL;
+    }
+    
+    ccs_list_iterator_release (list_iterator);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_iterator_write (ccs_list_iterator_t in_list_iterator,
+                                  cci_stream_t        in_stream)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_list_iterator) { err = cci_check_error (ccErrBadParam); }
+    if (!in_stream       ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_identifier_write (in_list_iterator->identifier, 
+                                    in_stream);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_iterator_clone (ccs_list_iterator_t  in_list_iterator,
+                                  ccs_list_iterator_t *out_list_iterator)
+{
+    cc_int32 err = ccNoError;
+    ccs_list_iterator_t list_iterator = NULL;
+    
+    if (!in_list_iterator ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_list_iterator) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_list_iterator_new (&list_iterator, in_list_iterator->list);
+    }
+    
+    if (!err) {
+        list_iterator->current = in_list_iterator->current;
+
+        *out_list_iterator = list_iterator;
+        list_iterator = NULL;
+    }
+    
+    ccs_list_iterator_release (list_iterator);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_list_iterator_object_release (cci_array_object_t io_list_iterator)
+{
+    cc_int32 err = ccNoError;
+    ccs_list_iterator_t list_iterator = (ccs_list_iterator_t) io_list_iterator;
+    
+    if (!io_list_iterator) { err = ccErrBadParam; }
+    
+    if (!err) {
+        cci_identifier_release (list_iterator->identifier);
+        free (io_list_iterator);
+    }
+    
+    return err;    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_iterator_release (ccs_list_iterator_t io_list_iterator)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_list_iterator) { err = ccErrBadParam; }
+    
+    if (!err) {
+        cc_uint64 i = 0;
+        
+        if (ccs_list_find_iterator_index (io_list_iterator->list, 
+                                          io_list_iterator->identifier, 
+                                          &i) == ccNoError) {
+            /* cci_array_remove will call ccs_list_iterator_object_release */
+            cci_array_remove (io_list_iterator->list->iterators, i);
+        } else {
+            cci_debug_printf ("Warning: iterator not in iterator list!");
+        }
+    }
+    
+    return err;        
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_iterator_current (ccs_list_iterator_t  io_list_iterator,
+                                    ccs_object_t        *out_object)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_list_iterator) { err = cci_check_error (ccErrBadParam); }
+    if (!out_object      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        if (io_list_iterator->current < cci_array_count (io_list_iterator->list->objects)) {
+            *out_object = cci_array_object_at_index (io_list_iterator->list->objects, 
+                                                     io_list_iterator->current);
+        } else {
+            err = ccIteratorEnd;
+        }
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_iterator_next (ccs_list_iterator_t  io_list_iterator,
+                                 ccs_object_t        *out_object)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_list_iterator) { err = cci_check_error (ccErrBadParam); }
+    if (!out_object      ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        if (io_list_iterator->current < cci_array_count (io_list_iterator->list->objects)) {
+            *out_object = cci_array_object_at_index (io_list_iterator->list->objects, 
+                                                     io_list_iterator->current);
+            io_list_iterator->current++;
+        } else {
+            err = ccIteratorEnd;
+        }
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_list_iterator_update (ccs_list_iterator_t  io_list_iterator,
+                                          ccs_list_action_enum in_action,
+                                          cc_uint64            in_object_index)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_list_iterator) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        /* When the list changes adjust the current index so that */
+        /* we don't unnecessarily skip or double count items      */
+        if (in_action == ccs_list_action_insert) {
+            if (io_list_iterator->current > in_object_index) {
+                io_list_iterator->current++;
+            }
+            
+        } else if (in_action == ccs_list_action_remove) {
+            if (io_list_iterator->current >= in_object_index) {
+                io_list_iterator->current--;
+            }
+            
+        } else if (in_action == ccs_list_action_push_front) {
+            if (io_list_iterator->current < in_object_index) {
+                io_list_iterator->current++;
+            }
+            
+        } else {
+            err = cci_check_error (ccErrBadParam);
+        }
+    }
+    
+    return cci_check_error (err);    
+}
+
diff --git a/src/ccapi/server/ccs_list_internal.h b/src/ccapi/server/ccs_list_internal.h
new file mode 100644 (file)
index 0000000..83320a5
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_LIST_INTERNAL_H
+#define CCS_LIST_INTERNAL_H
+
+#include "cci_common.h"
+
+struct ccs_list_d;
+typedef struct ccs_list_d *ccs_list_t;
+
+struct ccs_list_iterator_d;
+typedef struct ccs_list_iterator_d *ccs_list_iterator_t;
+
+typedef void *ccs_object_t;
+typedef cc_int32 (*ccs_object_release_t) (ccs_object_t);
+typedef cc_int32 (*ccs_object_compare_identifier_t) (ccs_object_t, cci_identifier_t, cc_uint32 *);
+
+cc_int32 ccs_list_new (ccs_list_t                      *out_list,
+                       cc_int32                         in_object_not_found_err,
+                       cc_int32                         in_iterator_not_found_err,
+                       ccs_object_compare_identifier_t  in_object_compare_identifier,
+                       ccs_object_release_t             in_object_release);
+
+cc_int32 ccs_list_release (ccs_list_t io_list);
+
+cc_int32 ccs_list_new_iterator (ccs_list_t           io_list,
+                                ccs_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_list_release_iterator (ccs_list_t       io_list,
+                                    cci_identifier_t in_identifier);
+
+cc_int32 ccs_list_count (ccs_list_t  in_list,
+                         cc_uint64  *out_count);
+
+cc_int32 ccs_list_find (ccs_list_t        in_list,
+                        cci_identifier_t  in_identifier,
+                        ccs_object_t     *out_object);
+
+cc_int32 ccs_list_find_iterator (ccs_list_t           in_list,
+                                 cci_identifier_t     in_identifier,
+                                 ccs_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_list_add (ccs_list_t   io_list,
+                       ccs_object_t in_object);
+
+cc_int32 ccs_list_remove (ccs_list_t       io_list,
+                          cci_identifier_t in_identifier);
+
+cc_int32 ccs_list_push_front (ccs_list_t       io_list,
+                              cci_identifier_t in_identifier);
+
+
+cc_int32 ccs_list_iterator_write (ccs_list_iterator_t in_list_iterator,
+                                  cci_stream_t        in_stream);
+
+cc_int32 ccs_list_iterator_clone (ccs_list_iterator_t  in_list_iterator,
+                                  ccs_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_list_iterator_current (ccs_list_iterator_t  io_list_iterator,
+                                    ccs_object_t        *out_object);
+
+cc_int32 ccs_list_iterator_next (ccs_list_iterator_t  io_list_iterator,
+                                 ccs_object_t        *out_object);
+
+cc_int32 ccs_list_iterator_release (ccs_list_iterator_t io_list_iterator);
+
+
+#endif /* CCS_LIST_INTERNAL_H */
diff --git a/src/ccapi/server/ccs_lock.c b/src/ccapi/server/ccs_lock.c
new file mode 100644 (file)
index 0000000..939da5e
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+
+struct ccs_lock_d {
+    cc_uint32 type;
+    cc_uint32 pending;
+    cc_int32  invalid_object_err;
+    ccs_pipe_t client_pipe;
+    ccs_pipe_t reply_pipe;
+};
+
+struct ccs_lock_d ccs_lock_initializer = { 0, 1, 1, NULL, NULL };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_new (ccs_lock_t *out_lock,
+                       cc_uint32   in_type,
+                       cc_int32    in_invalid_object_err,
+                       ccs_pipe_t  in_client_pipe,
+                       ccs_pipe_t  in_reply_pipe)
+{
+    cc_int32 err = ccNoError;
+    ccs_lock_t lock = NULL;
+    
+    if (!out_lock                       ) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (in_type != cc_lock_read && 
+        in_type != cc_lock_write &&
+        in_type != cc_lock_upgrade &&
+        in_type != cc_lock_downgrade) { 
+        err = cci_check_error (ccErrBadLockType); 
+    }
+    
+    if (!err) {
+        lock = malloc (sizeof (*lock));
+        if (lock) { 
+            *lock = ccs_lock_initializer;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        err = ccs_pipe_copy (&lock->client_pipe, in_client_pipe);
+    }
+    
+    if (!err) {
+        err = ccs_pipe_copy (&lock->reply_pipe, in_reply_pipe);
+    }
+    
+    if (!err) {
+        lock->type = in_type;
+        lock->invalid_object_err = in_invalid_object_err;
+        
+        *out_lock = lock;
+        lock = NULL;
+    }
+    
+    ccs_lock_release (lock);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_release (ccs_lock_t io_lock)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_lock) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err && io_lock->pending) {
+        err = ccs_server_send_reply (io_lock->reply_pipe, 
+                                     io_lock->invalid_object_err, NULL);
+    }
+    
+    if (!err) {
+        ccs_pipe_release (io_lock->client_pipe);
+        ccs_pipe_release (io_lock->reply_pipe);
+        free (io_lock);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_grant_lock (ccs_lock_t io_lock)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_lock) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        if (io_lock->pending) {
+            err = ccs_server_send_reply (io_lock->reply_pipe, err, NULL);
+            
+            if (!err) {
+                ccs_pipe_release (io_lock->reply_pipe);
+                io_lock->pending = 0;
+                io_lock->reply_pipe = NULL;
+            }
+        } else {
+            cci_debug_printf ("WARNING %s() called on non-pending lock!", 
+                              __FUNCTION__);
+        }
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 ccs_lock_is_pending (ccs_lock_t  in_lock,
+                               cc_uint32  *out_pending)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_lock    ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_pending) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_pending = in_lock->pending;
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_type (ccs_lock_t  in_lock,
+                        cc_uint32  *out_lock_type)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_lock      ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_lock_type) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_lock_type = in_lock->type;
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_is_read_lock (ccs_lock_t  in_lock,
+                                cc_uint32  *out_is_read_lock)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_lock         ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_is_read_lock) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_is_read_lock = (in_lock->type == cc_lock_read || 
+                             in_lock->type == cc_lock_downgrade);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_is_write_lock (ccs_lock_t  in_lock,
+                                 cc_uint32  *out_is_write_lock)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_lock          ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_is_write_lock) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_is_write_lock = (in_lock->type == cc_lock_write || 
+                              in_lock->type == cc_lock_upgrade);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_is_for_client (ccs_lock_t     in_lock,
+                                 ccs_pipe_t     in_client_pipe,
+                                 cc_uint32     *out_is_for_client)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_lock                        ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_is_for_client              ) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_pipe_compare (in_lock->client_pipe, in_client_pipe, 
+                                out_is_for_client);
+    }
+    
+    return cci_check_error (err);    
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_client (ccs_lock_t  in_lock,
+                          ccs_pipe_t *out_client_pipe)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_lock        ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_client_pipe) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_client_pipe = in_lock->client_pipe;
+    }
+    
+    return cci_check_error (err);    
+}
diff --git a/src/ccapi/server/ccs_lock.h b/src/ccapi/server/ccs_lock.h
new file mode 100644 (file)
index 0000000..197f5d5
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_LOCK_H
+#define CCS_LOCK_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_lock_new (ccs_lock_t *out_lock,
+                       cc_uint32   in_type,
+                       cc_int32    in_invalid_object_err,
+                       ccs_pipe_t  in_client_pipe,
+                       ccs_pipe_t  in_reply_pipe);
+
+cc_int32 ccs_lock_release (ccs_lock_t io_lock);
+
+cc_int32 ccs_lock_grant_lock (ccs_lock_t io_lock);
+
+cc_uint32 ccs_lock_is_pending (ccs_lock_t  in_lock,
+                               cc_uint32  *out_pending);
+
+cc_int32 ccs_lock_type (ccs_lock_t  in_lock,
+                        cc_uint32  *out_lock_type);
+
+cc_int32 ccs_lock_is_read_lock (ccs_lock_t  in_lock,
+                                cc_uint32  *out_is_read_lock);
+
+cc_int32 ccs_lock_is_write_lock (ccs_lock_t  in_lock,
+                                 cc_uint32  *out_is_write_lock);
+
+cc_int32 ccs_lock_is_for_client (ccs_lock_t  in_lock,
+                                 ccs_pipe_t  in_client_pipe,
+                                 cc_uint32  *out_is_for_client);
+
+cc_int32 ccs_lock_client (ccs_lock_t  in_lock,
+                          ccs_pipe_t *out_client_pipe);
+
+#endif /* CCS_LOCK_H */
diff --git a/src/ccapi/server/ccs_lock_state.c b/src/ccapi/server/ccs_lock_state.c
new file mode 100644 (file)
index 0000000..f9bb614
--- /dev/null
@@ -0,0 +1,543 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+
+struct ccs_lock_state_d {
+    cc_int32 invalid_object_err;
+    cc_int32 pending_lock_err;
+    cc_int32 no_lock_err;
+    ccs_lock_array_t locks;
+    cc_uint64 first_pending_lock_index;
+};
+
+struct ccs_lock_state_d ccs_lock_state_initializer = { 1, 1, 1, NULL, 0 };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_state_new (ccs_lock_state_t *out_lock_state, 
+                             cc_int32          in_invalid_object_err, 
+                             cc_int32          in_pending_lock_err, 
+                             cc_int32          in_no_lock_err)
+{
+    cc_int32 err = ccNoError;
+    ccs_lock_state_t lock_state = NULL;
+    
+    if (!out_lock_state) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        lock_state = malloc (sizeof (*lock_state));
+        if (lock_state) { 
+            *lock_state = ccs_lock_state_initializer;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        err = ccs_lock_array_new (&lock_state->locks);
+    }
+    
+    if (!err) {
+        lock_state->invalid_object_err = in_invalid_object_err;
+        lock_state->pending_lock_err = in_pending_lock_err;
+        lock_state->no_lock_err = in_no_lock_err;
+        
+        *out_lock_state = lock_state;
+        lock_state = NULL;
+    }
+    
+    ccs_lock_state_release (lock_state);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_state_release (ccs_lock_state_t io_lock_state)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_lock_state) { err = cci_check_error (ccErrBadParam); }
+
+    if (!err) {
+        ccs_lock_array_release (io_lock_state->locks);
+        free (io_lock_state);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_state_allow_read (ccs_lock_state_t  in_lock_state,
+                                    ccs_pipe_t        in_client_pipe,
+                                    cc_uint32        *out_allow_read)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 allow_read = 0;
+    
+    if (!in_lock_state                  ) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!out_allow_read                 ) { err = cci_check_error (ccErrBadParam); }
+    
+    /* A client may read if no other clients have write locks */
+    
+    if (!err) {
+        cc_uint64 lock_count = in_lock_state->first_pending_lock_index;
+        if (lock_count == 0) {
+            allow_read = 1;
+        } else {
+            ccs_lock_t lock = ccs_lock_array_object_at_index (in_lock_state->locks, 0);
+            cc_uint32 is_read_lock;
+            cc_uint32 is_for_client;
+            
+            err = ccs_lock_is_read_lock (lock, &is_read_lock);
+            
+            if (!err) {
+                err = ccs_lock_is_for_client (lock, in_client_pipe, &is_for_client);
+            }
+            
+            if (!err) {
+                /* read locks or write lock we own */
+                allow_read = (is_read_lock || is_for_client);  
+            }
+        }
+    }
+    
+    if (!err) {
+        *out_allow_read = allow_read;
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_state_allow_write (ccs_lock_state_t  in_lock_state,
+                                     ccs_pipe_t        in_client_pipe,
+                                     cc_uint32        *out_allow_write)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 allow_write = 0;
+    
+    if (!in_lock_state                  ) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!out_allow_write                ) { err = cci_check_error (ccErrBadParam); }
+    
+    /* A client may write if there are no locks or if it has a write lock */
+    
+    if (!err) {
+        cc_uint64 lock_count = in_lock_state->first_pending_lock_index;
+        if (lock_count == 0) {
+            allow_write = 1;
+        } else {
+            ccs_lock_t lock = ccs_lock_array_object_at_index (in_lock_state->locks, 0);
+            cc_uint32 is_write_lock = 0;
+            cc_uint32 is_for_client = 0;
+            
+            err = ccs_lock_is_write_lock (lock, &is_write_lock);
+            
+            if (!err) {
+                err = ccs_lock_is_for_client (lock, in_client_pipe, &is_for_client);
+            }
+            
+            if (!err) {
+                allow_write = (is_write_lock && is_for_client);
+            }
+        }
+    }
+    
+    if (!err) {
+        *out_allow_write = allow_write;
+    }
+    
+    return cci_check_error (err);    
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_lock_status_add_pending_lock (ccs_lock_state_t  io_lock_state,
+                                                  ccs_pipe_t        in_client_pipe,
+                                                  ccs_pipe_t        in_reply_pipe,
+                                                  cc_uint32         in_lock_type,
+                                                  cc_uint64        *out_lock_index)
+{
+    cc_int32 err = ccNoError;
+    ccs_lock_t lock = NULL;
+    
+    if (!io_lock_state                  ) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_lock_new (&lock, in_lock_type, 
+                            io_lock_state->invalid_object_err,
+                            in_client_pipe, in_reply_pipe);
+    }
+    
+    if (!err) {
+        err = ccs_lock_array_insert (io_lock_state->locks, lock,
+                                     ccs_lock_array_count (io_lock_state->locks));
+        if (!err) { lock = NULL; /* take ownership */ }
+    }
+    
+    if (!err) {
+        *out_lock_index = ccs_lock_array_count (io_lock_state->locks) - 1;
+    }
+    
+    ccs_lock_release (lock);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_lock_status_remove_lock (ccs_lock_state_t io_lock_state,
+                                             cc_uint64        in_lock_index)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_lock_state) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_lock_array_remove (io_lock_state->locks, in_lock_index);
+        
+        if (!err && in_lock_index < io_lock_state->first_pending_lock_index) { 
+            io_lock_state->first_pending_lock_index--; 
+        }
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_lock_status_grant_lock (ccs_lock_state_t io_lock_state,
+                                            cc_uint64        in_pending_lock_index)
+{
+    cc_int32 err = ccNoError;
+    cc_uint64 new_lock_index = 0;
+    
+    if (!io_lock_state) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err && in_pending_lock_index < io_lock_state->first_pending_lock_index) {
+        err = cci_check_error (ccErrBadParam);
+    }
+    
+    if (!err) {
+        err = ccs_lock_array_move (io_lock_state->locks, 
+                                   in_pending_lock_index, 
+                                   io_lock_state->first_pending_lock_index,
+                                   &new_lock_index);
+        if (!err) { io_lock_state->first_pending_lock_index++; }
+    }
+    
+    if (!err) {
+        ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, 
+                                                          new_lock_index);
+        err = ccs_lock_grant_lock (lock);
+    }
+    
+    return cci_check_error (err);    
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_lock_state_check_pending_lock (ccs_lock_state_t  io_lock_state,
+                                                   ccs_pipe_t        in_pending_lock_client_pipe,
+                                                   cc_uint32         in_pending_lock_type,
+                                                   cc_uint32        *out_grant_lock)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 is_write_locked = 0;
+    cc_uint32 client_has_lock = 0;
+    cc_uint32 client_lock_type = 0;
+    cc_uint32 grant_lock = 0;
+    
+    if (!io_lock_state                               ) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_pipe_valid (in_pending_lock_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!out_grant_lock                              ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        cc_uint64 i;
+        cc_uint64 lock_count = io_lock_state->first_pending_lock_index;
+        
+        for (i = 0; !err && i < lock_count; i++) {
+            ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i);
+            cc_uint32 lock_type = 0;
+            cc_uint32 lock_is_for_client = 0;
+            
+            err = ccs_lock_type (lock, &lock_type);
+            
+            if (!err) {
+                err = ccs_lock_is_for_client (lock, in_pending_lock_client_pipe, 
+                                              &lock_is_for_client);
+            }
+            
+            if (!err) {
+                if (lock_type == cc_lock_write || lock_type == cc_lock_upgrade) {
+                    if (is_write_locked) {
+                        cci_debug_printf ("WARNING %s() multiple write locks.", 
+                                          __FUNCTION__);
+                    }
+                    is_write_locked = 1;
+                }
+                
+                if (lock_is_for_client) {
+                    if (client_has_lock) {
+                        cci_debug_printf ("WARNING %s() client has multiple locks.", 
+                                          __FUNCTION__);
+                    }
+                    client_has_lock = 1;
+                    client_lock_type = lock_type;
+                }
+            }
+        }
+    }
+    
+    if (!err) {
+        cc_uint64 lock_count = io_lock_state->first_pending_lock_index;
+        
+        if (in_pending_lock_type == cc_lock_write) {
+            if (client_has_lock) {
+                err = cci_check_error (ccErrBadLockType);
+            } else {
+                grant_lock = (lock_count == 0);
+            }
+            
+        } else if (in_pending_lock_type == cc_lock_read) {
+            if (client_has_lock) {
+                err = cci_check_error (ccErrBadLockType);
+            } else {
+                grant_lock = !is_write_locked;
+            }
+            
+        } else if (in_pending_lock_type == cc_lock_upgrade) {
+            if (!client_has_lock || (client_lock_type != cc_lock_read && 
+                                     client_lock_type != cc_lock_downgrade)) {
+                err = cci_check_error (ccErrBadLockType);
+            } else {
+                /* don't grant if other clients have read locks */
+                grant_lock = (lock_count == 1); 
+            }
+            
+        } else if (in_pending_lock_type == cc_lock_downgrade) {
+            if (!client_has_lock || (client_lock_type != cc_lock_write && 
+                                     client_lock_type != cc_lock_upgrade)) {
+                err = cci_check_error (ccErrBadLockType);
+            } else {
+                /* downgrades can never block */
+                grant_lock = 1;
+            }
+        } else {
+            err = cci_check_error (ccErrBadLockType);
+       }
+    }
+    
+    if (!err) {
+        *out_grant_lock = grant_lock;
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_lock_status_try_to_grant_pending_locks (ccs_lock_state_t io_lock_state) 
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 done = 1;
+    
+    if (!io_lock_state) { err = cci_check_error (ccErrBadParam); }
+    
+    /* The lock array should now be in one of two states: empty or containing 
+        * only read locks because if it contained a write lock we would have just
+        * deleted it.  Look at the pending locks and see if we can grant them. 
+        * Note that downgrade locks mean we must check all pending locks each pass
+        * since a downgrade lock might be last in the list. */
+    
+    
+    while (!err && !done) {
+        cc_uint64 i;
+        cc_uint64 count = ccs_lock_array_count (io_lock_state->locks);
+        cc_uint32 granted_lock = 0;
+        
+        for (i = io_lock_state->first_pending_lock_index; !err && i < count; i++) {
+            ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i);
+            cc_uint32 lock_type = 0;
+            ccs_pipe_t client_pipe = NULL;
+            cc_uint32 can_grant_lock_now = 0;
+
+            err = ccs_lock_client (lock, &client_pipe);
+            
+            if (!err) {
+                err = ccs_lock_type (lock, &lock_type);
+            }
+            
+            if (!err) {
+                err = ccs_lock_state_check_pending_lock (io_lock_state, client_pipe,
+                                                         lock_type, &can_grant_lock_now);
+            }
+
+            if (!err && can_grant_lock_now) {
+                err = ccs_lock_status_grant_lock (io_lock_state, i);
+                if (!err) { granted_lock = 1; }
+            }
+        }
+        
+        if (!err && !granted_lock) {
+            done = 1;
+        }
+    } 
+    
+    return cci_check_error (err);    
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_state_add (ccs_lock_state_t  io_lock_state,
+                             ccs_pipe_t        in_client_pipe,
+                             ccs_pipe_t        in_reply_pipe,
+                             cc_uint32         in_lock_type,
+                             cc_uint32         in_block,
+                             cc_uint32        *out_will_block)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 can_grant_lock_now = 0;
+    cc_uint32 will_block = 0;
+    
+    if (!io_lock_state                  ) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_will_block                 ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        /* Sanity check: if there are any pending locks for this client
+         * the client must have timed out waiting for our reply.  Remove any
+         * existing pending locks for the client. */
+        cc_uint64 i;
+        cc_uint64 count = ccs_lock_array_count (io_lock_state->locks);
+
+        for (i = io_lock_state->first_pending_lock_index; !err && i < count; i++) {
+            ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i);
+            cc_uint32 has_pending_lock_for_client = 0;
+            
+            err = ccs_lock_is_for_client (lock, in_client_pipe, &has_pending_lock_for_client);
+            
+            if (!err && has_pending_lock_for_client) {
+                cci_debug_printf ("WARNING %s() removing pending lock for client.", __FUNCTION__);
+                err = ccs_lock_status_remove_lock (io_lock_state, i);
+            }
+        }
+    }
+    
+    if (!err) {
+        err = ccs_lock_state_check_pending_lock (io_lock_state, in_client_pipe,
+                                                 in_lock_type, &can_grant_lock_now);
+    }
+        
+    if (!err) {
+        if (!can_grant_lock_now && !in_block) {
+            err = cci_check_error (io_lock_state->pending_lock_err);
+            
+        } else {
+            cc_uint64 new_lock_index = 0;
+            
+            err = ccs_lock_status_add_pending_lock (io_lock_state,
+                                                    in_client_pipe,
+                                                    in_reply_pipe,
+                                                    in_lock_type,
+                                                    &new_lock_index);
+            
+            if (!err) {
+                if (can_grant_lock_now) {
+                    err = ccs_lock_status_grant_lock (io_lock_state,
+                                                      new_lock_index);
+                    
+                    if (!err && (in_lock_type == cc_lock_downgrade)) {
+                        /* downgrades can allow us to grant other locks */
+                        err = ccs_lock_status_try_to_grant_pending_locks (io_lock_state);
+                    }
+                } else {
+                    will_block = 1;
+                }
+            }
+        }
+    }
+    
+    if (!err) {
+        *out_will_block = will_block;
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_state_remove (ccs_lock_state_t io_lock_state,
+                                ccs_pipe_t       in_client_pipe)
+{
+    cc_int32 err = ccNoError;
+    cc_uint32 found_lock = 0;
+    
+    if (!io_lock_state                  ) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        cc_uint64 i;
+        cc_uint64 lock_count = io_lock_state->first_pending_lock_index;
+        
+        for (i = 0; !err && i < lock_count; i++) {
+            ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i);
+            
+            err = ccs_lock_is_for_client (lock, in_client_pipe, &found_lock);
+            
+            if (!err && found_lock) {
+                cci_debug_printf ("%s: Removing lock %p.", __FUNCTION__, lock);
+                err = ccs_lock_status_remove_lock (io_lock_state, i);
+                break;
+            }
+        }
+    }
+
+    if (!err && !found_lock) {
+        err = cci_check_error (io_lock_state->no_lock_err);
+    }
+    
+    if (!err) {
+        err = ccs_lock_status_try_to_grant_pending_locks (io_lock_state);
+    }    
+    
+    return cci_check_error (err);    
+}
+                                                  
diff --git a/src/ccapi/server/ccs_lock_state.h b/src/ccapi/server/ccs_lock_state.h
new file mode 100644 (file)
index 0000000..1918452
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_LOCK_STATE_H
+#define CCS_LOCK_STATE_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_lock_state_new (ccs_lock_state_t *out_lock_state, 
+                             cc_int32          in_invalid_object_err, 
+                             cc_int32          in_pending_lock_err, 
+                             cc_int32          in_no_lock_err);
+
+cc_int32 ccs_lock_state_release (ccs_lock_state_t io_lock_state);
+
+cc_int32 ccs_lock_state_allow_read (ccs_lock_state_t  in_lock_state,
+                                    ccs_pipe_t        in_client_pipe,
+                                    cc_uint32        *out_allow_read);
+
+cc_int32 ccs_lock_state_allow_write (ccs_lock_state_t  in_lock_state,
+                                     ccs_pipe_t        in_client_pipe,
+                                     cc_uint32        *out_allow_write);
+
+cc_int32 ccs_lock_state_add (ccs_lock_state_t  io_lock_state,
+                             ccs_pipe_t        in_client_pipe,
+                             ccs_pipe_t        in_reply_pipe,
+                             cc_uint32         in_lock_type,
+                             cc_uint32         in_block,
+                             cc_uint32        *out_will_block);
+
+cc_int32 ccs_lock_state_remove (ccs_lock_state_t io_lock_state,
+                                ccs_pipe_t       in_client_pipe);
+
+#endif /* CCS_LOCK_STATE_H */
diff --git a/src/ccapi/server/ccs_os_pipe.h b/src/ccapi/server/ccs_os_pipe.h
new file mode 100644 (file)
index 0000000..57fe64b
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_OS_PIPE_H
+#define CCS_OS_PIPE_H
+
+#include "ccs_types.h"
+
+inline cc_int32 ccs_os_pipe_copy (ccs_os_pipe_t *out_pipe,
+                                  ccs_os_pipe_t  in_pipe);
+
+inline cc_int32 ccs_os_pipe_release (ccs_os_pipe_t io_pipe);
+
+inline cc_int32 ccs_os_pipe_compare (ccs_os_pipe_t  in_pipe,
+                                     ccs_os_pipe_t  in_compare_to_pipe,
+                                     cc_uint32  *out_equal);
+
+cc_int32 ccs_os_pipe_valid (ccs_os_pipe_t in_pipe);
+
+
+#endif /* CCS_OS_PIPE_H */
diff --git a/src/ccapi/server/ccs_os_server.h b/src/ccapi/server/ccs_os_server.h
new file mode 100644 (file)
index 0000000..557ad59
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_OS_SERVER_H
+#define CCS_OS_SERVER_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_os_server_send_reply (ccs_pipe_t   in_reply_pipe,
+                                   cci_stream_t in_reply_stream);
+
+#endif /* CCS_OS_SERVER_H */
diff --git a/src/ccapi/server/ccs_pipe.c b/src/ccapi/server/ccs_pipe.c
new file mode 100644 (file)
index 0000000..d7521b5
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+#include "ccs_os_pipe.h"
+
+struct ccs_pipe_d {
+    ccs_os_pipe_t os_pipe;
+};
+
+struct ccs_pipe_d ccs_pipe_initializer = { CCS_OS_PIPE_NULL };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_pipe_new (ccs_pipe_t    *out_pipe,
+                       ccs_os_pipe_t  in_os_pipe)
+{
+    cc_int32 err = ccNoError;
+    ccs_pipe_t new_pipe = NULL;
+    
+    if (!out_pipe                      ) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_os_pipe_valid (in_os_pipe)) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        new_pipe = malloc (sizeof (*new_pipe));
+        if (new_pipe) { 
+            *new_pipe = ccs_pipe_initializer;
+        } else {
+            err = cci_check_error (ccErrNoMem); 
+        }
+    }
+    
+    if (!err) {
+        err = ccs_os_pipe_copy (&new_pipe->os_pipe, in_os_pipe);
+    }
+    
+    if (!err) {
+        *out_pipe = new_pipe;
+        new_pipe = NULL;
+    }
+    
+    ccs_pipe_release (new_pipe);
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_pipe_release (ccs_pipe_t io_pipe)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!io_pipe) { err = ccErrBadParam; }
+    
+    if (!err) {
+        ccs_os_pipe_release (io_pipe->os_pipe);
+        free (io_pipe);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_pipe_copy (ccs_pipe_t *out_pipe,
+                        ccs_pipe_t  in_pipe)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!out_pipe) { err = cci_check_error (ccErrBadParam); }
+    if (!in_pipe ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_pipe_new (out_pipe, in_pipe->os_pipe);
+     }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_pipe_compare (ccs_pipe_t  in_pipe,
+                           ccs_pipe_t  in_compare_to_pipe,
+                           cc_uint32  *out_equal)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!in_pipe           ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_compare_to_pipe) { err = cci_check_error (ccErrBadParam); }
+    if (!out_equal         ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_os_pipe_compare (in_pipe->os_pipe,
+                                   in_compare_to_pipe->os_pipe,
+                                   out_equal);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_pipe_compare_to_os_pipe (ccs_pipe_t     in_pipe,
+                                      ccs_os_pipe_t  in_compare_to_os_pipe,
+                                      cc_uint32      *out_equal)
+{
+    cc_int32 err = ccNoError;
+    
+    if (in_pipe) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = ccs_os_pipe_compare (in_pipe->os_pipe,
+                                   in_compare_to_os_pipe,
+                                   out_equal);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_pipe_valid (ccs_pipe_t in_pipe)
+{
+    if (in_pipe) {
+        return ccs_os_pipe_valid (in_pipe->os_pipe);
+    } else {
+        return 0;
+    }
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+ccs_os_pipe_t ccs_pipe_os (ccs_pipe_t in_pipe)
+{
+    if (in_pipe) {
+        return in_pipe->os_pipe;
+    } else {
+        return CCS_OS_PIPE_NULL;
+    }
+}
diff --git a/src/ccapi/server/ccs_pipe.h b/src/ccapi/server/ccs_pipe.h
new file mode 100644 (file)
index 0000000..7f3c0d4
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_PIPE_H
+#define CCS_PIPE_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_pipe_new (ccs_pipe_t    *out_pipe,
+                       ccs_os_pipe_t  in_os_pipe);
+
+cc_int32 ccs_pipe_copy (ccs_pipe_t *out_pipe,
+                        ccs_pipe_t  in_pipe);
+
+inline cc_int32 ccs_pipe_release (ccs_pipe_t io_pipe);
+
+cc_int32 ccs_pipe_compare (ccs_pipe_t  in_pipe,
+                           ccs_pipe_t  in_compare_to_pipe,
+                           cc_uint32  *out_equal);
+
+cc_int32 ccs_pipe_compare_to_os_pipe (ccs_pipe_t     in_pipe,
+                                      ccs_os_pipe_t  in_compare_to_os_pipe,
+                                      cc_uint32      *out_equal);
+
+cc_int32 ccs_pipe_valid (ccs_pipe_t in_pipe);
+
+ccs_os_pipe_t ccs_pipe_os (ccs_pipe_t in_pipe);
+
+#endif /* CCS_PIPE_H */
diff --git a/src/ccapi/server/ccs_server.c b/src/ccapi/server/ccs_server.c
new file mode 100644 (file)
index 0000000..b7d3be4
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+#include "ccs_os_server.h"
+
+/* Server Globals: */
+
+cci_uuid_string_t g_server_id = NULL;
+ccs_cache_collection_t g_cache_collection = NULL;
+ccs_pipe_array_t g_client_pipe_array = NULL;
+
+/* ------------------------------------------------------------------------ */
+
+ cc_int32 ccs_server_initialize (void)
+{
+    cc_int32 err = ccNoError;
+
+    if (!err) {
+        err = cci_identifier_new_uuid (&g_server_id);
+    }
+    
+    if (!err) {
+        err = ccs_cache_collection_new (&g_cache_collection);
+    }
+    
+    if (!err) {
+        err = ccs_pipe_array_new (&g_client_pipe_array);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+ cc_int32 ccs_server_cleanup (void)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!err) {
+        free (g_server_id);
+        cci_check_error (ccs_cache_collection_release (g_cache_collection));
+        cci_check_error (ccs_pipe_array_release (g_client_pipe_array));
+    }
+    
+    return cci_check_error (err);    
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_server_new_identifier (cci_identifier_t *out_identifier)
+{
+    return cci_check_error (cci_identifier_new (out_identifier,
+                                                g_server_id));
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_server_add_client (ccs_os_pipe_t in_connection_os_pipe)
+{
+    cc_int32 err = ccNoError;
+    ccs_pipe_t connection_pipe = NULL;
+    
+    if (!err) {
+        err = ccs_pipe_new (&connection_pipe, in_connection_os_pipe);
+    }
+    
+    if (!err) {
+        cci_debug_printf ("%s: Adding client %p.", __FUNCTION__, connection_pipe);
+        err = ccs_pipe_array_insert (g_client_pipe_array, 
+                                     connection_pipe,
+                                     ccs_pipe_array_count (g_client_pipe_array));
+    }
+
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_server_remove_client (ccs_os_pipe_t in_connection_os_pipe)
+{
+    cc_int32 err = ccNoError;
+
+    if (!err) {
+        cc_uint64 i;
+        cc_uint64 count = ccs_pipe_array_count (g_client_pipe_array);
+        cc_uint32 found = 0;
+        
+        for (i = 0; !err && i < count; i++) {
+            ccs_pipe_t client = ccs_pipe_array_object_at_index (g_client_pipe_array, i);
+            
+            err = ccs_pipe_compare_to_os_pipe (client, in_connection_os_pipe, &found);
+            
+            if (!err && found) {
+                cci_debug_printf ("%s: Removing client %p.", __FUNCTION__, client);
+                err = ccs_pipe_array_remove (g_client_pipe_array, i);
+                break;
+            }
+        }
+        
+        if (!err && !found) {
+            cci_debug_printf ("WARNING %s() didn't find client in client list.", 
+                              __FUNCTION__);
+        }        
+    }
+    
+    return cci_check_error (err);    
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_server_request_demux (ccs_pipe_t              in_client_pipe,
+                                          ccs_pipe_t              in_reply_pipe,
+                                          ccs_cache_collection_t  in_cache_collection,
+                                          enum cci_msg_id_t       in_request_name,
+                                          cci_identifier_t        in_request_identifier,
+                                          cci_stream_t            in_request_data,
+                                          cc_uint32              *out_reply_immediately,
+                                          cci_stream_t           *out_reply_data)
+{
+    cc_int32 err = ccNoError;
+
+    if (!ccs_pipe_valid (in_reply_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request_data               ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_reply_immediately         ) { err = cci_check_error (ccErrBadParam); }
+    if (!out_reply_data                ) { err = cci_check_error (ccErrBadParam); }
+
+    if (!err) {
+        if (in_request_name > cci_context_first_msg_id &&
+            in_request_name < cci_context_last_msg_id) {
+            /* Note: context identifier doesn't need to match.  
+             * Client just uses the identifier to detect server relaunch. */
+            
+            if (!err) {
+                err = ccs_cache_collection_handle_message (in_client_pipe,
+                                                           in_reply_pipe,
+                                                           in_cache_collection,
+                                                           in_request_name,
+                                                           in_request_data,
+                                                           out_reply_immediately,
+                                                           out_reply_data);
+            }
+                
+        } else if (in_request_name > cci_ccache_first_msg_id &&
+                   in_request_name < cci_ccache_last_msg_id) {
+            ccs_ccache_t ccache = NULL;
+            
+            err = ccs_cache_collection_find_ccache (in_cache_collection,
+                                                    in_request_identifier,
+                                                    &ccache);            
+            
+            if (!err) {
+                err = ccs_ccache_handle_message (in_client_pipe,
+                                                 in_reply_pipe,
+                                                 ccache,
+                                                 in_cache_collection,
+                                                 in_request_name,
+                                                 in_request_data,
+                                                 out_reply_immediately,
+                                                 out_reply_data);
+            }                
+                        
+        } else if (in_request_name > cci_ccache_iterator_first_msg_id &&
+                   in_request_name < cci_ccache_iterator_last_msg_id) {
+            ccs_ccache_iterator_t ccache_iterator = NULL;
+            
+            err = ccs_cache_collection_find_ccache_iterator (in_cache_collection,
+                                                             in_request_identifier,
+                                                             &ccache_iterator);            
+            
+            if (!err) {
+                err = ccs_ccache_iterator_handle_message (ccache_iterator,
+                                                          in_cache_collection,
+                                                          in_request_name,
+                                                          in_request_data,
+                                                          out_reply_data);
+            }
+            
+            if (!err) {
+                *out_reply_immediately = 1; /* can't block */
+            }
+            
+        } else if (in_request_name > cci_credentials_iterator_first_msg_id &&
+                   in_request_name < cci_credentials_iterator_last_msg_id) {
+            ccs_credentials_iterator_t credentials_iterator = NULL;
+            ccs_ccache_t ccache = NULL;
+            
+            err = ccs_cache_collection_find_credentials_iterator (in_cache_collection,
+                                                                  in_request_identifier,
+                                                                  &ccache,
+                                                                  &credentials_iterator);            
+            
+            if (!err) {
+                err = ccs_credentials_iterator_handle_message (credentials_iterator,
+                                                               ccache,
+                                                               in_request_name,
+                                                               in_request_data,
+                                                               out_reply_data);
+            }
+            
+            if (!err) {
+                *out_reply_immediately = 1; /* can't block */
+            }
+        } else {
+            err = ccErrBadInternalMessage;
+        }
+    }
+    
+    return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_server_handle_request (ccs_pipe_t     in_client_pipe,
+                                    ccs_pipe_t     in_reply_pipe,
+                                    cci_stream_t   in_request)
+{
+    cc_int32 err = ccNoError;
+    enum cci_msg_id_t request_name = 0;
+    cci_identifier_t request_identifier = NULL;
+    cc_uint32 reply_immediately = 1;
+    cci_stream_t reply_data = NULL;
+    
+    if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+    if (!in_request                     ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_message_read_request_header (in_request,
+                                               &request_name,
+                                               &request_identifier);
+    }
+    
+    if (!err) {
+        cc_uint32 server_err = 0;
+        cc_uint32 valid = 0;
+        ccs_cache_collection_t cache_collection = g_cache_collection;
+        
+        server_err = cci_identifier_is_for_server (request_identifier, 
+                                                   g_server_id, 
+                                                   &valid);
+        
+        if (!server_err && !valid) {
+            server_err = cci_message_invalid_object_err (request_name);
+        }
+        
+        if (!server_err) {
+            
+            /* Monolithic server implementation would need to select 
+             * cache collection here.  Currently we only support per-user
+             * servers so we always use the same cache collection. */
+            
+            server_err = ccs_server_request_demux (in_client_pipe,
+                                                   in_reply_pipe,
+                                                   cache_collection,
+                                                   request_name,
+                                                   request_identifier,
+                                                   in_request, 
+                                                   &reply_immediately,
+                                                   &reply_data);
+        }
+        
+        if (server_err || reply_immediately) {
+            err = ccs_server_send_reply (in_reply_pipe, server_err, reply_data);
+        }
+    }
+
+    cci_identifier_release (request_identifier);
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_server_send_reply (ccs_pipe_t     in_reply_pipe,
+                                cc_int32       in_reply_err,
+                                cci_stream_t   in_reply_data)
+{
+    cc_int32 err = ccNoError;
+    cci_stream_t reply = NULL;
+    
+    if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        err = cci_message_new_reply_header (&reply, in_reply_err);
+    }
+    
+    if (!err && in_reply_data && cci_stream_size (in_reply_data) > 0) {
+        err = cci_stream_write (in_reply_data, 
+                                cci_stream_data (in_reply_data), 
+                                cci_stream_size (in_reply_data));
+    }
+    
+    if (!err) {
+        err = ccs_os_server_send_reply (in_reply_pipe, reply);
+    }
+    
+    cci_stream_release (reply);
+    
+    return cci_check_error (err);    
+}
diff --git a/src/ccapi/server/ccs_server.h b/src/ccapi/server/ccs_server.h
new file mode 100644 (file)
index 0000000..7132710
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_SERVER_H
+#define CCS_SERVER_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_server_initialize (void);
+
+cc_int32 ccs_server_cleanup (void);
+
+cc_int32 ccs_server_new_identifier (cci_identifier_t *out_identifier);
+
+cc_int32 ccs_server_add_client (ccs_os_pipe_t in_connection_os_pipe);
+
+cc_int32 ccs_server_remove_client (ccs_os_pipe_t in_connection_os_pipe);
+
+cc_int32 ccs_server_handle_request (ccs_pipe_t     in_client_pipe,
+                                    ccs_pipe_t     in_reply_pipe,
+                                    cci_stream_t   in_request);
+
+cc_int32 ccs_server_send_reply (ccs_pipe_t     in_reply_pipe,
+                                cc_int32       in_reply_err,
+                                cci_stream_t   in_reply_data);
+
+#endif /* CCS_SERVER_H */
diff --git a/src/ccapi/server/ccs_types.h b/src/ccapi/server/ccs_types.h
new file mode 100644 (file)
index 0000000..f96e8d3
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef CCS_TYPES_H
+#define CCS_TYPES_H
+
+#include "cci_types.h"
+
+struct cci_array_d;
+
+typedef struct cci_array_d *ccs_pipe_array_t;
+
+typedef struct cci_array_d *ccs_lock_array_t;
+
+#pragma mark -
+
+/* ccs_os_pipe_t is IPC-specific so it's special cased here */
+
+#if TARGET_OS_MAC
+#include <mach/mach_types.h>
+typedef mach_port_t ccs_os_pipe_t;  /* Mach IPC port */
+#define CCS_OS_PIPE_NULL MACH_PORT_NULL
+
+#else
+typedef int ccs_os_pipe_t; /* Unix domain socket */
+#define CCS_OS_PIPE_NULL -1
+
+#endif
+
+#pragma mark -
+
+struct ccs_pipe_d;
+typedef struct ccs_pipe_d *ccs_pipe_t;
+
+struct ccs_list_d;
+struct ccs_list_iterator_d;
+
+typedef struct ccs_list_d *ccs_cache_collection_list_t;
+
+typedef struct ccs_list_d *ccs_ccache_list_t;
+typedef struct ccs_list_iterator_d *ccs_ccache_list_iterator_t;
+
+typedef struct ccs_list_d *ccs_credentials_list_t;
+typedef struct ccs_list_iterator_d *ccs_credentials_list_iterator_t;
+
+#pragma mark -
+
+struct ccs_client_d;
+typedef struct ccs_client_d *ccs_client_t;
+
+struct ccs_lock_d;
+typedef struct ccs_lock_d *ccs_lock_t;
+
+struct ccs_lock_state_d;
+typedef struct ccs_lock_state_d *ccs_lock_state_t;
+
+struct ccs_credentials_d;
+typedef struct ccs_credentials_d *ccs_credentials_t;
+
+typedef ccs_credentials_list_iterator_t ccs_credentials_iterator_t;
+
+struct ccs_ccache_d;
+typedef struct ccs_ccache_d *ccs_ccache_t;
+
+typedef ccs_ccache_list_iterator_t ccs_ccache_iterator_t;
+
+struct ccs_cache_collection_d;
+typedef struct ccs_cache_collection_d *ccs_cache_collection_t;
+
+#endif /* CCS_TYPES_H */
diff --git a/src/ccapi/server/mac/CCacheServerInfo.plist b/src/ccapi/server/mac/CCacheServerInfo.plist
new file mode 100644 (file)
index 0000000..e03d5f3
--- /dev/null
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>CCacheServer</string>
+       <key>CFBundleGetInfoString</key>
+       <string>4.1</string>
+       <key>CFBundleIconFile</key>
+       <string></string>
+       <key>CFBundleIdentifier</key>
+       <string>edu.mit.Kerberos.CCacheServer</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>Kerberos Credentials Cache Server</string>
+       <key>CFBundlePackageType</key>
+       <string>APPL</string>
+       <key>CFBundleSignature</key>
+       <string>CCSa</string>
+       <key>CFBundleVersion</key>
+       <string>0.0.1d1</string>
+        <key>CFBundleShortVersionString</key>
+        <string>5.5</string>
+        <key>CFBundleGetInfoString</key>
+        <string>5.5 Copyright MIT</string>
+        <key>KfMDisplayVersion</key>
+        <string>5.5 Copyright MIT</string>
+        <key>KfMDisplayCopyright</key>
+        <string>Copyright MIT</string>
+        <key>NSHumanReadableCopyright</key>
+        <string>5.5 Copyright MIT</string>
+       <key>LSBackgroundOnly</key>
+       <string>1</string>
+</dict>
+</plist>
diff --git a/src/ccapi/server/mac/ccs_os_pipe.c b/src/ccapi/server/mac/ccs_os_pipe.c
new file mode 100644 (file)
index 0000000..c3e7542
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+#include "ccs_os_pipe.h"
+#include <mach/port.h>
+
+/* On Mac OS X ccs_os_pipe_t is a mach_port_t */
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_os_pipe_copy (ccs_os_pipe_t *out_pipe,
+                                  ccs_os_pipe_t  in_pipe)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!out_pipe) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_pipe = in_pipe;
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_os_pipe_release (ccs_os_pipe_t io_pipe)
+{
+    return ccNoError;    
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_os_pipe_compare (ccs_os_pipe_t  in_pipe,
+                                     ccs_os_pipe_t  in_compare_to_pipe,
+                                     cc_uint32     *out_equal)
+{
+    cc_int32 err = ccNoError;
+    
+    if (!out_equal) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        *out_equal = (in_pipe == in_compare_to_pipe);
+    }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_os_pipe_valid (ccs_os_pipe_t in_pipe)
+{
+    return MACH_PORT_VALID (in_pipe);
+}
+
diff --git a/src/ccapi/server/mac/edu.mit.Kerberos.CCacheServer.plist b/src/ccapi/server/mac/edu.mit.Kerberos.CCacheServer.plist
new file mode 100644 (file)
index 0000000..42e7f27
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>Label</key>
+        <string>edu.mit.Kerberos.CCacheServer</string>
+        <key>Program</key>
+        <string>/System/Library/CoreServices/CCacheServer.app/Contents/MacOS/CCacheServer</string>
+        <key>MachServices</key>
+        <dict>
+                <key>edu.mit.Kerberos.CCacheServer.ipcService</key>
+                <true/>
+        </dict>
+        <key>OnDemand</key>
+        <true/>
+</dict>
+</plist>
diff --git a/src/ccapi/server/mac/main.c b/src/ccapi/server/mac/main.c
new file mode 100644 (file)
index 0000000..0753a24
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+
+#include <syslog.h>
+#include <Kerberos/kipc_server.h>
+#include "cci_mig_requestServer.h"
+#include "cci_mig_reply.h"
+#include "ccs_os_server.h"
+
+/* ------------------------------------------------------------------------ */
+
+static boolean_t ccs_server_demux (mach_msg_header_t *request, 
+                                   mach_msg_header_t *reply) 
+{
+    boolean_t handled = false;
+    
+    if (!handled) {
+        handled = ccs_server (request, reply);
+    }
+    
+    if (!handled && request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
+        kern_return_t err = KERN_SUCCESS;
+
+        err = ccs_server_remove_client (request->msgh_local_port);
+        
+        if (!err) {
+            /* Check here for a client in our table and free rights associated with it */
+            err = mach_port_mod_refs (mach_task_self (), request->msgh_local_port, 
+                                      MACH_PORT_RIGHT_RECEIVE, -1);
+        }
+        
+        if (!err) {
+            handled = 1;  /* was a port we are tracking */
+        }
+
+        cci_check_error (err);
+    }
+    
+    return handled;    
+}
+
+/* ------------------------------------------------------------------------ */
+
+int main (int argc, const char *argv[])
+{
+    cc_int32 err = 0;
+    
+    openlog (argv[0], LOG_CONS | LOG_PID, LOG_AUTH);
+    syslog (LOG_INFO, "Starting up.");   
+    
+    if (!err) {
+        err = ccs_server_initialize ();
+    }
+    
+    if (!err) {
+        err = kipc_server_run_server (ccs_server_demux);
+    }
+    
+    /* cleanup ccs resources */
+    ccs_server_cleanup ();
+    
+    syslog (LOG_NOTICE, "Exiting: %s (%d)", kipc_error_string (err), err);
+    
+    /* exit */
+    return err ? 1 : 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+kern_return_t ccs_mipc_create_client_connection (mach_port_t    in_server_port,
+                                                 mach_port_t   *out_connection_port)
+{
+    kern_return_t err = KERN_SUCCESS;
+    mach_port_t connection_port = MACH_PORT_NULL;
+    mach_port_t old_notification_target = MACH_PORT_NULL;
+    
+    if (!err) {
+        err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &connection_port);
+    }
+    
+    if (!err) {
+        err = mach_port_move_member (mach_task_self (), connection_port, kipc_server_get_listen_portset ());
+    }
+    
+    if (!err) {
+        /* request no-senders notification so we can tell when client quits/crashes */
+        err = mach_port_request_notification (mach_task_self (), connection_port, 
+                                              MACH_NOTIFY_NO_SENDERS, 1, connection_port, 
+                                              MACH_MSG_TYPE_MAKE_SEND_ONCE, &old_notification_target );
+    }
+    
+    if (!err) {
+        err = ccs_server_add_client (connection_port);
+    }
+    
+    if (!err) {
+        *out_connection_port = connection_port;
+        connection_port = MACH_PORT_NULL;
+    }
+    
+    if (MACH_PORT_VALID (connection_port)) { mach_port_deallocate (mach_task_self (), connection_port); }
+    
+    return cci_check_error (err);    
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_os_server_send_reply (ccs_pipe_t   in_reply_pipe,
+                                   cci_stream_t in_reply_stream)
+{
+    kern_return_t err = KERN_SUCCESS;
+    cci_mipc_inl_reply_t inl_reply;
+    mach_msg_type_number_t inl_reply_length = 0;
+    cci_mipc_ool_reply_t ool_reply = NULL;
+    mach_msg_type_number_t ool_reply_length = 0;
+    
+    if (!ccs_pipe_valid (in_reply_pipe)) { err = cci_check_error (ccErrBadParam); }
+    if (!in_reply_stream               ) { err = cci_check_error (ccErrBadParam); }
+    
+    if (!err) {
+        /* depending on how big the message is, use the fast inline buffer or  
+        * the slow dynamically allocated buffer */
+        mach_msg_type_number_t reply_length = cci_stream_size (in_reply_stream);
+        
+        if (reply_length > kCCAPIMaxILMsgSize) {            
+            cci_debug_printf ("%s choosing out of line buffer (size is %d)", 
+                              __FUNCTION__, reply_length);
+            
+            err = vm_read (mach_task_self (), 
+                           (vm_address_t) cci_stream_data (in_reply_stream), reply_length, 
+                           (vm_address_t *) &ool_reply, &ool_reply_length);
+            
+        } else {
+            //cci_debug_printf ("%s choosing in line buffer (size is %d)",
+            //                  __FUNCTION__, reply_length);
+            
+            inl_reply_length = reply_length;
+            memcpy (inl_reply, cci_stream_data (in_reply_stream), reply_length);
+        }
+    }
+    
+    if (!err) {
+        err = ccs_mipc_reply (ccs_pipe_os (in_reply_pipe), 
+                              inl_reply, inl_reply_length,
+                              ool_reply, ool_reply_length);
+    }
+    
+    if (!err) {
+        /* Because we use ",dealloc" ool_reply will be freed by mach. Don't double free it. */
+        ool_reply = NULL;
+        ool_reply_length = 0;
+    }
+    
+    if (ool_reply_length) { vm_deallocate (mach_task_self (), (vm_address_t) ool_reply, ool_reply_length); }
+    
+    return cci_check_error (err);
+}
+                                     
+
+/* ------------------------------------------------------------------------ */
+
+kern_return_t ccs_mipc_request (mach_port_t             in_connection_port,
+                                mach_port_t             in_reply_port,
+                                cci_mipc_inl_request_t  in_inl_request,
+                                mach_msg_type_number_t  in_inl_requestCnt,
+                                cci_mipc_ool_request_t  in_ool_request,
+                                mach_msg_type_number_t  in_ool_requestCnt)
+{
+    kern_return_t err = KERN_SUCCESS;
+    cci_stream_t request_stream = NULL;
+    ccs_pipe_t connection_pipe = NULL;
+    ccs_pipe_t reply_pipe = NULL;
+    
+    if (!err) {
+        err = cci_stream_new (&request_stream);
+    }
+    
+    if (!err) {
+        if (in_inl_requestCnt) {
+            err = cci_stream_write (request_stream, in_inl_request, in_inl_requestCnt);
+            
+        } else if (in_ool_requestCnt) {
+            err = cci_stream_write (request_stream, in_ool_request, in_ool_requestCnt);
+            
+        } else {
+            err = cci_check_error (ccErrBadInternalMessage);
+        }
+    }
+    
+    if (!err) {
+        err = ccs_pipe_new (&connection_pipe, in_connection_port);
+    }
+    
+    if (!err) {
+        err = ccs_pipe_new (&reply_pipe, in_reply_port);
+    }
+    
+    if (!err) {
+        err = ccs_server_handle_request (connection_pipe, reply_pipe, request_stream);
+    }
+    
+    ccs_pipe_release (connection_pipe);
+    ccs_pipe_release (reply_pipe);
+    cci_stream_release (request_stream);
+    if (in_ool_requestCnt) { vm_deallocate (mach_task_self (), (vm_address_t) in_ool_request, in_ool_requestCnt); }
+    
+    return cci_check_error (err);
+}
diff --git a/src/ccapi/test/Makefile b/src/ccapi/test/Makefile
new file mode 100644 (file)
index 0000000..28d487c
--- /dev/null
@@ -0,0 +1,60 @@
+# run with "make all" to create CCAPI tests in "/tmp/ccapi_test"
+# run resulting tests with "sh test_ccapi.sh"
+
+CC = gcc
+LIBS = -lkrb5
+
+SRCDIR = src
+DSTROOT = /tmp
+OBJDIR = $(DSTROOT)/ccapi_intermediates
+DSTDIR = $(DSTROOT)/ccapi_test
+TESTDIR = $(DSTDIR)/tests
+
+SCRIPT_NAME = test_ccapi.sh
+
+_OBJECTS = test_ccapi_ccache test_ccapi_check test_ccapi_constants test_ccapi_context test_ccapi_globals test_ccapi_iterators test_ccapi_log test_ccapi_util
+
+OBJECTS = $(patsubst %,$(OBJDIR)/%.o,$(_OBJECTS))
+
+TEST_NAMES = test_constants test_cc_initialize test_cc_context_get_version test_cc_context_release test_cc_context_get_change_time test_cc_context_get_default_ccache_name test_cc_context_open_ccache test_cc_context_open_default_ccache test_cc_context_create_ccache test_cc_context_create_default_ccache test_cc_context_create_new_ccache test_cc_context_new_ccache_iterator test_cc_context_compare test_cc_ccache_release test_cc_ccache_destroy test_cc_ccache_set_default test_cc_ccache_get_credentials_version test_cc_ccache_get_name test_cc_ccache_get_principal test_cc_ccache_set_principal test_cc_ccache_store_credentials test_cc_ccache_remove_credentials test_cc_ccache_new_credentials_iterator test_cc_ccache_get_change_time test_cc_ccache_get_last_default_time test_cc_ccache_move test_cc_ccache_compare test_cc_ccache_get_kdc_time_offset test_cc_ccache_set_kdc_time_offset test_cc_ccache_clear_kdc_time_offset test_cc_ccache_iterator_next test_cc_credentials_iterator_next
+
+TEST_OBJECTS = $(patsubst %,$(OBJDIR)/%.o,$(TEST_NAMES))
+
+all: setup-test-dir build-base build-tests link-tests copy-script success-message
+
+# compile base files used by all tests
+build-base: $(OBJECTS)
+
+# compile each test
+build-tests: $(TEST_OBJECTS)
+
+# rule to compile files in src directory
+$(OBJDIR)/%.o: $(SRCDIR)/%.c
+       $(CC) -c -o $@ $<
+
+# Make a build directory
+setup-test-dir:
+       @echo "Removing old destination directory... $(DSTDIR)"
+       if [ -d "$(DSTDIR)" ]; then chmod -R u+w "$(DSTDIR)" && rm -rf "$(DSTDIR)"; fi
+       mkdir -p "$(TESTDIR)"
+       if [ -d "$(OBJDIR)" ]; then chmod -R u+w "$(OBJDIR)" && rm -rf "$(OBJDIR)"; fi
+       mkdir -p "$(OBJDIR)"
+
+link-tests: $(TEST_NAMES)
+
+$(TEST_NAMES): $(TEST_OBJECTS)
+       $(CC) -o $(TESTDIR)/$@ $(OBJDIR)/$@.o $(OBJECTS) $(LIBS)
+
+copy-script:
+       cp $(SRCDIR)/$(SCRIPT_NAME) $(DSTDIR)/$(SCRIPT_NAME)
+
+success-message:
+       @echo
+       @echo "CCAPI tests created in $(DSTDIR)"
+
+.PHONY: clean
+
+clean:
+       -rm -rf "$(OBJDIR)"
+       
+
diff --git a/src/ccapi/test/main.c b/src/ccapi/test/main.c
new file mode 100644 (file)
index 0000000..94176f5
--- /dev/null
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+//     cc_ccache_iterator_t cache_iterator = NULL;
+//     cc_credentials_iterator_t cred_iterator = NULL;
+       
+       fprintf(stdout, "Testing CCAPI against CCAPI v3 rev 8 documentation...\n");
+       fprintf(stdout, "Warning: this test suite is woefully incomplete and unpolished.\n");
+       
+       T_CCAPI_INIT;
+       
+       err = check_constants();
+       
+       // *** cc_context ***
+       err = check_cc_initialize();
+       err = check_cc_context_get_version();
+       err = check_cc_context_release();
+       err = check_cc_context_get_change_time();
+       err = check_cc_context_get_default_ccache_name();
+       err = check_cc_context_open_ccache();
+       err = check_cc_context_open_default_ccache();
+       err = check_cc_context_create_ccache();
+       err = check_cc_context_create_default_ccache();
+       err = check_cc_context_create_new_ccache();
+       err = check_cc_context_new_ccache_iterator();
+       // err = check_cc_context_lock();
+       // err = check_cc_context_unlock();
+       err = check_cc_context_compare();
+       
+       // *** cc_ccache ***
+       err = check_cc_ccache_release();
+       err = check_cc_ccache_destroy();
+       err = check_cc_ccache_set_default();
+       err = check_cc_ccache_get_credentials_version();
+       err = check_cc_ccache_get_name();
+       err = check_cc_ccache_get_principal();
+       err = check_cc_ccache_set_principal();
+       err = check_cc_ccache_store_credentials();
+       err = check_cc_ccache_remove_credentials();
+       err = check_cc_ccache_new_credentials_iterator();
+       // err = check_cc_ccache_lock();
+       // err = check_cc_ccache_unlock();
+       err = check_cc_ccache_get_change_time();
+       err = check_cc_ccache_get_last_default_time();
+       err = check_cc_ccache_move();
+       err = check_cc_ccache_compare();
+       err = check_cc_ccache_get_kdc_time_offset();
+       err = check_cc_ccache_set_kdc_time_offset();
+       err = check_cc_ccache_clear_kdc_time_offset();
+       
+       // *** cc_ccache_iterator ***
+       err = check_cc_ccache_iterator_next();
+       
+       // *** cc_credentials_iterator ***
+       err = check_cc_credentials_iterator_next();
+       
+       fprintf(stdout, "\nFinished testing CCAPI. %d failure%s in total.\n", total_failure_count, (total_failure_count == 1) ? "" : "s");
+       
+    return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c b/src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c
new file mode 100644 (file)
index 0000000..ea63007
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_clear_kdc_time_offset();
+    return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_compare.c b/src/ccapi/test/test_cc_ccache_compare.c
new file mode 100644 (file)
index 0000000..aec606b
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_compare();
+    return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_destroy.c b/src/ccapi/test/test_cc_ccache_destroy.c
new file mode 100644 (file)
index 0000000..ee589e2
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_destroy();
+    return err;
+}
diff --git a/src/ccapi/test/test_cc_ccache_get_change_time.c b/src/ccapi/test/test_cc_ccache_get_change_time.c
new file mode 100644 (file)
index 0000000..44d4c2c
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_get_change_time();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_ccache_get_credentials_version.c b/src/ccapi/test/test_cc_ccache_get_credentials_version.c
new file mode 100644 (file)
index 0000000..4f16c9d
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_get_credentials_version();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c b/src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c
new file mode 100644 (file)
index 0000000..f3591a3
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_get_kdc_time_offset();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_ccache_get_last_default_time.c b/src/ccapi/test/test_cc_ccache_get_last_default_time.c
new file mode 100644 (file)
index 0000000..a2c9e25
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_get_last_default_time();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_ccache_get_name.c b/src/ccapi/test/test_cc_ccache_get_name.c
new file mode 100644 (file)
index 0000000..749bd93
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_get_name();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_ccache_get_principal.c b/src/ccapi/test/test_cc_ccache_get_principal.c
new file mode 100644 (file)
index 0000000..8ab935c
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_get_principal();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_ccache_iterator_next.c b/src/ccapi/test/test_cc_ccache_iterator_next.c
new file mode 100644 (file)
index 0000000..8e124e5
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_iterator_next();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_ccache_move.c b/src/ccapi/test/test_cc_ccache_move.c
new file mode 100644 (file)
index 0000000..49790e4
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_move();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_ccache_new_credentials_iterator.c b/src/ccapi/test/test_cc_ccache_new_credentials_iterator.c
new file mode 100644 (file)
index 0000000..fc1acbf
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_new_credentials_iterator();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_ccache_release.c b/src/ccapi/test/test_cc_ccache_release.c
new file mode 100644 (file)
index 0000000..1cd2d91
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_release();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_ccache_remove_credentials.c b/src/ccapi/test/test_cc_ccache_remove_credentials.c
new file mode 100644 (file)
index 0000000..00fe8c1
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_remove_credentials();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_ccache_set_default.c b/src/ccapi/test/test_cc_ccache_set_default.c
new file mode 100644 (file)
index 0000000..40d9bbd
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_set_default();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c b/src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c
new file mode 100644 (file)
index 0000000..f8f9a86
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_set_kdc_time_offset();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_ccache_set_principal.c b/src/ccapi/test/test_cc_ccache_set_principal.c
new file mode 100644 (file)
index 0000000..b9b5230
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_set_principal();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_ccache_store_credentials.c b/src/ccapi/test/test_cc_ccache_store_credentials.c
new file mode 100644 (file)
index 0000000..0676d4d
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_ccache_store_credentials();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_context_compare.c b/src/ccapi/test/test_cc_context_compare.c
new file mode 100644 (file)
index 0000000..6155618
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_context_compare();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_context_create_ccache.c b/src/ccapi/test/test_cc_context_create_ccache.c
new file mode 100644 (file)
index 0000000..dd65a53
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_context_create_ccache();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_context_create_default_ccache.c b/src/ccapi/test/test_cc_context_create_default_ccache.c
new file mode 100644 (file)
index 0000000..b7ef872
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_context_create_default_ccache();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_context_create_new_ccache.c b/src/ccapi/test/test_cc_context_create_new_ccache.c
new file mode 100644 (file)
index 0000000..b460f3a
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_context_create_new_ccache();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_context_get_change_time.c b/src/ccapi/test/test_cc_context_get_change_time.c
new file mode 100644 (file)
index 0000000..e6e6018
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_context_get_change_time();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_context_get_default_ccache_name.c b/src/ccapi/test/test_cc_context_get_default_ccache_name.c
new file mode 100644 (file)
index 0000000..a0514af
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_context_get_default_ccache_name();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_context_get_version.c b/src/ccapi/test/test_cc_context_get_version.c
new file mode 100644 (file)
index 0000000..f3ea8b9
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_context_get_version();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_context_new_ccache_iterator.c b/src/ccapi/test/test_cc_context_new_ccache_iterator.c
new file mode 100644 (file)
index 0000000..7f89376
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_context_new_ccache_iterator();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_context_open_ccache.c b/src/ccapi/test/test_cc_context_open_ccache.c
new file mode 100644 (file)
index 0000000..7212402
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_context_open_ccache();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_context_open_default_ccache.c b/src/ccapi/test/test_cc_context_open_default_ccache.c
new file mode 100644 (file)
index 0000000..00e0afd
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_context_open_default_ccache();
+    return err;
+}
+       
\ No newline at end of file
diff --git a/src/ccapi/test/test_cc_context_release.c b/src/ccapi/test/test_cc_context_release.c
new file mode 100644 (file)
index 0000000..5d7d49c
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_context_release();
+    return err;
+}
diff --git a/src/ccapi/test/test_cc_credentials_iterator_next.c b/src/ccapi/test/test_cc_credentials_iterator_next.c
new file mode 100644 (file)
index 0000000..f66a2f7
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_credentials_iterator_next();
+    return err;
+}
diff --git a/src/ccapi/test/test_cc_initialize.c b/src/ccapi/test/test_cc_initialize.c
new file mode 100644 (file)
index 0000000..47eeb36
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_cc_initialize();
+    return err;
+}
diff --git a/src/ccapi/test/test_ccapi_ccache.c b/src/ccapi/test/test_ccapi_ccache.c
new file mode 100644 (file)
index 0000000..cba481c
--- /dev/null
@@ -0,0 +1,2025 @@
+#include "test_ccapi_ccache.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include "test_ccapi_check.h"
+#include "test_ccapi_util.h"
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_release() {
+       BEGIN_TEST("cc_ccache_release");
+       
+       #ifndef cc_ccache_release
+       log_error("cc_ccache_release is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+       
+       
+       
+       if (!err) {
+               check_once_cc_ccache_release(context, ccache, ccNoError, NULL);
+               ccache = NULL;
+       }
+       
+       if (context) { cc_context_release(context); }
+       
+       #endif /* cc_ccache_release */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_release(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_ccache_release
+       
+       cc_int32 possible_return_values[2] = {
+               ccNoError, 
+               ccErrInvalidCCache, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_string_t name = NULL;
+       
+       err = cc_ccache_get_name(ccache, &name);
+       err = cc_ccache_release(ccache);
+       ccache = NULL;
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err && name) { // try opening released ccache to make sure it still exists
+               err = cc_context_open_ccache(context, name->data, &ccache);
+       }
+       check_if(err == ccErrCCacheNotFound, "released ccache was actually destroyed instead");
+       
+       if (ccache) { cc_ccache_destroy(ccache); }
+       if (name) { cc_string_release(name); }
+       
+       #endif /* cc_ccache_release */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_destroy() {
+       BEGIN_TEST("cc_ccache_destroy");
+       
+       #ifndef cc_ccache_destroy
+       log_error("cc_ccache_destroy is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+       
+       
+       
+       if (!err) {
+               check_once_cc_ccache_destroy(context, ccache, ccNoError, NULL);
+               ccache = NULL;
+       }
+               
+       if (context) { cc_context_release(context); }
+       
+       #endif /* cc_ccache_destroy */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_destroy(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_ccache_destroy
+       
+       cc_int32 possible_return_values[2] = {
+               ccNoError, 
+               ccErrInvalidCCache, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_string_t name = NULL;
+       
+       err = cc_ccache_get_name(ccache, &name);
+       err = cc_ccache_destroy(ccache);
+       ccache = NULL;
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err && name) { // try opening released ccache to make sure it still exists
+               err = cc_context_open_ccache(context, name->data, &ccache);
+       }
+       check_if(err != ccErrCCacheNotFound, "destroyed ccache was actually released instead");
+       
+       if (ccache) { cc_ccache_destroy(ccache); }
+       if (name) { cc_string_release(name); }
+       
+       #endif /* cc_ccache_destroy */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_set_default() {
+       BEGIN_TEST("cc_ccache_set_default");
+       
+       #ifndef cc_ccache_set_default
+       log_error("cc_ccache_set_default is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       // try when it's the only ccache (already default)
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+       if (!err) {
+               check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's the only ccache (already default)");
+       }
+       if (ccache) {
+               err = cc_ccache_release(ccache);
+               ccache = NULL;
+       }
+       
+       // try when it's not the only ccache (and not default)
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "baz@BAR.ORG", &ccache);
+       }
+       if (!err) {
+               check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's not the only ccache (and not default)");
+       }
+       if (ccache) {
+               err = cc_ccache_release(ccache);
+               ccache = NULL;
+       }
+       
+       // try when it's not the only ccache (and already default)      
+       if (!err) {
+               err = cc_context_open_default_ccache(context, &ccache);
+       }
+       if (!err) {
+               check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's not the only ccache (and already default)");
+       }
+       if (ccache) {
+               err = cc_ccache_release(ccache);
+               ccache = NULL;
+       }
+                       
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       
+       if (context) { cc_context_release(context); }
+       
+       #endif /* cc_ccache_set_default */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_set_default(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_ccache_set_default
+       
+       cc_int32 possible_return_values[3] = {
+               ccNoError, 
+               ccErrInvalidCCache, 
+               ccErrCCacheNotFound, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_ccache_t default_ccache = NULL;
+       cc_string_t name = NULL;
+       cc_string_t default_name = NULL;
+       
+       err = cc_ccache_set_default(ccache);
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err) {
+               err = cc_ccache_get_name(ccache, &name);
+       }
+       if (!err) {
+               err = cc_context_open_default_ccache(context, &default_ccache);
+       }
+       if (!err) {
+               err = cc_ccache_get_name(default_ccache, &default_name);
+       }
+       if (name && default_name) {
+               check_if(strcmp(name->data, default_name->data), NULL);
+       }
+       else {
+               check_if(1, "cc_ccache_get_name failed");
+       }
+               
+       if (default_ccache) { cc_ccache_release(default_ccache); }
+       //if (ccache) { cc_ccache_destroy(ccache); } // ccache is released by the caller
+       if (default_name) { cc_string_release(default_name); }
+       if (name) { cc_string_release(name); }
+       
+       #endif /* cc_ccache_set_default */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_get_credentials_version() {
+       BEGIN_TEST("cc_ccache_get_credentials_version");
+       
+       #ifndef cc_ccache_get_credentials_version
+       log_error("cc_ccache_get_credentials_version is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       // try one created with v5 creds
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+       if (!err) {
+               check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v5, ccNoError, "v5 creds");
+       }
+       else {
+               log_error("cc_context_create_new_ccache failed, can't complete test");
+               failure_count++;
+       }
+       
+       // try it with added v4 creds
+       if (!err) {
+               err = cc_ccache_set_principal(ccache, cc_credentials_v4, "foo@BAR.ORG");
+       }
+       if (!err) {
+               check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v4_v5, ccNoError, "v5 with v4 creds added");
+       }
+       else {
+               log_error("cc_ccache_set_principal failed, can't complete test");
+               failure_count++;
+       }
+       
+       if (ccache) {
+               cc_ccache_destroy(ccache);
+               ccache = NULL;
+       }
+       
+       err = ccNoError;
+       
+       // try one created with v4 creds
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo@BAR.ORG", &ccache);
+       }
+       if (!err) {
+               check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v4, ccNoError, "v4 creds");
+       }
+       else {
+               log_error("cc_context_create_new_ccache failed, can't complete test");
+               failure_count++;
+       }
+       
+       // try it with added v5 creds
+       if (!err) {
+               err = cc_ccache_set_principal(ccache, cc_credentials_v5, "foo@BAR.ORG");
+       }
+       if (!err) {
+               check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v4_v5, ccNoError, "v4 with v5 creds added");
+       }       
+       else {
+               log_error("cc_ccache_set_principal failed, can't complete test");
+               failure_count++;
+       }
+       
+       if (ccache) {
+               cc_ccache_destroy(ccache);
+               ccache = NULL;
+       }
+       
+       if (context) { cc_context_release(context); }
+       
+       #endif /* cc_ccache_get_credentials_version */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_get_credentials_version(cc_ccache_t ccache, cc_uint32 expected_cred_vers, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_ccache_get_credentials_version
+       
+       cc_int32 possible_return_values[4] = {
+               ccNoError, 
+               ccErrInvalidCCache, 
+               ccErrBadParam, 
+               ccErrCCacheNotFound, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_uint32 stored_cred_vers = 0;
+       
+       err = cc_ccache_get_credentials_version(ccache, &stored_cred_vers);
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err) {
+               check_if(stored_cred_vers != expected_cred_vers, NULL);
+       }
+       
+       #endif /* cc_ccache_get_credentials_version */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_get_name() {
+       BEGIN_TEST("cc_ccache_get_name");
+       
+       #ifndef cc_ccache_get_name
+       log_error("cc_ccache_get_name is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       
+       // try with unique ccache (which happens to be default)
+       if (!err) {
+               err = cc_context_create_ccache(context, "0", cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+       if (!err) {
+               check_once_cc_ccache_get_name(ccache, "0", ccNoError, "unique ccache (which happens to be default)");
+       }
+       else {
+               log_error("cc_context_create_ccache failed, can't complete test");
+               failure_count++;
+       }       
+       if (ccache) {
+               cc_ccache_release(ccache);
+               ccache = NULL;
+       }
+       
+       // try with unique ccache (which is not default)
+       if (!err) {
+               err = cc_context_create_ccache(context, "1", cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+       if (!err) {
+               check_once_cc_ccache_get_name(ccache, "1", ccNoError, "unique ccache (which is not default)");
+       }
+       else {
+               log_error("cc_context_create_ccache failed, can't complete test");
+               failure_count++;
+       }
+       
+       // try with bad param
+       if (!err) {
+               check_once_cc_ccache_get_name(ccache, NULL, ccErrBadParam, "NULL param");
+       }
+       if (ccache) {
+               cc_ccache_release(ccache);
+               ccache = NULL;
+       }
+       
+       if (context) { 
+               err = destroy_all_ccaches(context);
+               cc_context_release(context);
+       }
+       
+       #endif /* cc_ccache_get_name */
+       
+       END_TEST_AND_RETURN     
+}
+
+cc_int32 check_once_cc_ccache_get_name(cc_ccache_t ccache, const char *expected_name, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_ccache_get_name
+       
+       cc_int32 possible_return_values[4] = {
+               ccNoError, 
+               ccErrInvalidCCache, 
+               ccErrBadParam, 
+               ccErrCCacheNotFound, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_string_t stored_name = NULL;
+       
+       if (expected_name == NULL) { // we want to try with a NULL param
+               err = cc_ccache_get_name(ccache, NULL);
+       }
+       else {
+               err = cc_ccache_get_name(ccache, &stored_name);
+       }
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err) {
+               check_if(strcmp(stored_name->data, expected_name), NULL);
+       }
+       
+       if (stored_name) { cc_string_release(stored_name); }
+       
+       #endif /* cc_ccache_get_name */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_get_principal() {
+       BEGIN_TEST("cc_ccache_get_principal");
+       
+       #ifndef cc_ccache_get_principal
+       log_error("cc_ccache_get_principal is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       
+       // try with krb5 principal
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo/BAR@BAZ.ORG", &ccache);
+       }
+       if (!err) {
+               check_once_cc_ccache_get_principal(ccache, cc_credentials_v5, "foo/BAR@BAZ.ORG", ccNoError);
+       }
+       else {
+               log_error("cc_context_create_new_ccache failed, can't complete test");
+               failure_count++;
+       }
+       if (ccache) {
+               cc_ccache_release(ccache);
+               ccache = NULL;
+       }
+       
+       // try with krb4 principal
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo.BAR@BAZ.ORG", &ccache);
+       }
+       if (!err) {
+               check_once_cc_ccache_get_principal(ccache, cc_credentials_v4, "foo.BAR@BAZ.ORG", ccNoError);
+       }
+       else {
+               log_error("cc_context_create_new_ccache failed, can't complete test");
+               failure_count++;
+       }
+       
+       // try with bad param
+       if (!err) {
+               // cc_ccache_t doesn't have any concept of the difference between a v4 and v5 principal
+               check_once_cc_ccache_get_principal(ccache, cc_credentials_v4_v5, "foo.BAR@BAZ.ORG", 
+                       ccErrBadCredentialsVersion,
+                       "passing cc_credentials_v4_v5 (shouldn't be allowed)");
+               check_once_cc_ccache_get_principal(ccache, cc_credentials_v5, NULL, ccErrBadParam);
+       }
+       
+       if (ccache) {
+               cc_ccache_release(ccache);
+               ccache = NULL;
+       }
+       
+       if (context) { 
+               err = destroy_all_ccaches(context);
+               cc_context_release(context);
+       }
+       
+       #endif /* cc_ccache_get_principal */
+       
+       END_TEST_AND_RETURN     
+}
+
+cc_int32 check_once_cc_ccache_get_principal(cc_ccache_t ccache, cc_uint32 cred_vers, const char *expected_principal, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_ccache_get_principal
+       
+       cc_int32 possible_return_values[6] = {
+               ccNoError, 
+               ccErrNoMem, 
+               ccErrBadCredentialsVersion, 
+               ccErrBadParam, 
+               ccErrInvalidCCache, 
+               ccErrCCacheNotFound, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_string_t stored_principal = NULL;
+       
+       if (expected_principal == NULL) { // we want to try with a NULL param
+               err = cc_ccache_get_principal(ccache, cred_vers, NULL);
+       }
+       else {
+               err = cc_ccache_get_principal(ccache, cred_vers, &stored_principal);
+       }
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err) {
+               check_if(strcmp(stored_principal->data, expected_principal), "expected princ == \"%s\" stored princ == \"%s\"", expected_principal, stored_principal->data);
+       }
+       
+       if (stored_principal) { cc_string_release(stored_principal); }
+       
+       #endif /* cc_ccache_get_principal */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_set_principal() {
+       BEGIN_TEST("cc_ccache_set_principal");
+       
+       #ifndef cc_ccache_set_principal
+       log_error("cc_ccache_set_principal is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       
+       // bad params
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache);
+       }
+       if (!err) {
+               check_once_cc_ccache_set_principal(ccache, cc_credentials_v4_v5, "foo/BAZ@BAR.ORG", ccErrBadCredentialsVersion, "cc_credentials_v4_v5 (not allowed)");
+               check_once_cc_ccache_set_principal(ccache, cc_credentials_v5, NULL, ccErrBadParam, "NULL principal");
+       }
+       else {
+               log_error("cc_context_create_new_ccache failed, can't complete test");
+               failure_count++;
+       }
+       if (ccache) {
+               cc_ccache_destroy(ccache);
+               ccache = NULL;
+       }
+       
+
+       // empty ccache
+
+               // replace v5 only ccache's principal
+               if (!err) {
+                       err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache);
+               }
+               if (!err) {
+                       check_once_cc_ccache_set_principal(ccache, cc_credentials_v5, "foo/BAZ@BAR.ORG", ccNoError, "replace v5 only ccache's principal (empty ccache)");
+               }
+               else {
+                       log_error("cc_context_create_new_ccache failed, can't complete test");
+                       failure_count++;
+               }
+               if (ccache) {
+                       cc_ccache_destroy(ccache);
+                       ccache = NULL;
+               }
+               
+               // add v4 principal to v5 only ccache
+               if (!err) {
+                       err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache);
+               }
+               if (!err) {
+                       check_once_cc_ccache_set_principal(ccache, cc_credentials_v4, "foo.BAZ@BAR.ORG", ccNoError, "add v4 principal to v5 only ccache (empty ccache)");
+               }
+               else {
+                       log_error("cc_context_create_new_ccache failed, can't complete test");
+                       failure_count++;
+               }
+               if (ccache) {
+                       cc_ccache_destroy(ccache);
+                       ccache = NULL;
+               }
+
+               // replace v4 only ccache's principal
+               if (!err) {
+                       err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo@BAZ.ORG", &ccache);
+               }
+               if (!err) {
+                       check_once_cc_ccache_set_principal(ccache, cc_credentials_v4, "foo.BAZ@BAR.ORG", ccNoError, "replace v4 only ccache's principal (empty ccache)");
+               }
+               else {
+                       log_error("cc_context_create_new_ccache failed, can't complete test");
+                       failure_count++;
+               }
+               if (ccache) {
+                       cc_ccache_destroy(ccache);
+                       ccache = NULL;
+               }
+               
+               // add v5 principal to v4 only ccache
+               if (!err) {
+                       err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo@BAZ.ORG", &ccache);
+               }
+               if (!err) {
+                       check_once_cc_ccache_set_principal(ccache, cc_credentials_v5, "foo/BAZ@BAR.ORG", ccNoError, "add v5 principal to v4 only ccache (empty ccache)");
+               }
+               else {
+                       log_error("cc_context_create_new_ccache failed, can't complete test");
+                       failure_count++;
+               }
+               if (ccache) {
+                       cc_ccache_destroy(ccache);
+                       ccache = NULL;
+               }
+               
+       // with credentials
+       
+               // replace v5 only ccache's principal
+               
+               // add v4 principal to v5 only ccache
+
+               // replace v4 only ccache's principal
+               
+               // add v5 principal to v4 only ccache
+       
+       if (context) { 
+               err = destroy_all_ccaches(context);
+               cc_context_release(context);
+       }
+       
+       #endif /* cc_ccache_set_principal */
+       
+       END_TEST_AND_RETURN     
+}
+
+cc_int32 check_once_cc_ccache_set_principal(cc_ccache_t ccache, cc_uint32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_ccache_set_principal
+       
+       cc_int32 possible_return_values[6] = {
+               ccNoError, 
+               ccErrNoMem, 
+               ccErrInvalidCCache, 
+               ccErrBadCredentialsVersion, 
+               ccErrBadParam, 
+               ccErrCCacheNotFound, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_string_t stored_principal = NULL;
+       
+       err = cc_ccache_set_principal(ccache, cred_vers, in_principal);
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err) {
+               err = cc_ccache_get_principal(ccache, cred_vers, &stored_principal);
+       }
+       
+       // compare stored with input
+       if (!err) {
+               check_if(strcmp(stored_principal->data, in_principal), "expected princ == \"%s\" stored princ == \"%s\"", in_principal, stored_principal->data);
+       }
+       
+       if (stored_principal) { cc_string_release(stored_principal); }
+       
+       #endif /* cc_ccache_set_principal */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_store_credentials() {
+       BEGIN_TEST("cc_ccache_store_credentials");
+       
+       #ifndef cc_ccache_store_credentials
+       log_error("cc_ccache_store_credentials is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       cc_ccache_t dup_ccache = NULL;
+       cc_credentials_union creds_union;
+       cc_string_t name = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+
+       // cred with matching version and realm
+       if (!err) {
+               err = new_v5_creds_union(&creds_union, "BAR.ORG");
+       }
+       
+       if (!err) {
+               check_once_cc_ccache_store_credentials(ccache, &creds_union, ccNoError, "ok creds");
+       }
+       
+       if (&creds_union) { release_v5_creds_union(&creds_union); }
+       
+       // try with bad params
+       check_once_cc_ccache_store_credentials(ccache, NULL, ccErrInvalidCredentials, "NULL creds param");
+       
+       // invalid creds
+       if (!err) {
+               err = new_v5_creds_union(&creds_union, "BAR.ORG");
+       }
+       
+       if (!err) {
+               if (creds_union.credentials.credentials_v5->client) {
+                       free(creds_union.credentials.credentials_v5->client);
+                       creds_union.credentials.credentials_v5->client = NULL;
+               }
+               check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrInvalidCredentials, "invalid creds (NULL client string)");
+       }
+       
+       if (&creds_union) { release_v5_creds_union(&creds_union); }
+       
+       // bad creds version
+       if (!err) {
+               err = new_v5_creds_union(&creds_union, "BAR.ORG");
+       }
+       
+       if (!err) {
+               creds_union.version = cc_credentials_v4_v5;
+               check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrBadCredentialsVersion, "v4_v5 creds (invalid) into a ccache with only v5 princ");
+               creds_union.version = cc_credentials_v4;
+               check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrBadCredentialsVersion, "v4 creds into a ccache with only v5 princ");
+               creds_union.version = cc_credentials_v5;
+       }
+       
+       if (&creds_union) { release_v5_creds_union(&creds_union); }
+       
+       // non-existent ccache
+       if (ccache) { 
+               err = cc_ccache_get_name(ccache, &name);
+               if (!err) {
+                       err = cc_context_open_ccache(context, name->data, &dup_ccache);
+               }
+               if (name) { cc_string_release(name); }
+               if (dup_ccache) { cc_ccache_destroy(dup_ccache); }
+       }
+       
+       if (!err) {
+               err = new_v5_creds_union(&creds_union, "BAR.ORG");
+       }
+       
+       if (!err) {
+               check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrInvalidCCache, "invalid ccache");
+       }
+       
+       if (&creds_union) { release_v5_creds_union(&creds_union); }
+       if (ccache) { cc_ccache_release(ccache); }
+       if (context) { 
+               destroy_all_ccaches(context);
+               cc_context_release(context);
+       }
+       
+       #endif /* cc_ccache_store_credentials */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_store_credentials(cc_ccache_t ccache, const cc_credentials_union *credentials, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_ccache_store_credentials
+       
+       cc_int32 possible_return_values[5] = {
+               ccNoError, 
+               ccErrInvalidCCache, 
+               ccErrInvalidCredentials, 
+               ccErrBadCredentialsVersion, 
+               ccErrCCacheNotFound, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_credentials_iterator_t creds_iterator = NULL;
+       cc_credentials_t creds = NULL;
+       
+       err = cc_ccache_store_credentials(ccache, credentials);
+               
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       // make sure credentials were truly stored
+       if (!err) {
+               err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator);
+       }
+       while (!err) {
+               err = cc_credentials_iterator_next(creds_iterator, &creds);
+               if (creds) {
+                       if (compare_v5_creds_unions(credentials, creds->data) == 0) {
+                               break;
+                       }
+                       cc_credentials_release(creds);
+                       creds = NULL;                   
+               }
+       }
+       
+       if (err == ccIteratorEnd) { 
+               check_if((creds != NULL), "stored credentials not found in ccache");
+               err = ccNoError;
+       }
+       if (creds) { cc_credentials_release(creds); }
+       
+       #endif /* cc_ccache_store_credentials */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_remove_credentials() {
+       BEGIN_TEST("cc_ccache_remove_credentials");
+       
+       #ifndef cc_ccache_remove_credentials
+       log_error("cc_ccache_remove_credentials is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       cc_ccache_t dup_ccache = NULL;
+       cc_credentials_t creds_array[10];
+       cc_credentials_t creds = NULL;
+       cc_credentials_union creds_union;
+       cc_credentials_iterator_t creds_iterator = NULL;
+       cc_string_t name = NULL;
+       unsigned int i;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+       
+       // store 10 creds and retrieve their cc_credentials_t representations
+       for(i = 0; !err && (i < 10); i++) {
+               new_v5_creds_union(&creds_union, "BAR.ORG");
+               err = cc_ccache_store_credentials(ccache, &creds_union);
+               if (&creds_union) { release_v5_creds_union(&creds_union); }
+       }
+       if (err) {
+               log_error("failure to store creds_union in remove_creds test");
+       }
+       if (!err) {
+               err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator);
+       }
+       i = 0;
+       while (!err && i < 10) {
+               err = cc_credentials_iterator_next(creds_iterator, &creds);
+               if (creds) {
+                       creds_array[i++] = creds;
+                       creds = NULL;
+               }
+       }
+       if (err == ccIteratorEnd) { err = ccNoError; }
+       
+       // remove 10 valid creds
+       for (i = 0; !err && (i < 8); i++) {
+               check_once_cc_ccache_remove_credentials(ccache, creds_array[i], ccNoError, "10 ok creds");
+       }
+
+       // NULL param
+       check_once_cc_ccache_remove_credentials(ccache, NULL, ccErrInvalidCredentials, "NULL creds in param");
+       
+       // non-existent creds (remove same one twice)
+       check_once_cc_ccache_remove_credentials(ccache, creds_array[0], ccErrCredentialsNotFound, "removed same creds twice");
+       
+       // non-existent ccache
+       if (ccache) { 
+               err = cc_ccache_get_name(ccache, &name);
+               if (!err) {
+                       err = cc_context_open_ccache(context, name->data, &dup_ccache);
+               }
+               if (name) { cc_string_release(name); }
+               if (dup_ccache) { cc_ccache_destroy(dup_ccache); }
+       }
+       
+       if (!err) {
+               err = new_v5_creds_union(&creds_union, "BAR.ORG");
+       }
+       
+       if (!err) {
+               check_once_cc_ccache_remove_credentials(ccache, creds_array[8], ccErrInvalidCCache, "invalid ccache");
+       }
+
+       for(i = 0; i < 10; i++) {
+               if (creds_array[i]) { cc_credentials_release(creds_array[i]); }
+       }
+
+       if (ccache) { cc_ccache_release(ccache); }
+       if (context) { 
+               destroy_all_ccaches(context);
+               cc_context_release(context);
+       }
+       
+       #endif /* cc_ccache_remove_credentials */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_remove_credentials(cc_ccache_t ccache, cc_credentials_t in_creds, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_ccache_remove_credentials
+       
+       cc_int32 possible_return_values[5] = {
+               ccNoError, 
+               ccErrInvalidCCache, 
+               ccErrInvalidCredentials, 
+               ccErrCredentialsNotFound, 
+               ccErrCCacheNotFound,
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_credentials_iterator_t creds_iterator = NULL;
+       cc_credentials_t creds = NULL;
+       
+       err = cc_ccache_remove_credentials(ccache, in_creds);
+               
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       // make sure credentials were truly removed
+       if (!err) {
+               err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator);
+       }
+       while (!err) {
+               err = cc_credentials_iterator_next(creds_iterator, &creds);
+               if (creds) {
+                       if (compare_v5_creds_unions(in_creds->data, creds->data) == 0) {
+                               break;
+                       }
+                       cc_credentials_release(creds);
+                       creds = NULL;                   
+               }
+       }
+       
+       if (err == ccIteratorEnd) { 
+               err = ccNoError;
+       }
+       else {
+               check_if((creds != NULL), "credentials not removed from ccache");
+       }
+       if (creds) { cc_credentials_release(creds); }
+       
+       #endif /* cc_ccache_remove_credentials */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_new_credentials_iterator() {
+       BEGIN_TEST("cc_ccache_new_credentials_iterator");
+       
+       #ifndef cc_ccache_new_credentials_iterator
+       log_error("cc_ccache_new_credentials_iterator is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       cc_ccache_t dup_ccache = NULL;
+       cc_credentials_iterator_t creds_iterator = NULL;
+       cc_string_t name = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+       
+       // valid params
+       if (!err) {
+               check_once_cc_ccache_new_credentials_iterator(ccache, &creds_iterator, ccNoError, "valid params");
+       }
+       if (creds_iterator) { 
+               cc_credentials_iterator_release(creds_iterator); 
+               creds_iterator = NULL;
+       }
+       
+       // NULL out param
+       if (!err) {
+               check_once_cc_ccache_new_credentials_iterator(ccache, NULL, ccErrBadParam, "NULL out iterator param");
+       }
+       if (creds_iterator) { 
+               cc_credentials_iterator_release(creds_iterator); 
+               creds_iterator = NULL;
+       }
+       
+       // non-existent ccache
+       if (ccache) { 
+               err = cc_ccache_get_name(ccache, &name);
+               if (!err) {
+                       err = cc_context_open_ccache(context, name->data, &dup_ccache);
+               }
+               if (name) { cc_string_release(name); }
+               if (dup_ccache) { cc_ccache_destroy(dup_ccache); }
+       }
+       
+       if (!err) {
+               check_once_cc_ccache_new_credentials_iterator(ccache, &creds_iterator, ccErrCCacheNotFound, "invalid ccache");
+       }
+       
+       if (creds_iterator) { 
+               cc_credentials_iterator_release(creds_iterator); 
+               creds_iterator = NULL;
+       }
+       if (ccache) { cc_ccache_release(ccache); }
+       if (context) { 
+               destroy_all_ccaches(context);
+               cc_context_release(context);
+       }
+       
+       #endif /* cc_ccache_new_credentials_iterator */
+       
+       END_TEST_AND_RETURN
+}
+
+
+cc_int32 check_once_cc_ccache_new_credentials_iterator(cc_ccache_t ccache, cc_credentials_iterator_t *iterator, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_ccache_new_credentials_iterator
+       
+       cc_int32 possible_return_values[4] = {
+               ccNoError, 
+               ccErrBadParam, 
+               ccErrNoMem, 
+               ccErrCCacheNotFound, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       err = cc_ccache_new_credentials_iterator(ccache, iterator);
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       #endif /* cc_ccache_new_credentials_iterator */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_get_change_time() {
+       BEGIN_TEST("cc_ccache_get_change_time");
+       
+       #ifndef cc_ccache_get_change_time
+       log_error("cc_ccache_get_change_time is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t dummy_ccache = NULL;
+       cc_ccache_t ccache = NULL;
+       cc_credentials_union creds_union;
+       cc_credentials_iterator_t creds_iterator = NULL;
+       cc_credentials_t credentials = NULL;
+       cc_time_t last_time = 0;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       
+       // create some ccaches (so that the one we keep around as 'ccache' is not default)
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+       if (ccache) {
+               cc_ccache_release(ccache);
+       }
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache);
+       }
+       
+       // change it in all the ways it can change, checking after each
+       
+       // the ccache is created
+       if (!err) {
+               check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "new ccache (change time should be > 0)");
+       }
+       
+       // the ccache is made default
+       if (!err) {
+               err = cc_ccache_set_default(ccache);
+       }
+       if (!err) {
+               check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "non-default ccache became default");
+       }
+       
+       // the ccache is made not-default
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "something@ELSE.COM", &dummy_ccache);
+       }
+       if (!err) {
+               err = cc_ccache_set_default(dummy_ccache);
+       }
+       if (dummy_ccache) {     
+               cc_ccache_release(dummy_ccache);
+       }
+       if (!err) {
+               check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "default ccache became non-default");
+       }
+       
+       // try with bad params
+       
+       // NULL out param
+       if (!err) {
+               check_once_cc_ccache_get_change_time(ccache, NULL, ccErrBadParam, "NULL out param for time");
+       }
+       
+       // store a credential
+       if (!err) {
+               new_v5_creds_union(&creds_union, "BAR.ORG");
+               err = cc_ccache_store_credentials(ccache, &creds_union);
+               release_v5_creds_union(&creds_union);
+       }
+       check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "stored new credential");
+       
+       if (!err) {
+               // change principal (fails with ccErrBadInternalMessage)
+               err = cc_ccache_set_principal(ccache, cc_credentials_v5, "foo@BAR.ORG");
+               if (err) {
+                       log_error("failed to change ccache's principal - %s (%d)", translate_ccapi_error(err), err);
+                       failure_count++;
+                       err = ccNoError;
+               }
+       }
+       check_once_cc_context_get_change_time(context, &last_time, ccNoError, "after changing a principle");
+       
+       // remove a credential
+       if (!err) {
+               err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator);
+       }
+       if (!err) {
+               err = cc_credentials_iterator_next(creds_iterator, &credentials);
+       }
+       if (err == ccIteratorEnd) {
+               err = ccNoError;
+       }
+       if (!err) {
+               err = cc_ccache_remove_credentials(ccache, credentials);
+       }
+       check_once_cc_context_get_change_time(context, &last_time, ccNoError, "after removing a credential");
+       
+       
+       // invalid ccache
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       if (!err) {
+               check_once_cc_ccache_get_change_time(ccache, &last_time, ccErrInvalidCCache, "getting change time on destroyed ccache");
+       }
+       
+       if (ccache) { cc_ccache_release(ccache); }
+       if (context) { 
+               destroy_all_ccaches(context);
+               cc_context_release(context);
+       }
+       
+       #endif /* cc_ccache_get_change_time */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_get_change_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_ccache_get_change_time
+       
+       cc_int32 possible_return_values[4] = {
+               ccNoError, 
+               ccErrInvalidCCache, 
+               ccErrBadParam, 
+               ccErrCCacheNotFound, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_time_t this_time = 0;
+       
+       if (last_time == NULL) {
+               err = cc_ccache_get_change_time(ccache, NULL); // passed NULL to compare against because intention is actually to pass bad param instead
+       } else {
+               err = cc_ccache_get_change_time(ccache, &this_time);
+       }
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if ((!err) && last_time) {
+               check_if(this_time <= *last_time, "change time didn't increase when expected");
+               *last_time = this_time;
+       }
+               
+       #endif /* cc_ccache_get_change_time */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_get_last_default_time() {
+       BEGIN_TEST("cc_ccache_get_last_default_time");
+       
+       #ifndef cc_ccache_get_last_default_time
+       log_error("cc_ccache_get_last_default_time is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache_1 = NULL;
+       cc_ccache_t ccache_2 = NULL;
+       cc_time_t last_time_1 = 0;
+       cc_time_t last_time_2 = 0;
+       cc_string_t name = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       
+       // create 2 ccaches
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@ONE.ORG", &ccache_1);
+       }
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@TWO.ORG", &ccache_2);
+       }
+       
+       if (!err) {
+               err = cc_ccache_get_change_time(ccache_1, &last_time_1);
+       }
+       
+       // since we destroyed all ccaches before creating these two, 
+       // ccache_1 should be default and ccache_2 should never have been default
+       if (!err) {
+               check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccNoError, "ccache_1 default at creation");
+               check_once_cc_ccache_get_last_default_time(ccache_2, &last_time_2, ccErrNeverDefault, "ccache_2 never default");
+       }
+       
+       // make ccache_2 default and check each of their times again
+       if (!err) {
+               err = cc_ccache_set_default(ccache_2);
+       }
+       if (!err) {
+               err = cc_ccache_get_change_time(ccache_2, &last_time_2);
+       }
+       if (!err) {
+               check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccNoError, "ccache_1 no longer default");
+               check_once_cc_ccache_get_last_default_time(ccache_2, &last_time_2, ccNoError, "ccache_2 newly default");
+       }
+
+       // NULL param
+       if (!err) {
+               check_once_cc_ccache_get_last_default_time(ccache_1, NULL, ccErrBadParam, "NULL out param");
+       }
+       
+       // non-existent ccache
+       if (ccache_2) { 
+               cc_ccache_release(ccache_2); 
+               ccache_2 = NULL;
+       }
+       if (!err) {
+               err = cc_ccache_get_name(ccache_1, &name);
+       }
+       if (!err) {
+               err = cc_context_open_ccache(context, name->data, &ccache_2);
+       }
+       if (!err) {
+               cc_ccache_destroy(ccache_2);
+               ccache_2 = NULL;
+       }
+       
+       if (!err) {
+               check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccErrCCacheNotFound, "destroyed ccache");
+       }
+       
+       if (ccache_1) { cc_ccache_release(ccache_1); }
+       
+       if (context) { 
+               destroy_all_ccaches(context);
+               cc_context_release(context);
+       }
+       
+       #endif /* cc_ccache_get_last_default_time */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_get_last_default_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_ccache_get_last_default_time
+       
+       cc_int32 possible_return_values[5] = {
+               ccNoError, 
+               ccErrInvalidCCache, 
+               ccErrBadParam, 
+               ccErrNeverDefault, 
+               ccErrCCacheNotFound, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_time_t this_time = 0;
+       
+       if (last_time == NULL) {
+               err = cc_ccache_get_last_default_time(ccache, NULL); // passed NULL to compare against because intention is actually to pass bad param instead
+       } else {
+               err = cc_ccache_get_last_default_time(ccache, &this_time);
+       }
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err && last_time) {
+               check_if(this_time > *last_time, "last default time isn't as expected");
+               *last_time = this_time;
+       }
+               
+       #endif /* cc_ccache_get_last_default_time */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+int check_cc_ccache_move() {
+       BEGIN_TEST("cc_ccache_move");
+       
+       #ifndef cc_ccache_move
+       log_error("cc_ccache_move is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t source = NULL;
+       cc_ccache_t destination = NULL;
+       
+       cc_credentials_union creds_union;
+       unsigned int i = 0;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       
+       // create 2 ccaches
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@ONE.ORG", &source);
+       }
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@TWO.ORG", &destination);
+       }
+       
+       // store credentials in each
+       for (i = 0; !err && (i < 10); i++) {
+               new_v5_creds_union(&creds_union, "ONE.ORG");
+               err = cc_ccache_store_credentials(source, &creds_union);
+       }
+       for (i = 0; !err && (i < 10); i++) {
+               new_v5_creds_union(&creds_union, "TWO.ORG");
+               err = cc_ccache_store_credentials(destination, &creds_union);
+       }
+       
+       // move source into destination
+       if (!err) {
+               check_once_cc_ccache_move(source, destination, ccNoError, "valid params");
+       }
+
+       // NULL param
+       if (!err) {
+               check_once_cc_ccache_move(destination, NULL, ccErrInvalidCCache, "NULL destination param");
+       }
+       
+       // non-existent ccache
+       if (!err) {
+               check_once_cc_ccache_move(destination, source, ccErrInvalidCCache, "recently moved source as destination param");
+       }
+       
+       if (source) { cc_ccache_release(source); }
+       if (destination) { cc_ccache_release(destination); }
+       
+       if (context) { 
+               destroy_all_ccaches(context);
+               cc_context_release(context);
+       }
+       
+       #endif /* cc_ccache_move */
+       
+       END_TEST_AND_RETURN
+       
+       
+}
+
+cc_int32 check_once_cc_ccache_move(cc_ccache_t source, cc_ccache_t destination, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_ccache_move
+       
+       cc_int32 possible_return_values[3] = {
+               ccNoError, 
+               ccErrInvalidCCache, 
+               ccErrCCacheNotFound,
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_credentials_t dst_creds[10] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, };
+       cc_credentials_t creds = NULL;
+       cc_credentials_iterator_t cred_iterator = NULL;
+       unsigned int i = 0;
+       
+       cc_string_t src_principal = NULL;
+       cc_string_t dst_principal = NULL;
+
+       if (destination) {
+               // verify all of destination's credentials are no longer there (save a list and call remove_cred for each, expecting an err in response)        
+               if (!err) {
+                       err = cc_ccache_new_credentials_iterator(destination, &cred_iterator);
+               }
+               while (!err && (i < 10)) {
+                       err = cc_credentials_iterator_next(cred_iterator, &creds);
+                       if (creds) {
+                               dst_creds[i++] = creds;
+                       }
+               }
+               if (err == ccIteratorEnd) {
+                       !err;
+               }
+               if (cred_iterator) { 
+                       cc_credentials_iterator_release(cred_iterator); 
+                       cred_iterator = NULL;
+               }
+
+               // verify that destination's principal has changed to source's (strcmp)
+               if (!err) {
+                       err = cc_ccache_get_principal(source, cc_credentials_v5, &src_principal);
+               }
+       }
+       
+       
+       if (!err) {
+               err = cc_ccache_move(source, destination);
+       }
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       
+       if (!err) {
+               // verify all of destination's credentials are no longer there (save a list and call remove_cred for each, expecting an err in response)
+               i = 0;
+               while (dst_creds[i] && (i < 10)) {
+                       err = cc_ccache_remove_credentials(destination, dst_creds[i]);
+                       check_if(!(!err || err == ccErrCredentialsNotFound || ccErrInvalidCredentials), "credentials in destination not removed as promised");
+                       cc_credentials_release(dst_creds[i]);
+                       i++;
+               }
+               err = ccNoError;
+       }
+
+               // verify that destination's principal has changed to source's (strcmp)
+               if (!err) {
+                       err = cc_ccache_get_principal(destination, cc_credentials_v5, &dst_principal);
+               }
+               if (!err) {
+                       check_if(strcmp(src_principal->data, dst_principal->data), "destination principal not overwritten by source");
+               }
+
+               // verify that handles for source are no longer valid (get_change_time)
+               if (src_principal) { 
+                       cc_string_release(src_principal);
+                       src_principal = NULL;
+               }
+               if (!err) {
+                       err = cc_ccache_get_principal(source, cc_credentials_v5, &src_principal);
+                       check_if(err != ccErrInvalidCCache, "source ccache was not invalidated after move");
+               }
+       
+       
+       if (cred_iterator) { cc_credentials_iterator_release(cred_iterator); }
+       if (src_principal) { cc_string_release(src_principal); }
+       if (dst_principal) { cc_string_release(dst_principal); }
+               
+       #endif /* cc_ccache_move */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_compare() {
+       BEGIN_TEST("cc_ccache_compare");
+       
+       #ifndef cc_ccache_compare
+       log_error("cc_ccache_compare is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache_a = NULL;
+       cc_ccache_t ccache_b = NULL;
+       cc_uint32 equal = 0;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache_a);
+       }
+       if (!err) {
+               err = cc_context_open_default_ccache(context, &ccache_b);
+       }
+
+       equal = 1;
+       check_once_cc_ccache_compare(ccache_a, ccache_a, &equal, ccNoError, "compare ccache with same pointer");
+       equal = 1;
+       check_once_cc_ccache_compare(ccache_a, ccache_b, &equal, ccNoError, "compare different handles to same ccache");
+       
+       if (ccache_b) {
+               cc_ccache_release(ccache_b);
+               ccache_b = NULL;
+       }
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "baz@BAR.ORG", &ccache_b);
+       }
+       equal = 0;
+       check_once_cc_ccache_compare(ccache_a, ccache_b, &equal, ccNoError, "compare different ccaches");
+       check_once_cc_ccache_compare(ccache_a, NULL, &equal, ccErrInvalidCCache, "NULL compare_to ccache");
+       check_once_cc_ccache_compare(ccache_a, ccache_b, NULL, ccErrBadParam, "NULL out param");
+
+       if (ccache_a) { cc_ccache_release(ccache_a); }
+       if (ccache_b) { cc_ccache_release(ccache_b); }
+       
+       if (context) { 
+               err = destroy_all_ccaches(context);
+               cc_context_release(context); 
+       }
+       
+       #endif /* cc_ccache_compare */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_compare(cc_ccache_t ccache, cc_ccache_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+
+       BEGIN_CHECK_ONCE(description);
+
+       #ifdef cc_ccache_compare
+       
+       cc_int32 possible_return_values[4] = {
+               ccNoError, 
+               ccErrInvalidContext, 
+               ccErrBadParam, 
+               ccErrServerUnavailable,
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_uint32 actually_equal = 0;
+       
+       if (equal) {
+               actually_equal = *equal;
+       } 
+       
+       err = cc_ccache_compare(ccache, compare_to, equal);
+       
+       if (!err && equal) {
+               if (actually_equal) {
+                       check_if(actually_equal != *equal, "equal ccaches not considered equal");
+               }
+               else {
+                       check_if(actually_equal != *equal, "non-equal ccaches considered equal");
+               }
+       }
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       #endif /* cc_ccache_compare */
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_get_kdc_time_offset() {
+       BEGIN_TEST("cc_ccache_get_kdc_time_offset");
+       
+       #ifndef cc_ccache_get_kdc_time_offset
+       log_error("cc_ccache_get_kdc_time_offset is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       cc_time_t time_offset = 0;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+
+       time_offset = 0;
+       check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, &time_offset, ccErrTimeOffsetNotSet, "brand new ccache (offset not yet set)");
+       
+       time_offset = 10;
+       if (!err) {
+               err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, time_offset);
+       }
+       if (!err) {
+               check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, &time_offset, ccNoError, "offset set for v5 but not v4");
+       }
+       if (!err) {
+               check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v4, &time_offset, ccErrTimeOffsetNotSet, "asking for v4 offset when only v5 is set");
+       }
+       if (!err) {
+               err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4, time_offset);
+       }
+       if (!err) {
+               check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v4, &time_offset, ccNoError, "asking for v4 offset when v4 and v5 are set");
+       }
+       
+
+       check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, NULL, ccErrBadParam, "NULL time_offset out param");
+       check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v4_v5, &time_offset, ccErrBadCredentialsVersion, "v4_v5 creds_vers in param (invalid)");
+
+       if (ccache) { cc_ccache_release(ccache); }
+       
+       if (context) { 
+               err = destroy_all_ccaches(context);
+               cc_context_release(context); 
+       }
+       
+       #endif /* cc_ccache_get_kdc_time_offset */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_get_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t *time_offset, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+
+       BEGIN_CHECK_ONCE(description);
+
+       #ifdef cc_ccache_get_kdc_time_offset
+       
+       cc_int32 possible_return_values[7] = {
+               ccNoError, 
+               ccErrTimeOffsetNotSet, 
+               ccErrCCacheNotFound, 
+               ccErrInvalidCCache, 
+               ccErrBadParam, 
+               ccErrServerUnavailable, 
+               ccErrBadCredentialsVersion,     
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_time_t expected_offset;
+       
+       if (time_offset) {
+               expected_offset = *time_offset;
+       }
+       
+       err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, time_offset);
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err && time_offset) {
+               check_if(*time_offset != expected_offset, "kdc time offset doesn't match expected value");
+       }
+       
+       #endif /* cc_ccache_get_kdc_time_offset */
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_set_kdc_time_offset() {
+       BEGIN_TEST("cc_ccache_set_kdc_time_offset");
+       
+       #ifndef cc_ccache_set_kdc_time_offset
+       log_error("cc_ccache_set_kdc_time_offset is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+
+       check_once_cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, 0, ccNoError, "first time setting offset (v5)");
+       check_once_cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4, 0, ccNoError, "first time setting offset (v4)");
+       
+       check_once_cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4_v5, 0, ccErrBadCredentialsVersion, "invalid creds_vers (v4_v5)");
+
+       if (ccache) { cc_ccache_release(ccache); }
+       
+       if (context) { 
+               err = destroy_all_ccaches(context);
+               cc_context_release(context); 
+       }
+       
+       #endif /* cc_ccache_set_kdc_time_offset */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_set_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t time_offset, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+
+       BEGIN_CHECK_ONCE(description);
+
+       #ifdef cc_ccache_set_kdc_time_offset
+       
+       cc_int32 possible_return_values[6] = {
+               ccNoError, 
+               ccErrCCacheNotFound, 
+               ccErrInvalidCCache, 
+               ccErrBadParam, 
+               ccErrServerUnavailable, 
+               ccErrBadCredentialsVersion,
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_time_t stored_offset = 0;
+               
+       err = cc_ccache_set_kdc_time_offset(ccache, credentials_version, time_offset);
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err) {
+               err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, &stored_offset);
+       }
+       
+       if (!err) {
+               check_if(time_offset != stored_offset, "kdc time offset doesn't match expected value");
+       }
+       
+       #endif /* cc_ccache_set_kdc_time_offset */
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_clear_kdc_time_offset() {
+       BEGIN_TEST("cc_ccache_clear_kdc_time_offset");
+       
+       #ifndef cc_ccache_clear_kdc_time_offset
+       log_error("cc_ccache_clear_kdc_time_offset is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+
+       check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v5, ccNoError, "clearing an offset that was never set (v5)");
+       check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v4, ccNoError, "clearing an offset that was never set (v4)");
+
+       err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, 0);
+       err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4, 0);
+       
+       check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v5, ccNoError, "clearing v5");
+       check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v4, ccNoError, "clearing v4");
+       
+       check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v4_v5, ccErrBadCredentialsVersion, "bad in param creds vers (v4_v5)");
+       
+       if (ccache) { cc_ccache_release(ccache); }
+       
+       if (context) { 
+               err = destroy_all_ccaches(context);
+               cc_context_release(context); 
+       }
+       
+       #endif /* cc_ccache_clear_kdc_time_offset */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_clear_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+
+       BEGIN_CHECK_ONCE(description);
+
+       #ifdef cc_ccache_clear_kdc_time_offset
+       
+       cc_int32 possible_return_values[6] = {
+               ccNoError, 
+               ccErrCCacheNotFound, 
+               ccErrInvalidCCache, 
+               ccErrBadParam, 
+               ccErrServerUnavailable, 
+               ccErrBadCredentialsVersion,
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+       cc_time_t stored_offset = 0;
+       
+       err = cc_ccache_clear_kdc_time_offset(ccache, credentials_version);
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err) {
+               err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, &stored_offset);
+               check_if(err != ccErrTimeOffsetNotSet, "time offset not cleared");
+       }
+       
+       #endif /* cc_ccache_clear_kdc_time_offset */
+       
+       return err;
+}
+
+
diff --git a/src/ccapi/test/test_ccapi_ccache.h b/src/ccapi/test/test_ccapi_ccache.h
new file mode 100644 (file)
index 0000000..31d0083
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _TEST_CCAPI_CCACHE_H_
+#define _TEST_CCAPI_CCACHE_H_
+
+#include <Kerberos/CredentialsCache.h>
+
+
+int check_cc_ccache_release();
+cc_int32 check_once_cc_ccache_release(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description);
+int check_cc_ccache_destroy();
+cc_int32 check_once_cc_ccache_destroy(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description);
+int check_cc_ccache_set_default();
+cc_int32 check_once_cc_ccache_set_default(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description);
+int check_cc_ccache_get_credentials_version();
+cc_int32 check_once_cc_ccache_get_credentials_version(cc_ccache_t ccache, cc_uint32 expected_cred_vers, cc_int32 expected_err, const char *description);
+int check_cc_ccache_get_name();
+cc_int32 check_once_cc_ccache_get_name(cc_ccache_t ccache, const char *expected_name, cc_int32 expected_err, const char *description);
+int check_cc_ccache_get_principal();
+cc_int32 check_once_ccache_get_principal(cc_ccache_t ccache, cc_uint32 cred_vers, const char *expected_principal, cc_int32 expected_err, const char *description);
+int check_cc_ccache_set_principal();
+cc_int32 check_once_cc_ccache_set_principal(cc_ccache_t ccache, cc_uint32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_store_credentials();
+cc_int32 check_once_cc_ccache_store_credentials(cc_ccache_t ccache, const cc_credentials_union *credentials, cc_int32 expected_err, const char *description);
+int check_cc_ccache_remove_credentials();
+cc_int32 check_once_cc_ccache_remove_credentials(cc_ccache_t ccache, cc_credentials_t in_creds, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_new_credentials_iterator();
+cc_int32 check_once_cc_ccache_new_credentials_iterator(cc_ccache_t ccache, cc_credentials_iterator_t *iterator, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_get_change_time();
+cc_int32 check_once_cc_ccache_get_change_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description);
+int check_cc_ccache_get_last_default_time();
+cc_int32 check_once_ccache_get_last_default_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_move();
+cc_int32 check_once_cc_ccache_move(cc_ccache_t source, cc_ccache_t destination, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_compare();
+cc_int32 check_once_cc_ccache_compare(cc_ccache_t ccache, cc_ccache_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_get_kdc_time_offset();
+cc_int32 check_once_cc_ccache_get_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t *time_offset, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_set_kdc_time_offset();
+cc_int32 check_once_cc_ccache_set_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t time_offset, cc_int32 expected_err, const char *description);
+
+int check_cc_ccache_clear_kdc_time_offset();
+cc_int32 check_once_cc_ccache_clear_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_int32 expected_err, const char *description);
+
+#endif /* _TEST_CCAPI_CCACHE_H_ */
diff --git a/src/ccapi/test/test_ccapi_check.c b/src/ccapi/test/test_ccapi_check.c
new file mode 100644 (file)
index 0000000..12192a6
--- /dev/null
@@ -0,0 +1,37 @@
+#include "test_ccapi_check.h"
+
+int _check_if(int expression, const char *file, int line, const char *expression_string, const char *format, ...) {
+       if (expression) {
+               failure_count++;
+               // call with NULL format to get a generic error message
+               if (format == NULL) {
+                       _log_error(file, line, expression_string);
+               }
+               // call with format and varargs for a more useful error message
+               else {
+                       va_list ap;
+                       va_start(ap, format);
+                       _log_error_v(file, line, format, ap);
+                       va_end(ap);
+               }
+               
+               if (current_test_activity) {
+                       fprintf(stdout, " (%s)", current_test_activity);
+               }
+       }
+       
+       return (expression != 0);       
+}
+
+int array_contains_int(cc_int32 *array, int size, cc_int32 value) {
+       if (array != NULL && size > 0) {
+               int i = 0;
+               while (i < size && array[i] != value) { 
+                       i++; 
+               }
+               if (i < size) {
+                       return 1;
+               }
+       }
+       return 0;
+}
\ No newline at end of file
diff --git a/src/ccapi/test/test_ccapi_check.h b/src/ccapi/test/test_ccapi_check.h
new file mode 100644 (file)
index 0000000..c05a515
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef _TEST_CCAPI_CHECK_H_
+#define _TEST_CCAPI_CHECK_H_
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "test_ccapi_log.h"
+#include "test_ccapi_globals.h"
+
+int _check_if(int expression, const char *file, int line, const char *expression_string, const char *format, ...);
+               
+#define check_int(a, b) \
+               check_if(a != b, NULL)
+
+/*
+ *     if expression evaluates to true, check_if increments the failure_count and prints:
+ *     
+ *     check_if(a!=a, NULL);
+ *     ==> "/path/to/file:line: a!=a" 
+ *     
+ *     check_if(a!=a, "This shouldn't be happening");
+ *     ==> "/path/to/file:line: This shouldn't be happening"
+ *     
+ *     check_if(a!=a, "This has happened %d times now", 3);
+ *     ==> "/path/to/file:line: This has happened 3 times now" 
+*/
+
+#define check_if(expression, format, ...) \
+               _check_if(expression, __FILE__, __LINE__, #expression, format , ## __VA_ARGS__)
+
+#define check_if_not(expression, format, ...) \
+               check_if(!(expression), format, ## __VA_ARGS__)
+
+// first check if err is what we were expecting to get back
+// then check if err is even in the set of errors documented for the function
+#define check_err(err, expected_err, possible_return_values) \
+               do { \
+                       check_if(err != expected_err, "unexpected error %s (%d), expected %s (%d)", translate_ccapi_error(err), err, translate_ccapi_error(expected_err), expected_err); \
+                       check_if_not(array_contains_int(possible_return_values, possible_ret_val_count, err), "error not documented as a possible return value: %s (%d)", translate_ccapi_error(err), err); \
+               } while( 0 )
+
+int array_contains_int(cc_int32 *array, int size, cc_int32 value);
+
+#endif /* _TEST_CCAPI_CHECK_H_ */
diff --git a/src/ccapi/test/test_ccapi_constants.c b/src/ccapi/test/test_ccapi_constants.c
new file mode 100644 (file)
index 0000000..5203fff
--- /dev/null
@@ -0,0 +1,66 @@
+#include "test_ccapi_constants.h"
+#include "test_ccapi_globals.h"
+#include "test_ccapi_check.h"
+
+int check_constants() {
+       BEGIN_TEST("constants");
+       /* API versions */
+       
+       check_int(ccapi_version_2, 2);
+       check_int(ccapi_version_3, 3);
+       check_int(ccapi_version_4, 4);
+       check_int(ccapi_version_5, 5);
+       check_int(ccapi_version_6, 6);
+       
+       /* Errors */
+       
+       check_int(ccNoError                                       , 0  );        //   0               
+       check_int(ccIteratorEnd                                   , 201);    // 201
+       check_int(ccErrBadParam                               , 202);    // 202
+       check_int(ccErrNoMem                                      , 203);    // 203
+       check_int(ccErrInvalidContext             , 204);    // 204
+       check_int(ccErrInvalidCCache              , 205);    // 205
+       check_int(ccErrInvalidString              , 206);    // 206
+       check_int(ccErrInvalidCredentials         , 207);    // 207
+       check_int(ccErrInvalidCCacheIterator      , 208);    // 208
+       check_int(ccErrInvalidCredentialsIterator , 209);    // 209
+       check_int(ccErrInvalidLock                , 210);    // 210
+       check_int(ccErrBadName                    , 211);    // 211
+       check_int(ccErrBadCredentialsVersion      , 212);    // 212
+       check_int(ccErrBadAPIVersion              , 213);    // 213
+       check_int(ccErrContextLocked              , 214);    // 214
+       check_int(ccErrContextUnlocked            , 215);    // 215
+       check_int(ccErrCCacheLocked               , 216);    // 216
+       check_int(ccErrCCacheUnlocked             , 217);    // 217
+       check_int(ccErrBadLockType                , 218);    // 218
+       check_int(ccErrNeverDefault               , 219);    // 219
+       check_int(ccErrCredentialsNotFound        , 220);    // 220
+       check_int(ccErrCCacheNotFound             , 221);    // 221
+       check_int(ccErrContextNotFound            , 222);    // 222
+       check_int(ccErrServerUnavailable          , 223);    // 223
+       check_int(ccErrServerInsecure             , 224);    // 224
+       check_int(ccErrServerCantBecomeUID        , 225);    // 225
+       check_int(ccErrTimeOffsetNotSet           , 226);    // 226
+       check_int(ccErrBadInternalMessage         , 227);    // 227
+       check_int(ccErrNotImplemented             , 228);    // 228
+
+       /* Credentials versions */
+       
+       check_int(cc_credentials_v4,    1);
+       check_int(cc_credentials_v5,    2);
+       check_int(cc_credentials_v4_v5, (cc_credentials_v4 | cc_credentials_v5));
+
+       /* Lock types */
+
+       check_int(cc_lock_read,      0);
+       check_int(cc_lock_write,     1);
+       check_int(cc_lock_upgrade,   2);
+       check_int(cc_lock_downgrade, 3);
+
+    /* Locking Modes */
+  
+       check_int(cc_lock_noblock, 0);
+       check_int(cc_lock_block,   1);
+       
+       END_TEST_AND_RETURN
+}
\ No newline at end of file
diff --git a/src/ccapi/test/test_ccapi_constants.h b/src/ccapi/test/test_ccapi_constants.h
new file mode 100644 (file)
index 0000000..ff6fd66
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _TEST_CCAPI_CONSTANTS_H_
+#define _TEST_CCAPI_CONSTANTS_H_
+
+int check_constants();
+
+#endif /* _TEST_CCAPI_CONSTANTS_H_ */
diff --git a/src/ccapi/test/test_ccapi_context.c b/src/ccapi/test/test_ccapi_context.c
new file mode 100644 (file)
index 0000000..b9365a6
--- /dev/null
@@ -0,0 +1,1065 @@
+#include <string.h>
+#include "test_ccapi_context.h"
+#include <limits.h>
+#include "test_ccapi_check.h"
+#include "test_ccapi_util.h"
+
+int check_cc_initialize() {
+       BEGIN_TEST("cc_initialize");
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       
+       // try every api_version
+       err = check_once_cc_initialize(&context, ccapi_version_2, NULL, NULL, 11, NULL);                 // err == CC_NOT_SUPP, not reflected in documentation rev 8
+       err = check_once_cc_initialize(&context, ccapi_version_3, NULL, NULL, ccNoError, NULL);            // !err                                    
+       err = check_once_cc_initialize(&context, ccapi_version_4, NULL, NULL, ccNoError, NULL);            //        "                                            
+       err = check_once_cc_initialize(&context, ccapi_version_5, NULL, NULL, ccNoError, NULL);            //        "                                            
+       err = check_once_cc_initialize(&context, ccapi_version_6, NULL, NULL, ccNoError, NULL);            //        "                                            
+       
+       // try bad api_version
+       err = check_once_cc_initialize(&context, INT_MAX,         NULL, NULL, ccErrBadAPIVersion, NULL); // err == ccErrBadAPIVersion                             
+       
+       // try bad param
+       err = check_once_cc_initialize(NULL,     ccapi_version_3, NULL, NULL, ccErrBadParam, NULL);        // err == ccErrBadParam                                
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_initialize(cc_context_t *out_context, cc_int32 in_version, cc_int32 *out_supported_version, char const **out_vendor, cc_int32 expected_err, const char *description) {
+       cc_int32 err = 0;
+       cc_context_t context;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       cc_int32 possible_return_values[4] = {
+               ccNoError, 
+               ccErrNoMem, 
+               ccErrBadAPIVersion, 
+               ccErrBadParam,
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       err = cc_initialize(out_context, in_version, out_supported_version, out_vendor);
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (out_context) { context = *out_context; }
+       else { context = NULL; }
+       
+       // check output parameters
+       if (!err) {
+               check_if(context == NULL, NULL);
+               if (context) { 
+                       cc_context_release(context); 
+                       *out_context = NULL;
+               }
+       } else {
+               check_if(context != NULL, NULL);
+       }
+       
+       return err;
+}
+
+
+int check_cc_context_get_version() {
+       BEGIN_TEST("cc_context_get_version");
+       
+       #ifndef cc_context_get_version
+       log_error("cc_context_get_version is not implemented yet");
+       failure_count++;
+       #else
+       // This code is all untested, since there is no cc_context_get_version to test against
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       
+       // try every api_version
+       //err = check_once_cc_context_get_version(&context, ccapi_version_2, NULL, NULL, ccNoError);         // err == CC_NOT_SUPP, not reflected in documentation rev 8
+       err = check_once_cc_context_get_version(&context, ccapi_version_3, NULL, NULL, ccNoError);           // !err                                    
+       err = check_once_cc_context_get_version(&context, ccapi_version_4, NULL, NULL, ccNoError);           //        "                                            
+       err = check_once_cc_context_get_version(&context, ccapi_version_5, NULL, NULL, ccNoError);           //        "                                            
+       err = check_once_cc_context_get_version(&context, ccapi_version_6, NULL, NULL, ccNoError);           //        "                                            
+       
+       // try bad api_version
+       err = check_once_cc_context_get_version(&context, INT_MAX,         NULL, NULL, ccErrBadAPIVersion);  // err == ccErrBadAPIVersion                             
+       
+       // try bad param
+       err = check_once_cc_context_get_version(NULL,     ccapi_version_3, NULL, NULL, ccErrInvalidContext); // err == ccErrInvalidContext                                         
+       
+       
+       #endif /* cc_context_get_version */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_get_version(cc_context_t *out_context, cc_int32 in_version, cc_int32 *out_supported_version, char const **out_vendor, cc_int32 expected_err, const char *description) {
+       cc_int32 err = 0;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_context_get_version
+       // This code is all untested, since there is no cc_context_get_version to test against
+       
+       cc_context_t context = NULL;
+       cc_int32 reported_version;
+       
+       cc_int32 possible_return_values[3] = {
+               ccNoError, 
+               ccErrInvalidContext, 
+               ccErrBadParam,
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       err = cc_initialize(out_context, in_version, out_supported_version, out_vendor);
+       
+       if (err != ccNoError) {
+               log_error("failure in cc_initialize, unable to perform check");
+               return err;
+       }
+       else {
+               context = *out_context;
+               err = cc_context_get_version(context, &reported_version);
+               
+               // check returned error
+               check_err(err, expected_err, possible_return_values);
+       }
+                       
+       // check output parameters and free memory
+       if (!err) {
+               check_if(reported_version != in_version, NULL);
+       } else if (err == ccErrBadParam) {
+               check_if_not((context == NULL || &reported_version == NULL), "given ccErrBadParam but no param was bad");
+       }
+       
+       if (context) { 
+               cc_context_release(context); 
+               *out_context = NULL;
+       }
+       
+       #endif /* cc_context_get_version */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+int check_cc_context_release() {
+       BEGIN_TEST("cc_context_release");
+       
+       #ifndef cc_context_release
+       log_error("cc_context_release is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       
+       // try with valid context
+       err = check_once_cc_context_release(&context, ccNoError, NULL);
+       
+       // try with NULL
+       //err = check_once_cc_context_release(NULL, ccErrInvalidContext);
+       /* calling with NULL context crashes, because this macro expands to 
+          ((NULL) -> functions -> release (NULL)) which is dereferencing NULL which is bad. */
+       
+       if (context) { cc_context_release(context); }
+       
+       #endif /* cc_context_release */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_release(cc_context_t *out_context, cc_int32 expected_err, const char *description) {
+       cc_int32 err = 0;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_context_release
+       
+       cc_context_t context = NULL;
+       
+       cc_int32 possible_return_values[2] = {
+               ccNoError, 
+               ccErrInvalidContext, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       if (out_context) {
+               err = cc_initialize(out_context, ccapi_version_3, NULL, NULL);
+               if (!err) { 
+                       context = *out_context; 
+               }
+       }
+       
+       if (err != ccNoError) {
+               log_error("failure in cc_initialize, unable to perform check");
+               return err;
+       }
+       else {
+               err = cc_context_release(context);
+               // check returned error
+               check_err(err, expected_err, possible_return_values);
+       }
+       
+       *out_context = NULL;
+       
+       #endif /* cc_context_release */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+int check_cc_context_get_change_time() {
+       BEGIN_TEST("cc_context_get_change_time");
+       
+       #ifndef cc_context_get_change_time
+       log_error("cc_context_get_change_time is not implemented yet");
+       failure_count++;
+       #else
+       
+       /*
+        * Make a context
+        * make sure the change time changes after:
+        *      a ccache is created  
+        *      a ccache is destroyed  
+        *      a credential is stored  
+        *      a credential is removed  
+        *      a ccache principal is changed  
+        *      the default ccache is changed
+        * clean up memory
+        */
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_time_t last_change_time = 0;
+       cc_ccache_t ccache = NULL;
+       cc_credentials_union creds_union;
+       cc_credentials_iterator_t creds_iterator = NULL;
+       cc_credentials_t credentials = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       if (!err) {
+               
+               // try bad parameters first
+               err = check_once_cc_context_get_change_time(context, NULL, ccErrBadParam, "NULL param, should fail");
+               
+               // make sure we have a default ccache
+               err = cc_context_open_default_ccache(context, &ccache);
+               if (err == ccErrCCacheNotFound) {
+                       err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache);
+               }
+               if (!err) {
+                       err = cc_ccache_release(ccache);
+               }
+               // either the default ccache already existed or we just created it
+               // either way, the get_change_time should now give something > 0
+               check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "first-run, should be > 0");
+               
+               // create a ccache
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+               check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after creating a new ccache");
+               
+               // store a credential
+               if (!err) {
+                       new_v5_creds_union(&creds_union, "BAR.ORG");
+                       err = cc_ccache_store_credentials(ccache, &creds_union);
+                       release_v5_creds_union(&creds_union);
+               }
+               check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after storing a credential");
+               
+               if (!err) {
+                       // change principal (fails with ccErrBadInternalMessage)
+                       err = cc_ccache_set_principal(ccache, cc_credentials_v5, "foo@BAR.ORG");
+                       if (err) {
+                               log_error("failed to change ccache's principal - %s (%d)", translate_ccapi_error(err), err);
+                               failure_count++;
+                               err = ccNoError;
+                       }
+               }
+               check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after changing a principle");
+               
+               // remove a credential
+               if (!err) {
+                       err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator);
+               }
+               if (!err) {
+                       err = cc_credentials_iterator_next(creds_iterator, &credentials);
+               }
+               if (err == ccIteratorEnd) {
+                       err = ccNoError;
+               }
+               if (!err) {
+                       err = cc_ccache_remove_credentials(ccache, credentials);
+               }
+               check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after removing a credential");            
+               
+               if (!err) {
+                       // change default ccache
+                       err = cc_ccache_set_default(ccache);
+                       check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after changing default ccache");
+               }
+               
+               if (ccache) {
+                       // destroy a ccache
+                       err = cc_ccache_destroy(ccache);
+                       check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after destroying a ccache");
+               }
+       }
+       
+       if (context) { cc_context_release(context); }
+       
+       #endif /* cc_get_change_time */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_get_change_time(cc_context_t context, cc_time_t *time, cc_int32 expected_err, const char *description) {
+       cc_int32 err = 0;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_context_get_change_time
+       
+       cc_int32 possible_return_values[3] = {
+               ccNoError, 
+               ccErrInvalidContext, 
+               ccErrBadParam,
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       cc_time_t last_change_time;
+       cc_time_t current_change_time = 0;
+       
+       if (time != NULL) { // if we were passed NULL, then we're looking to pass a bad param
+               err = cc_context_get_change_time(context, &current_change_time);
+       } else {
+               err = cc_context_get_change_time(context, NULL);
+       }
+       
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err) {
+               last_change_time = *time;
+               check_if(current_change_time <= last_change_time, "context change time did not increase when it was supposed to (%d <= %d)", current_change_time, last_change_time);
+               *time = current_change_time;
+       }
+       
+       #endif /* cc_context_get_change_time */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+int check_cc_context_get_default_ccache_name() {
+       BEGIN_TEST("cc_context_get_default_ccache_name");
+       
+       #ifndef cc_context_get_default_ccache_name
+       log_error("cc_context_get_default_ccache_name is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       cc_string_t name = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       if (!err) {     
+               // try bad parameters first
+               err = check_once_cc_context_get_default_ccache_name(context, NULL, ccErrBadParam, NULL);
+               
+               // try with no default
+               err = destroy_all_ccaches(context);
+               err = cc_context_open_default_ccache(context, &ccache);
+               if (err != ccErrCCacheNotFound) {
+                       log_error("didn't remove all ccaches");
+               }
+               err = check_once_cc_context_get_default_ccache_name(context, &name, ccNoError, NULL);
+               
+               // try normally
+               err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+               if (ccache) { cc_ccache_release(ccache); }
+               err = check_once_cc_context_get_default_ccache_name(context, &name, ccNoError, NULL);
+               
+       }
+       
+       if (context) { cc_context_release(context); }
+       
+       #endif /* cc_context_get_default_ccache_name */
+       
+       END_TEST_AND_RETURN     
+}
+
+cc_int32 check_once_cc_context_get_default_ccache_name(cc_context_t context, cc_string_t *name, cc_int32 expected_err, const char *description) {
+       cc_int32 err = 0;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_context_get_default_ccache_name
+       
+       cc_int32 possible_return_values[4] = {
+               ccNoError, 
+               ccErrInvalidContext, 
+               ccErrBadParam, 
+               ccErrNoMem, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+               
+       if (name != NULL) { // if we were passed NULL, then we're looking to pass a bad param
+               err = cc_context_get_default_ccache_name(context, name);
+       } else {
+               err = cc_context_get_default_ccache_name(context, NULL);
+       }
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       // not really anything else to check
+       
+       if (name && *name) { cc_string_release(*name); }
+       
+       #endif /* cc_context_get_default_ccache_name */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+int check_cc_context_open_ccache() {
+       BEGIN_TEST("cc_context_open_ccache");
+       
+       #ifndef cc_context_open_ccache
+       log_error("cc_context_open_ccache is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       cc_string_t name = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       if (!err) {     
+               // make sure we have a default ccache
+               err = cc_context_open_default_ccache(context, &ccache);
+               if (err == ccErrCCacheNotFound) {
+                       err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache);
+               }
+               if (!err) {
+                       err = cc_ccache_release(ccache);
+                       ccache = NULL;
+               }
+               
+               // try default ccache
+               err = cc_context_get_default_ccache_name(context, &name);
+               if (!err) {
+                       err = check_once_cc_context_open_ccache(context, name->data, &ccache, ccNoError, NULL);
+               }
+
+               // try bad parameters
+               err = check_once_cc_context_open_ccache(context, NULL, &ccache, ccErrBadParam, NULL);
+               err = check_once_cc_context_open_ccache(context, name->data, NULL, ccErrBadParam, NULL);
+               
+               // try a ccache that doesn't exist (create one and then destroy it)
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+               if (!err) {
+                       err = cc_ccache_get_name(ccache, &name);
+               }
+               if (!err) {
+                       err = cc_ccache_destroy(ccache);
+                       ccache = NULL;
+               }
+               
+               err = check_once_cc_context_open_ccache(context, name->data, &ccache, ccErrCCacheNotFound, NULL);
+       }
+       
+       if (context) { cc_context_release(context); }
+       
+       #endif /* cc_context_open_ccache */
+       
+       END_TEST_AND_RETURN     
+}
+
+cc_int32 check_once_cc_context_open_ccache(cc_context_t context, const char *name, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) {
+       cc_int32 err = 0;
+       cc_string_t stored_name = NULL;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_context_open_ccache
+       
+       cc_int32 possible_return_values[6] = {
+               ccNoError, 
+               ccErrBadName, 
+               ccErrInvalidContext, 
+               ccErrNoMem, 
+               ccErrCCacheNotFound, 
+               ccErrBadParam, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+               
+       if (ccache != NULL) { // if we were passed NULL, then we're looking to pass a bad param
+               err = cc_context_open_ccache(context, name, ccache);
+       } else {
+               err = cc_context_open_ccache(context, name, NULL);
+       }
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err) {
+               check_if(*ccache == NULL, NULL);
+               
+               if (!err) {
+                       err = cc_ccache_get_name(*ccache, &stored_name);
+               }
+               if (!err) { 
+                       check_if(strcmp(stored_name->data, name), NULL); 
+               }
+               if (stored_name) { cc_string_release(stored_name); }
+               
+               
+               if (ccache && *ccache) {
+                       cc_ccache_release(*ccache);
+                       *ccache = NULL;
+               }
+       }
+       
+       #endif /* cc_context_open_ccache */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+int check_cc_context_open_default_ccache() {
+       BEGIN_TEST("cc_context_open_default_ccache");
+       
+       #ifndef cc_context_open_default_ccache
+       log_error("cc_context_open_default_ccache is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       if (!err) {     
+               // make sure we have a default ccache
+               err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache);
+               if (ccache) { cc_ccache_release(ccache); }
+               
+               // try default ccache
+               if (!err) {
+                       err = check_once_cc_context_open_default_ccache(context, &ccache, ccNoError, NULL);
+               }
+               
+               // try bad parameters
+               err = check_once_cc_context_open_default_ccache(context, NULL, ccErrBadParam, NULL);
+               
+               // try with no default ccache (destroy all ccaches first)
+               err = destroy_all_ccaches(context);
+               
+               err = check_once_cc_context_open_default_ccache(context, &ccache, ccErrCCacheNotFound, NULL);
+       }
+       
+       if (context) { cc_context_release(context); }
+       
+       #endif /* cc_context_open_default_ccache */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_open_default_ccache(cc_context_t context, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) {
+       cc_int32 err = 0;
+       cc_string_t given_name = NULL;
+       cc_string_t default_name = NULL;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_context_open_default_ccache
+       
+       cc_int32 possible_return_values[5] = {
+               ccNoError, 
+               ccErrInvalidContext, 
+               ccErrNoMem, 
+               ccErrCCacheNotFound, 
+               ccErrBadParam, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+               
+       if (ccache != NULL) { // if we were passed NULL, then we're looking to pass a bad param
+               err = cc_context_open_default_ccache(context, ccache);
+       } else {
+               err = cc_context_open_default_ccache(context, NULL);
+       }
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err) {
+               check_if(*ccache == NULL, NULL);
+               
+               // make sure this ccache is the one we were looking to get back (compare name with cc_context_get_default_ccache_name)
+               err = cc_ccache_get_name(*ccache, &given_name);
+               err = cc_context_get_default_ccache_name(context, &default_name);
+               if (given_name && default_name) {
+                       check_if(strcmp(given_name->data, default_name->data), "name of ccache returned by cc_context_open_default_ccache doesn't match name returned by cc_context_get_default_ccache_name");
+               }
+               if (given_name) { cc_string_release(given_name); }
+               if (default_name) { cc_string_release(default_name); }
+               
+               if (ccache && *ccache) {
+                       cc_ccache_release(*ccache);
+                       *ccache = NULL;
+               }
+       }
+       
+       #endif /* cc_context_open_default_ccache */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+int check_cc_context_create_ccache() {
+       BEGIN_TEST("cc_context_create_ccache");
+       
+       #ifndef cc_context_create_ccache
+       log_error("cc_context_create_ccache is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       cc_string_t name = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       if (!err) {     
+               // try making a ccache with a non-unique name (the existing default's name)
+               if (!err) {
+                       err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache);
+               }
+               if (!err) {
+                       err = cc_ccache_get_name(ccache, &name);
+               }
+               if (ccache) { cc_ccache_release(ccache); }
+               if (!err) {
+                       err = check_once_cc_context_create_ccache(context, name->data, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccNoError, NULL);
+               }
+               
+               // try making a ccache with a unique name (the now destroyed default's name)
+               if (ccache) { cc_ccache_destroy(ccache); }
+               if (!err) {
+                       err = check_once_cc_context_create_ccache(context, name->data, cc_credentials_v5, "foo/baz@BAR.ORG", &ccache, ccNoError, NULL);
+               }
+                               
+               // try bad parameters
+               err = check_once_cc_context_create_ccache(context, NULL, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccErrBadName, "NULL name");                    // NULL name
+               err = check_once_cc_context_create_ccache(context, "name", cc_credentials_v4_v5, "foo@BAR.ORG", &ccache, ccErrBadCredentialsVersion, "invalid creds_vers"); // invalid creds_vers
+               err = check_once_cc_context_create_ccache(context, "name", cc_credentials_v5, NULL, &ccache, ccErrBadParam, "NULL principal");                          // NULL principal
+               err = check_once_cc_context_create_ccache(context, "name", cc_credentials_v5, "foo@BAR.ORG", NULL, ccErrBadParam, "NULL ccache");                    // NULL ccache
+       }
+       
+       if (name) { cc_string_release(name); }
+       if (ccache) { cc_ccache_destroy(ccache); }
+       if (context) { cc_context_release(context); }
+       
+       #endif /* cc_context_create_ccache */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_create_ccache(cc_context_t context, const char *name, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) {
+       cc_int32 err = 0;
+       cc_string_t stored_name = NULL;
+       cc_string_t stored_principal = NULL;
+       cc_uint32 stored_creds_vers = 0;
+
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_context_create_ccache
+       
+       cc_int32 possible_return_values[6] = {
+               ccNoError, 
+               ccErrBadName, 
+               ccErrBadParam, 
+               ccErrInvalidContext, 
+               ccErrNoMem, 
+               ccErrBadCredentialsVersion, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+               
+       err = cc_context_create_ccache(context, name, cred_vers, principal, ccache);
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err) {
+               check_if(*ccache == NULL, NULL);
+               
+               // make sure all of the ccache's info matches what we gave it
+               // name
+               err = cc_ccache_get_name(*ccache, &stored_name);
+               if (!err) { check_if(strcmp(stored_name->data, name), NULL); }
+               if (stored_name) { cc_string_release(stored_name); }
+               // cred_vers
+               // FIXME Documented function name of cc_ccache_get_credentials_version is a typo.
+               // FIXME Documented type of creds param the wrong signedness (should be unsigned) for cc_ccache_get_credentials_version, cc_context_create_ccache, cc_context_create_default_ccache, cc_context_create_new_ccache
+               err = cc_ccache_get_credentials_version(*ccache, &stored_creds_vers);
+               if (!err) { check_if(stored_creds_vers != cred_vers, NULL); }
+               // principal
+               err = cc_ccache_get_principal(*ccache, cc_credentials_v5, &stored_principal);
+               if (!err) { check_if(strcmp(stored_principal->data, principal), NULL); }
+               if (stored_principal) { cc_string_release(stored_principal); }
+                               
+               if (ccache && *ccache) {
+                       cc_ccache_destroy(*ccache);
+                       *ccache = NULL;
+               }
+       }
+       
+       #endif /* cc_context_create_ccache */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+int check_cc_context_create_default_ccache() {
+       BEGIN_TEST("cc_context_create_default_ccache");
+       
+       #ifndef cc_context_create_default_ccache
+       log_error("cc_context_create_default_ccache is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       cc_string_t name = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       if (!err) {     
+               // try making the default when there are no existing ccaches
+               err = destroy_all_ccaches(context);
+               if (!err) {
+                       err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccNoError, NULL);
+               }
+               if (ccache) { cc_ccache_release(ccache); }
+               
+               // try making a new default when one already exists
+               if (!err) {
+                       err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, "foo/baz@BAR.ORG", &ccache, ccNoError, NULL);
+               }
+               
+               // try bad parameters
+               err = check_once_cc_context_create_default_ccache(context, cc_credentials_v4_v5, "foo@BAR.ORG", &ccache, ccErrBadCredentialsVersion, "invalid creds_vers"); // invalid creds_vers
+               err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, NULL, &ccache, ccErrBadParam, "NULL principal");                          // NULL principal
+               err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", NULL, ccErrBadParam, "NULL ccache");                    // NULL ccache
+       }
+       
+       if (name) { cc_string_release(name); }
+       if (ccache) { cc_ccache_destroy(ccache); }
+       if (context) { cc_context_release(context); }
+       
+       #endif /* cc_context_create_default_ccache */
+       
+       END_TEST_AND_RETURN     
+}
+
+cc_int32 check_once_cc_context_create_default_ccache(cc_context_t context, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) {
+       cc_int32 err = 0;
+       cc_string_t stored_principal = NULL;
+       cc_uint32 stored_creds_vers = 0;
+
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_context_create_default_ccache
+       
+       cc_int32 possible_return_values[6] = {
+               ccNoError, 
+               ccErrBadName, // how can this be possible when the name isn't a parameter?
+               ccErrBadParam, 
+               ccErrInvalidContext, 
+               ccErrNoMem, 
+               ccErrBadCredentialsVersion, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+               
+       err = cc_context_create_default_ccache(context, cred_vers, principal, ccache);
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err) {
+               if (ccache) { check_if(*ccache == NULL, NULL); }
+               // make sure all of the ccache's info matches what we gave it
+               // cred_vers
+               err = cc_ccache_get_credentials_version(*ccache, &stored_creds_vers);
+               if (!err) { check_if(stored_creds_vers != cred_vers, NULL); }
+               // principal
+               err = cc_ccache_get_principal(*ccache, cc_credentials_v5, &stored_principal);
+               if (!err) { check_if(strcmp(stored_principal->data, principal), NULL); }
+               if (stored_principal) { cc_string_release(stored_principal); }
+                               
+               if (ccache && *ccache) {
+                       cc_ccache_release(*ccache);
+                       *ccache = NULL;
+               }
+       }
+       
+       #endif /* cc_context_create_default_ccache */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+int check_cc_context_create_new_ccache() {
+       BEGIN_TEST("cc_context_create_new_ccache");
+       
+       #ifndef cc_context_create_new_ccache
+       log_error("cc_context_create_new_ccache is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       cc_string_t name = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       if (!err) {     
+               // try making when there are no existing ccaches (should have name of default)
+               err = destroy_all_ccaches(context);
+               if (!err) {
+                       err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccNoError, NULL);
+               }
+               if (ccache) { cc_ccache_release(ccache); }
+               
+               // try making a new ccache when one already exists (should not have name of default)
+               if (!err) {
+                       err = check_once_cc_context_create_new_ccache(context, 0, cc_credentials_v5, "foo/baz@BAR.ORG", &ccache, ccNoError, NULL);
+               }
+               if (ccache) { cc_ccache_release(ccache); }
+               
+               // try bad parameters
+               err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v4_v5, "foo@BAR.ORG", &ccache, ccErrBadCredentialsVersion, "invalid creds_vers"); // invalid creds_vers
+               err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v5, NULL, &ccache, ccErrBadParam, "NULL principal");                          // NULL principal
+               err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v5, "foo@BAR.ORG", NULL, ccErrBadParam, "NULL ccache");                    // NULL ccache
+       }
+       
+       if (name) { cc_string_release(name); }
+       if (ccache) { cc_ccache_destroy(ccache); }
+       if (context) { cc_context_release(context); }
+       
+       #endif /* cc_context_create_new_ccache */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_create_new_ccache(cc_context_t context, cc_int32 should_be_default, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) {
+       cc_int32 err = 0;
+       cc_string_t name = NULL;
+       cc_string_t stored_name = NULL;
+       cc_string_t stored_principal = NULL;
+       cc_uint32 stored_creds_vers = 0;
+       
+       BEGIN_CHECK_ONCE(description);
+       
+       #ifdef cc_context_create_new_ccache
+       
+       cc_int32 possible_return_values[6] = {
+               ccNoError, 
+               ccErrBadName, // how can this be possible when the name isn't a parameter?
+               ccErrBadParam, 
+               ccErrInvalidContext, 
+               ccErrNoMem, 
+               ccErrBadCredentialsVersion, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+               
+       err = cc_context_create_new_ccache(context, cred_vers, principal, ccache);
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       if (!err) {
+               if (ccache) { check_if(*ccache == NULL, NULL); }
+               // make sure all of the ccache's info matches what we gave it
+               if (!err) {
+                       err = cc_context_get_default_ccache_name(context, &name);
+               }
+               if (!err) {
+                       err = cc_ccache_get_name(*ccache, &stored_name);
+               }
+               if (!err) { 
+                       if (should_be_default) {
+                               check_if(strcmp(stored_name->data, name->data), "new ccache does not have name of default"); 
+                       }
+                       else {
+                               check_if((strcmp(stored_name->data, name->data) == 0), "new cache has name of default"); 
+                       }       
+               }
+               if (name) { cc_string_release(name); }
+               if (stored_name) { cc_string_release(stored_name); }
+               
+               // cred_vers
+               err = cc_ccache_get_credentials_version(*ccache, &stored_creds_vers);
+               if (!err) { check_if(stored_creds_vers != cred_vers, NULL); }
+               // principal
+               err = cc_ccache_get_principal(*ccache, cc_credentials_v5, &stored_principal);
+               if (!err) { check_if(strcmp(stored_principal->data, principal), NULL); }
+               if (stored_principal) { cc_string_release(stored_principal); }
+                               
+               if (ccache && *ccache) {
+                       cc_ccache_release(*ccache);
+                       *ccache = NULL;
+               }
+       }
+       
+       #endif /* cc_context_create_new_ccache */
+       
+       END_CHECK_ONCE;
+       
+       return err;
+}
+
+int check_cc_context_new_ccache_iterator() {
+       BEGIN_TEST("cc_context_new_ccache_iterator");
+       
+       #ifndef cc_context_new_ccache_iterator
+       log_error("cc_context_new_ccache_iterator is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       cc_string_t name = NULL;
+       cc_ccache_iterator_t iterator = NULL;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       if (!err) {     
+               err = destroy_all_ccaches(context);
+       }
+       if (!err) {     
+               // try making when there are no existing ccaches (shouldn't make a difference, but just in case)
+               check_once_cc_context_new_ccache_iterator(context, &iterator, ccNoError, "when there are no existing ccaches");
+       
+               err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+       if (!err) {     
+               // try making when at least one ccache already exists (just to cover all our bases)
+               check_once_cc_context_new_ccache_iterator(context, &iterator, ccNoError, "when at least one ccache already exists");
+               
+               // try bad parameters
+               check_once_cc_context_new_ccache_iterator(context, NULL, ccErrBadParam, "NULL param"); // NULL iterator
+       }
+               // we'll do a comprehensive test of cc_ccache_iterator related functions later in the test suite
+       
+       if (name) { cc_string_release(name); }
+       if (ccache) { cc_ccache_destroy(ccache); }
+       if (context) { cc_context_release(context); }
+       
+       #endif /* cc_context_new_ccache_iterator */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_new_ccache_iterator(cc_context_t context, cc_ccache_iterator_t *iterator, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+
+       BEGIN_CHECK_ONCE(description);
+
+       #ifdef cc_context_create_new_ccache
+       
+       cc_int32 possible_return_values[4] = {
+               ccNoError, 
+               ccErrBadParam, 
+               ccErrNoMem, 
+               ccErrInvalidContext, 
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       err = cc_context_new_ccache_iterator(context, iterator);
+               
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       // we'll do a comprehensive test of cc_ccache_iterator related functions later
+       
+       #endif /* cc_context_create_new_ccache */
+       
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+int check_cc_context_compare(){
+       BEGIN_TEST("cc_context_compare");
+       
+       #ifndef cc_context_compare
+       log_error("cc_context_compare is not implemented yet");
+       failure_count++;
+       #else
+       
+       cc_int32 err = 0;
+       cc_context_t context_a = NULL;
+       cc_context_t context_b = NULL;
+       cc_uint32 equal = 0;
+       
+       err = cc_initialize(&context_a, ccapi_version_3, NULL, NULL);
+       if (!err) {
+               err = cc_initialize(&context_b, ccapi_version_3, NULL, NULL);
+       }
+
+       check_once_cc_context_compare(context_a, context_a, &equal, ccNoError, "valid params, same contexts");
+       check_once_cc_context_compare(context_a, context_b, &equal, ccNoError, "valid params, different contexts");
+       check_once_cc_context_compare(context_a, NULL, &equal, ccErrInvalidContext, "NULL compare_to context");
+       check_once_cc_context_compare(context_a, context_b, NULL, ccErrBadParam, "NULL out param");
+
+       if (context_a) { cc_context_release(context_a); }
+       if (context_b) { cc_context_release(context_b); }
+       
+       #endif /* cc_context_compare */
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_context_compare(cc_context_t context, cc_context_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+
+       BEGIN_CHECK_ONCE(description);
+
+       #ifdef cc_context_compare
+       
+       cc_int32 possible_return_values[4] = {
+               ccNoError, 
+               ccErrInvalidContext, 
+               ccErrBadParam, 
+               ccErrServerUnavailable,
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+       
+       err = cc_context_compare(context, compare_to, equal);
+       
+       if (!err) {
+               *equal = 0;
+       }
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       #endif /* cc_context_compare */
+       
+       return err;
+}
diff --git a/src/ccapi/test/test_ccapi_context.h b/src/ccapi/test/test_ccapi_context.h
new file mode 100644 (file)
index 0000000..e347692
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _TEST_CCAPI_CONTEXT_H_
+#define _TEST_CCAPI_CONTEXT_H_
+
+#include <Kerberos/CredentialsCache.h>
+
+int check_cc_initialize();
+cc_int32 check_once_cc_initialize(cc_context_t *out_context, cc_int32 in_version, cc_int32 *out_supported_version, char const **out_vendor, cc_int32 expected_err, const char *description);
+int check_cc_context_get_version();
+cc_int32 check_once_cc_context_get_version(cc_context_t *out_context, cc_int32 in_version, cc_int32 *out_supported_version, char const **out_vendor, cc_int32 expected_err, const char *description);
+int check_get_version();
+cc_int32 check_once_get_version(cc_context_t *out_context, cc_int32 in_version, cc_int32 *out_supported_version, char const **out_vendor, cc_int32 expected_err, const char *description);
+int check_cc_context_release();
+cc_int32 check_once_cc_context_release(cc_context_t *out_context, cc_int32 expected_err, const char *description);
+int check_cc_context_get_change_time();
+cc_int32 check_once_cc_context_get_change_time(cc_context_t context, cc_time_t *time, cc_int32 expected_err, const char *description);
+int check_cc_context_get_default_ccache_name();
+cc_int32 check_once_cc_context_get_default_ccache_name(cc_context_t context, cc_string_t *name, cc_int32 expected_err, const char *description);
+int check_cc_context_open_ccache();
+cc_int32 check_once_cc_context_open_ccache(cc_context_t context, const char *name, cc_ccache_t *ccache, cc_int32 expected_err, const char *description);
+int check_cc_context_open_default_ccache();
+cc_int32 check_once_cc_context_open_default_ccache(cc_context_t context, cc_ccache_t *ccache, cc_int32 expected_err, const char *description);
+int check_cc_context_create_ccache();
+cc_int32 check_once_cc_context_create_ccache(cc_context_t context, const char *name, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description);
+int check_cc_context_create_default_ccache();
+cc_int32 check_once_cc_context_create_default_ccache(cc_context_t context, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description);
+int check_cc_context_create_new_ccache();
+cc_int32 check_once_cc_context_create_new_ccache(cc_context_t context, cc_int32 should_be_default, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description);
+int check_cc_context_new_ccache_iterator();
+cc_int32 check_once_cc_context_new_ccache_iterator(cc_context_t context, cc_ccache_iterator_t *iterator, cc_int32 expected_err, const char *description);
+
+int check_cc_context_compare();
+cc_int32 check_once_cc_context_compare(cc_context_t context, cc_context_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description);
+
+#endif /* _TEST_CCAPI_CONTEXT_H_ */
diff --git a/src/ccapi/test/test_ccapi_globals.c b/src/ccapi/test/test_ccapi_globals.c
new file mode 100644 (file)
index 0000000..c508c18
--- /dev/null
@@ -0,0 +1,62 @@
+#include "test_ccapi_globals.h"
+
+/* GLOBALS */
+unsigned int total_failure_count = 0;
+unsigned int failure_count = 0;
+
+const char *current_test_name;
+const char *current_test_activity;
+
+const char * ccapi_error_strings[30] = {
+       
+       "ccNoError",                                            /* 0 */
+       "ccIteratorEnd",                                        /* 201 */
+    "ccErrBadParam",
+    "ccErrNoMem",
+    "ccErrInvalidContext",
+    "ccErrInvalidCCache",
+
+    "ccErrInvalidString",                              /* 206 */
+    "ccErrInvalidCredentials",
+    "ccErrInvalidCCacheIterator",
+    "ccErrInvalidCredentialsIterator",
+    "ccErrInvalidLock",
+
+    "ccErrBadName",                                            /* 211 */
+    "ccErrBadCredentialsVersion",
+    "ccErrBadAPIVersion",
+    "ccErrContextLocked",
+    "ccErrContextUnlocked",
+
+    "ccErrCCacheLocked",                               /* 216 */
+    "ccErrCCacheUnlocked",
+    "ccErrBadLockType",
+    "ccErrNeverDefault",
+    "ccErrCredentialsNotFound",
+
+    "ccErrCCacheNotFound",                             /* 221 */
+    "ccErrContextNotFound",
+    "ccErrServerUnavailable",
+    "ccErrServerInsecure",
+    "ccErrServerCantBecomeUID",
+    
+    "ccErrTimeOffsetNotSet",                   /* 226 */
+    "ccErrBadInternalMessage",
+    "ccErrNotImplemented",
+       
+};
+
+const char *translate_ccapi_error(cc_int32 err) {
+       
+       if (err == 0) {
+               return ccapi_error_strings[0];
+       }
+       else if (err >= 201 && err <= 228){
+               return ccapi_error_strings[err - 200];
+       }
+       else {
+               return "\"Invalid or private CCAPI error\"";
+       }
+       
+       return "";
+}
\ No newline at end of file
diff --git a/src/ccapi/test/test_ccapi_globals.h b/src/ccapi/test/test_ccapi_globals.h
new file mode 100644 (file)
index 0000000..cebfb63
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef _TEST_CCAPI_GLOBALS_H_
+#define _TEST_CCAPI_GLOBALS_H_
+
+#include <Kerberos/CredentialsCache.h>
+
+/* GLOBALS */
+extern unsigned int total_failure_count;
+extern unsigned int failure_count;
+
+extern const char *current_test_name;
+extern const char *current_test_activity;
+
+extern const char * ccapi_error_strings[30];
+
+const char *translate_ccapi_error(cc_int32 err);
+
+#define T_CCAPI_INIT \
+               do { \
+                       current_test_name = NULL; \
+                       current_test_activity = NULL; \
+               } while( 0 )
+
+#define BEGIN_TEST(name) \
+               do { \
+                       current_test_name = name; \
+                       failure_count = 0; \
+                       test_header(current_test_name); \
+               } while( 0 )
+
+#define BEGIN_CHECK_ONCE(x) \
+               do { \
+                       if (x) { \
+                               current_test_activity = x; \
+                       } \
+               } while( 0 )
+
+#define END_CHECK_ONCE \
+               do { \
+                       current_test_activity = NULL; \
+               } while( 0 )
+
+#define END_TEST_AND_RETURN \
+               test_footer(current_test_name, failure_count); \
+               total_failure_count += failure_count; \
+               return failure_count;
+
+#endif /* _TEST_CCAPI_GLOBALS_H_ */
diff --git a/src/ccapi/test/test_ccapi_iterators.c b/src/ccapi/test/test_ccapi_iterators.c
new file mode 100644 (file)
index 0000000..afc8556
--- /dev/null
@@ -0,0 +1,244 @@
+#include "test_ccapi_iterators.h"
+#include "test_ccapi_check.h"
+#include "test_ccapi_util.h"
+
+
+// ---------------------------------------------------------------------------
+
+int check_cc_ccache_iterator_next() {
+       BEGIN_TEST("cc_ccache_iterator_next");
+               
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       cc_ccache_iterator_t iterator = NULL;
+       unsigned int i;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       
+       // iterate with no ccaches
+       if (!err) {
+               err = cc_context_new_ccache_iterator(context, &iterator);
+       }
+       check_once_cc_ccache_iterator_next(iterator, 0, ccNoError, "iterating over an empty collection");
+       if (iterator) {
+               cc_ccache_iterator_release(iterator);
+               iterator = NULL;
+       }
+       
+       // iterate with one ccache
+       if (!err) {
+               destroy_all_ccaches(context);
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+       if (ccache) {
+               cc_ccache_release(ccache);
+               ccache = NULL;
+       }
+       if (!err) {
+               err = cc_context_new_ccache_iterator(context, &iterator);
+       }
+       check_once_cc_ccache_iterator_next(iterator, 1, ccNoError, "iterating over a collection of 1 ccache");
+       if (iterator) {
+               cc_ccache_iterator_release(iterator);
+               iterator = NULL;
+       }
+       
+       // iterate with several ccaches
+       if (!err) {
+               destroy_all_ccaches(context);
+       }
+       for(i = 0; !err && (i < 1000); i++)
+       {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+               if (ccache) {
+                       cc_ccache_release(ccache);
+                       ccache = NULL;
+               }
+       }
+       if (!err) {
+               err = cc_context_new_ccache_iterator(context, &iterator);
+       }
+       check_once_cc_ccache_iterator_next(iterator, 1000, ccNoError, "iterating over a collection of 1000 ccache");
+       if (iterator) {
+               cc_ccache_iterator_release(iterator);
+               iterator = NULL;
+       }
+       
+
+       if (ccache) { cc_ccache_release(ccache); }
+       if (iterator) { cc_ccache_iterator_release(iterator); }
+       if (context) { 
+               destroy_all_ccaches(context);
+               cc_context_release(context);
+       }
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_ccache_iterator_next(cc_ccache_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+
+       BEGIN_CHECK_ONCE(description);
+
+       cc_int32 possible_return_values[6] = {
+               ccNoError, 
+               ccIteratorEnd, 
+               ccErrBadParam, 
+               ccErrNoMem, 
+               ccErrInvalidCCacheIterator, 
+               ccErrCCacheNotFound,
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+       cc_ccache_t ccache = NULL;
+       cc_uint32 actual_count = 0;
+
+       while (!err) {
+               err = cc_ccache_iterator_next(iterator, &ccache);
+               if (ccache) {
+                       actual_count++;
+                       cc_ccache_release(ccache);
+                       ccache = NULL;
+               }
+       }
+       if (err == ccIteratorEnd) {
+               err = ccNoError;
+       }
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches");
+
+       END_CHECK_ONCE;
+
+       return err;     
+}
+
+
+// ---------------------------------------------------------------------------
+
+int check_cc_credentials_iterator_next() {
+       BEGIN_TEST("cc_credentials_iterator_next");
+               
+       cc_int32 err = 0;
+       cc_context_t context = NULL;
+       cc_ccache_t ccache = NULL;
+       cc_credentials_union creds_union;
+       cc_credentials_iterator_t iterator = NULL;
+       unsigned int i;
+       
+       err = cc_initialize(&context, ccapi_version_3, NULL, NULL);
+       
+       if (!err) {
+               err = destroy_all_ccaches(context);
+       }
+       
+       // iterate with no creds
+       if (!err) {
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+       if (!err) {
+               err = cc_ccache_new_credentials_iterator(ccache, &iterator);
+       }
+       check_once_cc_credentials_iterator_next(iterator, 0, ccNoError, "iterating over an empty ccache");
+       if (iterator) {
+               cc_ccache_iterator_release(iterator);
+               iterator = NULL;
+       }
+       if (ccache) {
+               cc_ccache_release(ccache);
+               ccache = NULL;
+       }
+       
+       // iterate with one cred
+       if (!err) {
+               destroy_all_ccaches(context);
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+       if (!err) {
+               new_v5_creds_union(&creds_union, "BAR.ORG");
+               err = cc_ccache_store_credentials(ccache, &creds_union);
+               release_v5_creds_union(&creds_union);
+       }
+       if (!err) {
+               err = cc_ccache_new_credentials_iterator(ccache, &iterator);
+       }
+       check_once_cc_credentials_iterator_next(iterator, 1, ccNoError, "iterating over a ccache with 1 cred");
+       if (iterator) {
+               cc_credentials_iterator_release(iterator);
+               iterator = NULL;
+       }
+       if (ccache) {
+               cc_ccache_release(ccache);
+               ccache = NULL;
+       }
+       
+       // iterate with several creds
+       if (!err) {
+               destroy_all_ccaches(context);
+               err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache);
+       }
+       for(i = 0; !err && (i < 1000); i++) {
+               new_v5_creds_union(&creds_union, "BAR.ORG");
+               err = cc_ccache_store_credentials(ccache, &creds_union);
+               release_v5_creds_union(&creds_union);
+       }
+       if (!err) {
+               err = cc_ccache_new_credentials_iterator(ccache, &iterator);
+       }
+       check_once_cc_credentials_iterator_next(iterator, 1000, ccNoError, "iterating over a ccache with 1000 creds");  
+
+       if (ccache) { cc_ccache_release(ccache); }
+       if (iterator) { cc_credentials_iterator_release(iterator); }
+       if (context) { 
+               destroy_all_ccaches(context);
+               cc_context_release(context);
+       }
+       
+       END_TEST_AND_RETURN
+}
+
+cc_int32 check_once_cc_credentials_iterator_next(cc_credentials_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description) {
+       cc_int32 err = ccNoError;
+
+       BEGIN_CHECK_ONCE(description);
+
+       cc_int32 possible_return_values[5] = {
+               ccNoError, 
+               ccIteratorEnd, 
+               ccErrBadParam, 
+               ccErrNoMem, 
+               ccErrInvalidCredentialsIterator,
+       };
+       #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
+
+       cc_credentials_t creds = NULL;
+       cc_uint32 actual_count = 0;
+
+       while (!err) {
+               err = cc_credentials_iterator_next(iterator, &creds);
+               if (creds) {
+                       actual_count++;
+                       cc_credentials_release(creds);
+                       creds = NULL;
+               }
+       }
+       if (err == ccIteratorEnd) {
+               err = ccNoError;
+       }
+       
+       // check returned error
+       check_err(err, expected_err, possible_return_values);
+       
+       check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches");
+
+       END_CHECK_ONCE;
+
+       return err;     
+}
\ No newline at end of file
diff --git a/src/ccapi/test/test_ccapi_iterators.h b/src/ccapi/test/test_ccapi_iterators.h
new file mode 100644 (file)
index 0000000..4ce8198
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _TEST_CCAPI_ITERATORS_H_
+#define _TEST_CCAPI_ITERATORS_H_
+
+#include <Kerberos/CredentialsCache.h>
+
+int check_cc_ccache_iterator_next();
+cc_int32 check_once_cc_ccache_iterator_next(cc_ccache_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description);
+
+int check_cc_credentials_iterator_next();
+cc_int32 check_once_cc_credentials_iterator_next(cc_credentials_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description);
+
+#endif /* _TEST_CCAPI_ITERATORS_H_ */
diff --git a/src/ccapi/test/test_ccapi_log.c b/src/ccapi/test/test_ccapi_log.c
new file mode 100644 (file)
index 0000000..95a467a
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef _TEST_CCAPI_LOG_C_
+#define _TEST_CCAPI_LOG_C_
+
+#include "test_ccapi_log.h"
+
+void _log_error_v(const char *file, int line, const char *format, va_list ap)
+{
+       fprintf(stdout, "\n\t%s:%d: ", file, line);
+       if (!format) {
+               fprintf(stdout, "An unknown error occurred", file, line);
+       } else {
+               vfprintf(stdout, format, ap);
+       }
+       fflush(stdout);
+}
+
+void _log_error(const char *file, int line, const char *format, ...)
+{      
+       va_list ap;
+       va_start(ap, format);
+       _log_error_v(file, line, format, ap);
+       va_end(ap);
+}
+
+void test_header(const char *msg) {
+       if (msg != NULL) {
+               fprintf(stdout, "\nChecking %s... ", msg);
+               fflush(stdout);
+       }
+}
+
+void test_footer(const char *msg, int err) {
+       if (msg != NULL) {
+               if (!err) {
+                       fprintf(stdout, "OK\n");
+               }
+               else {
+                       fprintf(stdout, "\n*** %d failure%s in %s ***\n", err, (err == 1) ? "" : "s", msg);
+               }               
+       }
+}
+
+
+
+#endif /* _TEST_CCAPI_LOG_C_ */
diff --git a/src/ccapi/test/test_ccapi_log.h b/src/ccapi/test/test_ccapi_log.h
new file mode 100644 (file)
index 0000000..abb79d5
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _TEST_CCAPI_LOG_H_
+#define _TEST_CCAPI_LOG_H_
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "test_ccapi_globals.h"
+
+#define log_error(format, ...) \
+               _log_error(__FILE__, __LINE__, format , ## __VA_ARGS__)
+
+void _log_error_v(const char *file, int line, const char *format, va_list ap);
+void _log_error(const char *file, int line, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
+
+void test_header(const char *msg);
+void test_footer(const char *msg, int err);
+
+#endif /* _TEST_CCAPI_LOG_H_ */
diff --git a/src/ccapi/test/test_ccapi_util.c b/src/ccapi/test/test_ccapi_util.c
new file mode 100644 (file)
index 0000000..d7dc3e1
--- /dev/null
@@ -0,0 +1,140 @@
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <krb5.h>
+#include "test_ccapi_util.h"
+
+
+// ---------------------------------------------------------------------------
+
+cc_int32 destroy_all_ccaches(cc_context_t context) {
+       cc_int32 err = ccNoError;
+       cc_ccache_t ccache = NULL;
+       
+       while (!err) {
+               err = cc_context_open_default_ccache(context, &ccache);
+               if (!err) {
+                       err = cc_ccache_destroy(ccache);
+               }
+       }
+       if (err == ccErrCCacheNotFound) {
+               err = ccNoError;
+       }
+       else {
+               log_error("cc_context_open_default_ccache or cc_ccache_destroy failed with %s (%d)", translate_ccapi_error(err), err);
+       }
+
+       return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+cc_int32 new_v5_creds_union (cc_credentials_union *out_union, const char *realm)
+{
+    cc_int32 err = ccNoError;
+    cc_credentials_union *cred_union = NULL;
+       cc_credentials_v5_t *v5creds = NULL;
+    static num_runs = 1;
+       char *client = NULL;
+       char *server = NULL;
+       
+    if (!out_union) { err = ccErrBadParam; }
+    
+       if (!err) {
+               v5creds = malloc (sizeof (*v5creds));
+               if (!v5creds) {
+                       err = ccErrNoMem;
+               }
+       }
+
+       if (!err) {
+               asprintf(&client, "client@%s", realm);
+               asprintf(&server, "host/%d%s@%s", num_runs++, realm, realm);
+               if (!client || !server) {
+                       err = ccErrNoMem;
+               }
+       }
+
+       if (!err) {
+               v5creds->client = client;
+               v5creds->server = server;
+               v5creds->keyblock.type = 1;
+               v5creds->keyblock.length = 0;
+               v5creds->keyblock.data = NULL;
+               v5creds->authtime = time (NULL);
+               v5creds->starttime = time (NULL);
+               v5creds->endtime = time(NULL) + 1000;
+               v5creds->renew_till = time(NULL) + 10000;
+               v5creds->is_skey = 0;
+               v5creds->ticket_flags = TKT_FLG_FORWARDABLE | TKT_FLG_PROXIABLE | TKT_FLG_RENEWABLE | TKT_FLG_INITIAL;
+               v5creds->addresses = NULL;
+               v5creds->ticket.type = 0;
+               v5creds->ticket.length = 0;
+               v5creds->ticket.data = NULL;
+               v5creds->second_ticket.type = 0;
+               v5creds->second_ticket.length = 0;
+               v5creds->second_ticket.data = NULL;
+               v5creds->authdata = NULL;
+       }
+       
+       
+    if (!err) {
+        cred_union = malloc (sizeof (*cred_union));
+        if (cred_union) { 
+                       cred_union->version = cc_credentials_v5;
+                       cred_union->credentials.credentials_v5 = v5creds;
+        } else { 
+            err = ccErrNoMem; 
+        }
+    }
+       if (!err) {
+               *out_union = *cred_union;
+               cred_union = NULL;
+       }
+    
+    return err;
+}
+
+
+// ---------------------------------------------------------------------------
+
+void release_v5_creds_union(cc_credentials_union *creds_union) {
+       cc_credentials_v5_t *v5creds = NULL;
+       
+       if (creds_union) {
+               if (creds_union->credentials.credentials_v5) {
+                       v5creds = creds_union->credentials.credentials_v5;
+                       if (v5creds->client) { free(v5creds->client); }
+                       if (v5creds->server) { free(v5creds->server); }
+                       if (v5creds->keyblock.data) { free(v5creds->keyblock.data); }
+                       if (v5creds->ticket.data) { free(v5creds->ticket.data); }
+                       if (v5creds->second_ticket.data) { free(v5creds->second_ticket.data); }
+                       free(v5creds);
+               }               
+               //free(creds_union);
+       }
+}
+
+
+// ---------------------------------------------------------------------------
+
+// return zero when both unions are considered equal, non-zero when not
+
+int compare_v5_creds_unions(const cc_credentials_union *a, const cc_credentials_union *b) {
+       int retval = -1;
+       
+       if (a && 
+               b &&
+               (a->version == cc_credentials_v5) &&
+               (a->version == b->version) && 
+               (strcmp(a->credentials.credentials_v5->client, b->credentials.credentials_v5->client) == 0) && 
+               (strcmp(a->credentials.credentials_v5->server, b->credentials.credentials_v5->server) == 0)) 
+       {
+               retval = 0;
+       }
+       
+       return retval;
+}
\ No newline at end of file
diff --git a/src/ccapi/test/test_ccapi_util.h b/src/ccapi/test/test_ccapi_util.h
new file mode 100644 (file)
index 0000000..8c9e51e
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _TEST_CCAPI_UTIL_H_
+#define _TEST_CCAPI_UTIL_H_
+
+#include <Kerberos/CredentialsCache.h>
+#include "test_ccapi_globals.h"
+#include "test_ccapi_log.h"
+
+cc_int32 destroy_all_ccaches(cc_context_t context);
+
+cc_int32 new_v5_creds_union(cc_credentials_union *out_union, const char *realm);
+void release_v5_creds_union(cc_credentials_union *creds_union);
+int compare_v5_creds_unions(const cc_credentials_union *a, const cc_credentials_union *b);
+
+#endif /* _TEST_CCAPI_UTIL_H_ */
diff --git a/src/ccapi/test/test_constants.c b/src/ccapi/test/test_constants.c
new file mode 100644 (file)
index 0000000..9f52e74
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <limits.h>
+#include <Kerberos/Kerberos.h>
+
+#include "test_ccapi_check.h"
+#include "test_ccapi_constants.h"
+#include "test_ccapi_context.h"
+#include "test_ccapi_ccache.h"
+
+int main (int argc, const char * argv[]) {
+    
+       cc_int32 err = ccNoError;
+       T_CCAPI_INIT;
+       err = check_constants();
+    return err;
+}
diff --git a/src/include/CredentialsCache.h b/src/include/CredentialsCache.h
new file mode 100644 (file)
index 0000000..51242bb
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+ * $Header$
+ *
+ * Copyright 1998-2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+#ifndef __CREDENTIALSCACHE__
+#define __CREDENTIALSCACHE__
+
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+#include <TargetConditionals.h>
+#endif
+
+#if defined(_WIN32)
+#include <winsock.h>
+#else
+#include <sys/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if TARGET_OS_MAC
+#pragma pack(push,2)
+#endif    
+
+#if defined(_WIN32)
+#define CCACHE_API     __declspec(dllexport)
+
+#if _INTEGRAL_MAX_BITS >= 64 && _MSC_VER >= 1400 && !defined(_WIN64) && !defined(_USE_32BIT_TIME_T)
+#if defined(_TIME_T_DEFINED) || defined(_INC_IO) || defined(_INC_TIME) || defined(_INC_WCHAR)
+#error time_t has been defined as a 64-bit integer which is incompatible with Kerberos on this platform.
+#endif /* _TIME_T_DEFINED */
+#define _USE_32BIT_TIME_T
+#endif 
+#else
+#define CCACHE_API
+#endif
+
+#include <time.h>
+
+/*
+ * Constants
+ */
+/* API versions */
+enum {
+    ccapi_version_2 = 2,
+    ccapi_version_3 = 3,
+    ccapi_version_4 = 4,
+    ccapi_version_5 = 5,
+    ccapi_version_6 = 6,
+    ccapi_version_max = ccapi_version_6
+};
+/* Errors */
+enum {
+    ccNoError                                          = 0,
+
+    ccIteratorEnd                                      = 201,
+    ccErrBadParam,
+    ccErrNoMem,
+    ccErrInvalidContext,
+    ccErrInvalidCCache,
+
+    ccErrInvalidString,                                        /* 206 */
+    ccErrInvalidCredentials,
+    ccErrInvalidCCacheIterator,
+    ccErrInvalidCredentialsIterator,
+    ccErrInvalidLock,
+
+    ccErrBadName,                                      /* 211 */
+    ccErrBadCredentialsVersion,
+    ccErrBadAPIVersion,
+    ccErrContextLocked,
+    ccErrContextUnlocked,
+
+    ccErrCCacheLocked,                                 /* 216 */
+    ccErrCCacheUnlocked,
+    ccErrBadLockType,
+    ccErrNeverDefault,
+    ccErrCredentialsNotFound,
+
+    ccErrCCacheNotFound,                               /* 221 */
+    ccErrContextNotFound,
+    ccErrServerUnavailable,
+    ccErrServerInsecure,
+    ccErrServerCantBecomeUID,
+    
+    ccErrTimeOffsetNotSet,                             /* 226 */
+    ccErrBadInternalMessage,
+    ccErrNotImplemented,
+    ccErrClientNotFound
+};
+
+/* Credentials versions */
+enum cc_credential_versions {
+    cc_credentials_v4 = 1,
+    cc_credentials_v5 = 2,
+    cc_credentials_v4_v5 = 3
+};
+
+/* Lock types */
+enum cc_lock_types {
+    cc_lock_read = 0,
+    cc_lock_write = 1,
+    cc_lock_upgrade = 2,
+    cc_lock_downgrade = 3
+};
+
+/* Locking Modes */
+enum cc_lock_modes {
+    cc_lock_noblock = 0,
+    cc_lock_block = 1
+};
+
+/* Basic types */
+typedef uint32_t            cc_uint32;
+typedef int32_t             cc_int32;
+#if defined (WIN32)
+typedef __int64             cc_int64;
+typedef unsigned __int64    cc_uint64;
+#else
+typedef int64_t             cc_int64;
+typedef uint64_t            cc_uint64;
+#endif
+typedef cc_uint32           cc_time_t;
+
+/* API types */
+/* Forward declarations */
+struct cc_context_f;
+typedef struct cc_context_f cc_context_f;
+
+struct cc_ccache_f;
+typedef struct cc_ccache_f cc_ccache_f;
+
+struct cc_ccache_iterator_f;
+typedef struct cc_ccache_iterator_f cc_ccache_iterator_f;
+
+struct cc_ccache_iterator_f;
+typedef struct cc_credentials_iterator_f cc_credentials_iterator_f;
+
+struct cc_string_f;
+typedef struct cc_string_f cc_string_f;
+
+struct cc_credentials_f;
+typedef struct cc_credentials_f cc_credentials_f;
+
+/* Credentials types */
+
+enum { /* Make sure all of these are multiples of four (for alignment sanity) */
+    cc_v4_name_size     = 40,
+    cc_v4_instance_size        = 40,
+    cc_v4_realm_size    = 40,
+    cc_v4_ticket_size   = 1254,
+    cc_v4_key_size      = 8
+};
+
+enum cc_string_to_key_type {
+    cc_v4_stk_afs = 0,
+    cc_v4_stk_des = 1,
+    cc_v4_stk_columbia_special = 2,
+    cc_v4_stk_krb5 = 3,
+    cc_v4_stk_unknown = 4
+};
+
+struct cc_credentials_v4_t {
+    cc_uint32       version;
+    char            principal [cc_v4_name_size];
+    char            principal_instance [cc_v4_instance_size];
+    char            service [cc_v4_name_size];
+    char            service_instance [cc_v4_instance_size];
+    char            realm [cc_v4_realm_size];
+    unsigned char   session_key [cc_v4_key_size];
+    cc_int32        kvno;
+    cc_int32        string_to_key_type;
+    cc_time_t       issue_date;
+    cc_int32        lifetime;
+    cc_uint32       address;
+    cc_int32        ticket_size;
+    unsigned char   ticket [cc_v4_ticket_size];
+};      
+typedef struct cc_credentials_v4_t cc_credentials_v4_t;
+
+struct cc_data {
+    cc_uint32                  type;
+    cc_uint32                  length;
+    void*                      data;
+};      
+typedef struct cc_data cc_data;
+
+struct cc_credentials_v5_t {
+    char*      client;
+    char*      server;
+    cc_data    keyblock;
+    cc_time_t  authtime;
+    cc_time_t  starttime;
+    cc_time_t  endtime;
+    cc_time_t  renew_till;
+    cc_uint32  is_skey;
+    cc_uint32  ticket_flags;
+    cc_data**  addresses;
+    cc_data    ticket;
+    cc_data    second_ticket;
+    cc_data**  authdata;
+};      
+typedef struct cc_credentials_v5_t cc_credentials_v5_t;
+
+struct cc_credentials_union {
+    cc_uint32                  version;
+    union {
+        cc_credentials_v4_t*   credentials_v4;
+        cc_credentials_v5_t*   credentials_v5;
+    }                          credentials;
+};
+typedef struct cc_credentials_union cc_credentials_union;
+
+/* Exposed parts */
+
+struct cc_context_d {
+    const cc_context_f *functions;
+#if TARGET_OS_MAC
+    const cc_context_f *vector_functions;
+#endif
+};
+typedef struct cc_context_d cc_context_d;
+typedef cc_context_d *cc_context_t;
+
+struct cc_ccache_d {
+    const cc_ccache_f *functions;
+#if TARGET_OS_MAC
+    const cc_ccache_f *vector_functions;
+#endif
+};
+typedef struct cc_ccache_d cc_ccache_d;
+typedef cc_ccache_d *cc_ccache_t;
+
+struct cc_ccache_iterator_d {
+    const cc_ccache_iterator_f *functions;
+#if TARGET_OS_MAC
+    const cc_ccache_iterator_f *vector_functions;
+#endif
+};
+typedef struct cc_ccache_iterator_d cc_ccache_iterator_d;
+typedef cc_ccache_iterator_d *cc_ccache_iterator_t;
+
+struct cc_credentials_iterator_d {
+    const cc_credentials_iterator_f *functions;
+#if TARGET_OS_MAC
+    const cc_credentials_iterator_f *vector_functions;
+#endif
+};
+typedef struct cc_credentials_iterator_d cc_credentials_iterator_d;
+typedef cc_credentials_iterator_d *cc_credentials_iterator_t;
+
+struct cc_string_d {
+    const char *data;
+    const cc_string_f *functions;
+#if TARGET_OS_MAC
+    const cc_string_f *vector_functions;
+#endif
+};
+typedef struct cc_string_d cc_string_d;
+typedef cc_string_d *cc_string_t;
+
+struct cc_credentials_d {
+    const cc_credentials_union *data;
+    const cc_credentials_f *functions;
+#if TARGET_OS_MAC
+    const cc_credentials_f *otherFunctions;
+#endif
+};
+typedef struct cc_credentials_d cc_credentials_d;
+typedef cc_credentials_d *cc_credentials_t;
+
+/* Function pointer structs */
+
+struct  cc_context_f {
+    cc_int32 (*release) (cc_context_t in_context);
+    
+    cc_int32 (*get_change_time) (cc_context_t  in_context,
+                                 cc_time_t    *out_time);
+    
+    cc_int32 (*get_default_ccache_name) (cc_context_t  in_context,
+                                         cc_string_t  *out_name);
+    
+    cc_int32 (*open_ccache) (cc_context_t  in_context,
+                             const char   *in_name,
+                             cc_ccache_t  *out_ccache);
+    
+    cc_int32 (*open_default_ccache) (cc_context_t  in_context,
+                                     cc_ccache_t  *out_ccache);
+    
+    cc_int32 (*create_ccache) (cc_context_t  in_context,
+                               const char   *in_name,
+                               cc_uint32     in_cred_vers,
+                               const char   *in_principal, 
+                               cc_ccache_t  *out_ccache);
+    
+    cc_int32 (*create_default_ccache) (cc_context_t  in_context,
+                                       cc_uint32     in_cred_vers,
+                                       const char   *in_principal, 
+                                       cc_ccache_t  *out_ccache);
+    
+    cc_int32 (*create_new_ccache) (cc_context_t in_context,
+                                   cc_uint32    in_cred_vers,
+                                   const char  *in_principal, 
+                                   cc_ccache_t *out_ccache);
+    
+    cc_int32 (*new_ccache_iterator) (cc_context_t          in_context,
+                                     cc_ccache_iterator_t *out_iterator);
+    
+    cc_int32 (*lock) (cc_context_t in_context,
+                      cc_uint32    in_lock_type,
+                      cc_uint32    in_block);
+    
+    cc_int32 (*unlock) (cc_context_t in_cc_context);
+    
+    cc_int32 (*compare) (cc_context_t  in_cc_context,
+                         cc_context_t  in_compare_to_context,
+                         cc_uint32    *out_equal);
+
+    cc_int32 (*wait_for_change) (cc_context_t  in_cc_context);
+};
+
+struct cc_ccache_f {
+    cc_int32 (*release) (cc_ccache_t io_ccache);
+    
+    cc_int32 (*destroy) (cc_ccache_t io_ccache);
+    
+    cc_int32 (*set_default) (cc_ccache_t io_ccache);
+    
+    cc_int32 (*get_credentials_version) (cc_ccache_t  in_ccache,
+                                         cc_uint32   *out_credentials_version);
+    
+    cc_int32 (*get_name) (cc_ccache_t  in_ccache,
+                          cc_string_t *out_name);
+    
+    cc_int32 (*get_principal) (cc_ccache_t  in_ccache,
+                               cc_uint32    in_credentials_version,
+                               cc_string_t *out_principal);
+    
+    cc_int32 (*set_principal) (cc_ccache_t  io_ccache,
+                               cc_uint32    in_credentials_version,
+                               const char  *in_principal);
+    
+    cc_int32 (*store_credentials) (cc_ccache_t                 io_ccache,
+                                   const cc_credentials_union *in_credentials_union);
+    
+    cc_int32 (*remove_credentials) (cc_ccache_t      io_ccache,
+                                    cc_credentials_t in_credentials);
+    
+    cc_int32 (*new_credentials_iterator) (cc_ccache_t                in_ccache,
+                                          cc_credentials_iterator_t *out_credentials_iterator);
+    
+    cc_int32 (*move) (cc_ccache_t io_source_ccache,
+                      cc_ccache_t io_destination_ccache);
+    
+    cc_int32 (*lock) (cc_ccache_t io_ccache,
+                      cc_uint32   in_lock_type,
+                      cc_uint32   in_block);
+    
+    cc_int32 (*unlock) (cc_ccache_t io_ccache);
+    
+    cc_int32 (*get_last_default_time) (cc_ccache_t  in_ccache,
+                                       cc_time_t   *out_last_default_time);
+    
+    cc_int32 (*get_change_time) (cc_ccache_t  in_ccache,
+                                 cc_time_t   *out_change_time);
+    
+    cc_int32 (*compare) (cc_ccache_t  in_ccache,
+                         cc_ccache_t  in_compare_to_ccache,
+                         cc_uint32   *out_equal);
+    
+    cc_int32 (*get_kdc_time_offset) (cc_ccache_t  in_ccache,
+                                     cc_uint32    in_credentials_version,
+                                     cc_time_t   *out_time_offset);
+    
+    cc_int32 (*set_kdc_time_offset) (cc_ccache_t io_ccache,
+                                     cc_uint32   in_credentials_version,
+                                     cc_time_t   in_time_offset);
+    
+    cc_int32 (*clear_kdc_time_offset) (cc_ccache_t io_ccache,
+                                       cc_uint32   in_credentials_version);
+    
+    cc_int32 (*wait_for_change) (cc_ccache_t  in_ccache);
+};
+
+struct cc_string_f {
+    cc_int32 (*release) (cc_string_t in_string);
+};
+
+struct cc_credentials_f {
+    cc_int32 (*release) (cc_credentials_t  io_credentials);
+    
+    cc_int32 (*compare) (cc_credentials_t  in_credentials,
+                         cc_credentials_t  in_compare_to_credentials,
+                         cc_uint32        *out_equal);
+};
+
+
+struct cc_ccache_iterator_f {
+    cc_int32 (*release) (cc_ccache_iterator_t io_ccache_iterator);
+    
+    cc_int32 (*next) (cc_ccache_iterator_t  in_ccache_iterator,
+                      cc_ccache_t          *out_ccache);
+    
+    cc_int32 (*clone) (cc_ccache_iterator_t  in_ccache_iterator,
+                       cc_ccache_iterator_t *out_ccache_iterator);
+};
+
+struct cc_credentials_iterator_f {
+    cc_int32 (*release) (cc_credentials_iterator_t io_credentials_iterator);
+    
+    cc_int32 (*next) (cc_credentials_iterator_t  in_credentials_iterator,
+                      cc_credentials_t          *out_credentials);
+    
+    cc_int32 (*clone) (cc_credentials_iterator_t  in_credentials_iterator,
+                       cc_credentials_iterator_t *out_credentials_iterator);
+};
+
+/* API functions */
+
+CCACHE_API cc_int32 cc_initialize (cc_context_t  *out_context,
+                                   cc_int32       in_version,
+                                   cc_int32      *out_supported_version,
+                                   char const   **out_vendor);
+       
+/* Convenience macros */
+#define                cc_context_release(context) \
+                       ((context) -> functions -> release (context))
+#define                cc_context_get_change_time(context, change_time) \
+                       ((context) -> functions -> get_change_time (context, change_time))
+#define                cc_context_get_default_ccache_name(context, name) \
+                       ((context) -> functions -> get_default_ccache_name (context, name))
+#define                cc_context_open_ccache(context, name, ccache) \
+                       ((context) -> functions -> open_ccache (context, name, ccache))
+#define                cc_context_open_default_ccache(context, ccache) \
+                       ((context) -> functions -> open_default_ccache (context, ccache))
+#define                cc_context_create_ccache(context, name, version, principal, ccache) \
+                       ((context) -> functions -> create_ccache (context, name, version, principal, ccache))
+#define                cc_context_create_default_ccache(context, version, principal, ccache) \
+                       ((context) -> functions -> create_default_ccache (context, version, principal, ccache))
+#define                cc_context_create_new_ccache(context, version, principal, ccache) \
+                       ((context) -> functions -> create_new_ccache (context, version, principal, ccache))
+#define                cc_context_new_ccache_iterator(context, iterator) \
+                       ((context) -> functions -> new_ccache_iterator (context, iterator))
+#define                cc_context_lock(context, type, block) \
+                       ((context) -> functions -> lock (context, type, block))
+#define                cc_context_unlock(context) \
+                       ((context) -> functions -> unlock (context))
+#define                cc_context_compare(context, compare_to, equal) \
+                       ((context) -> functions -> compare (context, compare_to, equal))
+#define                cc_context_wait_for_change(context) \
+                       ((context) -> functions -> wait_for_change (context))
+
+#define                cc_ccache_release(ccache) \
+                       ((ccache) -> functions -> release (ccache))
+#define                cc_ccache_destroy(ccache) \
+                       ((ccache) -> functions -> destroy (ccache))
+#define                cc_ccache_set_default(ccache) \
+                       ((ccache) -> functions -> set_default (ccache))
+#define                cc_ccache_get_credentials_version(ccache, version) \
+                       ((ccache) -> functions -> get_credentials_version (ccache, version))
+#define                cc_ccache_get_name(ccache, name) \
+                       ((ccache) -> functions -> get_name (ccache, name))
+#define                cc_ccache_get_principal(ccache, version, principal) \
+                       ((ccache) -> functions -> get_principal (ccache, version, principal))
+#define                cc_ccache_set_principal(ccache, version, principal) \
+                       ((ccache) -> functions -> set_principal (ccache, version, principal))
+#define                cc_ccache_store_credentials(ccache, credentials) \
+                       ((ccache) -> functions -> store_credentials (ccache, credentials))
+#define                cc_ccache_remove_credentials(ccache, credentials) \
+                       ((ccache) -> functions -> remove_credentials (ccache, credentials))
+#define                cc_ccache_new_credentials_iterator(ccache, iterator) \
+                       ((ccache) -> functions -> new_credentials_iterator (ccache, iterator))
+#define                cc_ccache_lock(ccache, type, block) \
+                       ((ccache) -> functions -> lock (ccache, type, block))
+#define                cc_ccache_unlock(ccache, unlock) \
+                       ((ccache) -> functions -> unlock (ccache, unlock))
+#define                cc_ccache_get_last_default_time(ccache, last_default_time) \
+                       ((ccache) -> functions -> get_last_default_time (ccache, last_default_time))
+#define                cc_ccache_get_change_time(ccache, change_time) \
+                       ((ccache) -> functions -> get_change_time (ccache, change_time))
+#define                cc_ccache_move(source, destination) \
+                       ((source) -> functions -> move (source, destination))
+#define                cc_ccache_compare(ccache, compare_to, equal) \
+                       ((ccache) -> functions -> compare (ccache, compare_to, equal))
+#define                cc_ccache_get_kdc_time_offset(ccache, version, time_offset) \
+                        ((ccache) -> functions -> get_kdc_time_offset (ccache, version, time_offset))
+#define                cc_ccache_set_kdc_time_offset(ccache, version, time_offset) \
+                        ((ccache) -> functions -> set_kdc_time_offset (ccache, version, time_offset))
+#define                cc_ccache_clear_kdc_time_offset(ccache, version) \
+                        ((ccache) -> functions -> clear_kdc_time_offset (ccache, version))
+#define                cc_ccache_wait_for_change(ccache) \
+                        ((ccache) -> functions -> wait_for_change (ccache))
+
+#define                cc_string_release(string) \
+                       ((string) -> functions -> release (string))
+
+#define                cc_credentials_release(credentials) \
+                       ((credentials) -> functions -> release (credentials))
+#define                cc_credentials_compare(credentials, compare_to, equal) \
+                       ((credentials) -> functions -> compare (credentials, compare_to, equal))
+
+#define                cc_ccache_iterator_release(iterator) \
+                       ((iterator) -> functions -> release (iterator))
+#define                cc_ccache_iterator_next(iterator, ccache) \
+                       ((iterator) -> functions -> next (iterator, ccache))
+#define                cc_ccache_iterator_clone(iterator, new_iterator) \
+                       ((iterator) -> functions -> clone (iterator, new_iterator))
+       
+#define                cc_credentials_iterator_release(iterator) \
+                       ((iterator) -> functions -> release (iterator))
+#define                cc_credentials_iterator_next(iterator, credentials) \
+                       ((iterator) -> functions -> next (iterator, credentials))
+#define                cc_credentials_iterator_clone(iterator, new_iterator) \
+                       ((iterator) -> functions -> clone (iterator, new_iterator))
+                       
+#if TARGET_OS_MAC
+#pragma pack(pop)
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __CREDENTIALSCACHE__ */
diff --git a/src/include/CredentialsCache2.h b/src/include/CredentialsCache2.h
new file mode 100644 (file)
index 0000000..b0c45d5
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * This is backwards compatibility for CCache API v2 clients to be able to run 
+ * against the CCache API v3 library
+ */
+#ifndef CCAPI_V2_H
+#define CCAPI_V2_H
+#include <CredentialsCache.h>
+
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+#include <TargetConditionals.h>
+#include <AvailabilityMacros.h>
+#ifdef DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER
+#define CCAPI_DEPRECATED DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER
+#endif
+#endif
+
+#ifndef CCAPI_DEPRECATED
+#define CCAPI_DEPRECATED
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if TARGET_OS_MAC
+#pragma pack(push,2)
+#endif
+    
+/* Some old types get directly mapped to new types */
+
+typedef cc_context_d apiCB;
+typedef cc_ccache_d ccache_p;
+typedef cc_credentials_iterator_d ccache_cit_creds;
+typedef cc_ccache_iterator_d ccache_cit_ccache;
+typedef cc_data cc_data_compat;
+typedef cc_int32 cc_cred_vers;
+typedef cc_int32 cc_result;
+
+/* This doesn't exist in API v3 */
+typedef cc_uint32 cc_flags;
+
+/* Credentials types are visible to the caller so we have to keep binary compatibility */
+
+typedef struct cc_credentials_v5_compat {
+    char*                      client;
+    char*                      server;
+    cc_data_compat             keyblock;
+    cc_time_t                  authtime;
+    cc_time_t                  starttime;
+    cc_time_t                  endtime;
+    cc_time_t                  renew_till;
+    cc_uint32                  is_skey;
+    cc_uint32                  ticket_flags;
+    cc_data_compat**           addresses;
+    cc_data_compat             ticket;
+    cc_data_compat             second_ticket;
+    cc_data_compat**           authdata;
+} cc_credentials_v5_compat;
+enum {
+    MAX_V4_CRED_LEN = 1250
+};
+enum {
+    KRB_NAME_SZ = 40,
+    KRB_INSTANCE_SZ = 40,
+    KRB_REALM_SZ = 40
+};
+typedef struct cc_credentials_v4_compat {
+    unsigned char      kversion;
+    char               principal[KRB_NAME_SZ+1];
+    char               principal_instance[KRB_INSTANCE_SZ+1];
+    char               service[KRB_NAME_SZ+1];
+    char               service_instance[KRB_INSTANCE_SZ+1];
+    char               realm[KRB_REALM_SZ+1];
+    unsigned char      session_key[8];
+    cc_int32           kvno;
+    cc_int32           str_to_key;
+    long               issue_date;
+    cc_int32           lifetime;
+    cc_uint32          address;
+    cc_int32           ticket_sz;
+    unsigned char      ticket[MAX_V4_CRED_LEN];
+    unsigned long      oops;
+} cc_credentials_v4_compat;
+
+typedef union cred_ptr_union_compat {
+    cc_credentials_v4_compat* pV4Cred;
+    cc_credentials_v5_compat* pV5Cred;
+} cred_ptr_union_compat;
+typedef struct cred_union {
+    cc_int32              cred_type;  /* cc_cred_vers */
+    cred_ptr_union_compat cred;
+} cred_union;
+
+/* NC info structure is gone in v3 */
+
+struct infoNC {
+    char*      name;
+    char*      principal;
+    cc_int32   vers;
+};
+
+typedef struct infoNC infoNC;
+
+/* Some old type names */
+
+typedef cc_credentials_v4_compat V4Cred_type;
+typedef cc_credentials_v5_compat cc_creds;
+struct ccache_cit;
+typedef struct ccache_cit ccache_cit;
+
+enum {
+    CC_API_VER_2 = ccapi_version_2
+};
+
+enum {
+    CC_NOERROR,
+    CC_BADNAME,
+    CC_NOTFOUND,
+    CC_END,
+    CC_IO,
+    CC_WRITE,
+    CC_NOMEM,
+    CC_FORMAT,
+    CC_LOCKED,
+    CC_BAD_API_VERSION,
+    CC_NO_EXIST,
+    CC_NOT_SUPP,
+    CC_BAD_PARM,
+    CC_ERR_CACHE_ATTACH,
+    CC_ERR_CACHE_RELEASE,
+    CC_ERR_CACHE_FULL,
+    CC_ERR_CRED_VERSION
+};      
+
+enum {
+    CC_CRED_UNKNOWN,
+    CC_CRED_V4,
+    CC_CRED_V5,
+    CC_CRED_MAX
+};
+
+enum {
+    CC_LOCK_UNLOCK = 1,
+    CC_LOCK_READER = 2,
+    CC_LOCK_WRITER = 3,
+    CC_LOCK_NOBLOCK = 16
+};
+
+CCACHE_API cc_int32 
+cc_shutdown (apiCB **io_context)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_get_NC_info (apiCB    *in_context,
+                infoNC ***out_info)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_get_change_time (apiCB     *in_context,
+                    cc_time_t *out_change_time)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_open (apiCB       *in_context,
+         const char  *in_name,
+         cc_int32     in_version,
+         cc_uint32    in_flags,
+         ccache_p   **out_ccache)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_create (apiCB       *in_context,
+           const char  *in_name,
+           const char  *in_principal,
+           cc_int32     in_version,
+           cc_uint32    in_flags,
+           ccache_p   **out_ccache)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_close (apiCB     *in_context,
+          ccache_p **ioCCache)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_destroy (apiCB     *in_context,
+            ccache_p **io_ccache)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_seq_fetch_NCs_begin (apiCB       *in_context,
+                        ccache_cit **out_nc_iterator)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_seq_fetch_NCs_next (apiCB       *in_context,
+                       ccache_p   **out_ccache,
+                       ccache_cit  *in_nc_iterator)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_seq_fetch_NCs_end (apiCB       *in_context,
+                      ccache_cit **io_nc_iterator)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_get_name (apiCB     *in_context,
+             ccache_p  *in_ccache,
+             char     **out_name)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_get_cred_version (apiCB    *in_context,
+                     ccache_p *in_ccache,
+                     cc_int32 *out_version)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_set_principal (apiCB    *in_context,
+                  ccache_p *in_ccache,
+                  cc_int32  in_version,
+                  char     *in_principal)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_get_principal (apiCB     *in_context,
+                  ccache_p  *in_ccache,
+                  char     **out_principal)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_store (apiCB      *in_context,
+          ccache_p   *in_ccache,
+          cred_union  in_credentials)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_remove_cred (apiCB      *in_context,
+                ccache_p   *in_ccache,
+                cred_union  in_credentials)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_seq_fetch_creds_begin (apiCB           *in_context,
+                          const ccache_p  *in_ccache,
+                          ccache_cit     **out_ccache_iterator)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_seq_fetch_creds_next (apiCB       *in_context,
+                         cred_union **out_cred_union,
+                         ccache_cit  *in_ccache_iterator)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_seq_fetch_creds_end (apiCB       *in_context,
+                        ccache_cit **io_ccache_iterator)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_free_principal (apiCB  *in_context,
+                   char  **io_principal)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_free_name (apiCB  *in_context,
+              char  **io_name)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_free_creds (apiCB       *in_context,
+               cred_union **io_cred_union)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_free_NC_info (apiCB    *in_context,
+                 infoNC ***io_info)
+CCAPI_DEPRECATED;
+
+CCACHE_API cc_int32 
+cc_lock_request (apiCB          *in_context,
+                 const ccache_p *in_ccache,
+                 const cc_int32  in_lock_type)
+CCAPI_DEPRECATED;
+
+#if TARGET_OS_MAC
+#pragma pack(pop)
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CCAPI_V2_H */
index 36bc780e211d9cab15d0021e5cf661e40c68fb72..babfea48b4598757b15671bbdfa5309aac7681c5 100644 (file)
@@ -230,7 +230,7 @@ static krb5_error_code stdccv3_get_timeoffset (krb5_context in_context,
     krb5_error_code err = 0;
     
     if (gCCVersion >= ccapi_version_5) {
-        krb5_os_context os_ctx = (krb5_os_context) in_context->os_context;
+        krb5_os_context os_ctx = (krb5_os_context) &in_context->os_context;
         cc_time_t time_offset = 0;
     
         err = cc_ccache_get_kdc_time_offset (in_ccache, cc_credentials_v5,
@@ -257,7 +257,7 @@ static krb5_error_code stdccv3_set_timeoffset (krb5_context in_context,
     krb5_error_code err = 0;
     
     if (gCCVersion >= ccapi_version_5) {
-        krb5_os_context os_ctx = (krb5_os_context) in_context->os_context;
+        krb5_os_context os_ctx = (krb5_os_context) &in_context->os_context;
         
         if (!err && os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) {
             err = cc_ccache_set_kdc_time_offset (in_ccache, 
index 2ab5da5d4a97b08cc9acaa0b7abfdd6ca722609d..6d68cd922f128de74c3c002db6cfc7bae2e89b08 100644 (file)
@@ -97,7 +97,7 @@ krb5_rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context,
     krb5_timestamp       currenttime;
     krb5_principal_data princ_data;
     
-    req->ticket->enc_part2 == NULL;
+    req->ticket->enc_part2 = NULL;
     if (server && krb5_is_referral_realm(&server->realm)) {
        char *realm;
        princ_data = *server;