summaryrefslogtreecommitdiffstats
path: root/src/util/support
diff options
context:
space:
mode:
authorAlexandra Ellwood <lxs@mit.edu>2008-09-28 19:43:47 +0000
committerAlexandra Ellwood <lxs@mit.edu>2008-09-28 19:43:47 +0000
commitb5dce4285a9330d25542528030ce93da78e36375 (patch)
treec8cbd6a729cddb99bda84991e1c7c231449434f2 /src/util/support
parent01a5986cbf7afdba2b805bdd16893b6b52c87f42 (diff)
downloadkrb5-b5dce4285a9330d25542528030ce93da78e36375.tar.gz
krb5-b5dce4285a9330d25542528030ce93da78e36375.tar.xz
krb5-b5dce4285a9330d25542528030ce93da78e36375.zip
Create common stream and ipc layer for CCAPI and KIM.
Will switch CCAPI to this new code later though, so as not to destabilize KfM and the Windows builds. ticket: 6055 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20769 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/util/support')
-rw-r--r--src/util/support/ipc_stream.c507
1 files changed, 507 insertions, 0 deletions
diff --git a/src/util/support/ipc_stream.c b/src/util/support/ipc_stream.c
new file mode 100644
index 000000000..608e0fb37
--- /dev/null
+++ b/src/util/support/ipc_stream.c
@@ -0,0 +1,507 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006, 2007 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 "k5-ipc_stream.h"
+
+#if !defined(htonll)
+#define htonll(x) k5_htonll(x)
+#endif
+
+#if !defined(ntohll)
+#define ntohll(x) k5_ntohll(x)
+#endif
+
+/* Add debugging later */
+#define k5_check_error(x) (x)
+
+struct k5_ipc_stream {
+ char *data;
+ uint64_t size;
+ uint64_t max_size;
+};
+
+const struct k5_ipc_stream k5_ipc_stream_initializer = { NULL, 0, 0 };
+
+#define K5_IPC_STREAM_SIZE_INCREMENT 128
+
+/* ------------------------------------------------------------------------ */
+
+static uint32_t k5_ipc_stream_reallocate (k5_ipc_stream io_stream,
+ uint64_t in_new_size)
+{
+ int32_t err = 0;
+ uint64_t new_max_size = 0;
+
+ if (!io_stream) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ uint64_t 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 += K5_IPC_STREAM_SIZE_INCREMENT;
+ }
+
+
+ } else if ((in_new_size + K5_IPC_STREAM_SIZE_INCREMENT) < old_max_size) {
+ /* Shrink the array, but never drop below K5_IPC_STREAM_SIZE_INCREMENT */
+ while ((in_new_size + K5_IPC_STREAM_SIZE_INCREMENT) < new_max_size &&
+ (new_max_size > K5_IPC_STREAM_SIZE_INCREMENT)) {
+ new_max_size -= K5_IPC_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 = k5_check_error (ENOMEM);
+ }
+ }
+
+ return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+int32_t k5_ipc_stream_new (k5_ipc_stream *out_stream)
+{
+ int32_t err = 0;
+ k5_ipc_stream stream = NULL;
+
+ if (!out_stream) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ stream = malloc (sizeof (*stream));
+ if (stream) {
+ *stream = k5_ipc_stream_initializer;
+ } else {
+ err = k5_check_error (ENOMEM);
+ }
+ }
+
+ if (!err) {
+ *out_stream = stream;
+ stream = NULL;
+ }
+
+ k5_ipc_stream_release (stream);
+
+ return k5_check_error (err);
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_release (k5_ipc_stream io_stream)
+{
+ int32_t err = 0;
+
+ if (!err && io_stream) {
+ free (io_stream->data);
+ free (io_stream);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint64_t k5_ipc_stream_size (k5_ipc_stream in_stream)
+{
+ return in_stream ? in_stream->size : 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+const char *k5_ipc_stream_data (k5_ipc_stream in_stream)
+{
+ return in_stream ? in_stream->data : NULL;
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read (k5_ipc_stream io_stream,
+ void *io_data,
+ uint64_t in_size)
+{
+ int32_t err = 0;
+
+ if (!io_stream) { err = k5_check_error (EINVAL); }
+ if (!io_data ) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ if (in_size > io_stream->size) {
+ err = k5_check_error (EINVAL);
+ }
+ }
+
+ 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 = k5_ipc_stream_reallocate (io_stream, io_stream->size - in_size);
+
+ if (!err) {
+ io_stream->size -= in_size;
+ }
+ }
+
+ return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write (k5_ipc_stream io_stream,
+ const void *in_data,
+ uint64_t in_size)
+{
+ int32_t err = 0;
+
+ if (!io_stream) { err = k5_check_error (EINVAL); }
+ if (!in_data ) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ /* Security check: Do not let the caller overflow the length */
+ if (in_size > (UINT64_MAX - io_stream->size)) {
+ err = k5_check_error (EINVAL);
+ }
+ }
+
+ if (!err) {
+ err = k5_ipc_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 k5_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+void k5_ipc_stream_free_string (char *in_string)
+{
+ free (in_string);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read_string (k5_ipc_stream io_stream,
+ char **out_string)
+{
+ int32_t err = 0;
+ uint32_t length = 0;
+ char *string = NULL;
+
+ if (!io_stream ) { err = k5_check_error (EINVAL); }
+ if (!out_string) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ err = k5_ipc_stream_read_uint32 (io_stream, &length);
+ }
+
+ if (!err) {
+ string = malloc (length);
+ if (!string) { err = k5_check_error (ENOMEM); }
+ }
+
+ if (!err) {
+ err = k5_ipc_stream_read (io_stream, string, length);
+ }
+
+ if (!err) {
+ *out_string = string;
+ string = NULL;
+ }
+
+ free (string);
+
+ return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write_string (k5_ipc_stream io_stream,
+ const char *in_string)
+{
+ int32_t err = 0;
+ uint32_t length = 0;
+
+ if (!io_stream) { err = k5_check_error (EINVAL); }
+ if (!in_string) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ length = strlen (in_string) + 1;
+
+ err = k5_ipc_stream_write_uint32 (io_stream, length);
+ }
+
+ if (!err) {
+ err = k5_ipc_stream_write (io_stream, in_string, length);
+ }
+
+ return k5_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read_int32 (k5_ipc_stream io_stream,
+ int32_t *out_int32)
+{
+ int32_t err = 0;
+ int32_t int32 = 0;
+
+ if (!io_stream) { err = k5_check_error (EINVAL); }
+ if (!out_int32) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ err = k5_ipc_stream_read (io_stream, &int32, sizeof (int32));
+ }
+
+ if (!err) {
+ *out_int32 = ntohl (int32);
+ }
+
+ return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write_int32 (k5_ipc_stream io_stream,
+ int32_t in_int32)
+{
+ int32_t err = 0;
+ int32_t int32 = htonl (in_int32);
+
+ if (!io_stream) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ err = k5_ipc_stream_write (io_stream, &int32, sizeof (int32));
+ }
+
+ return k5_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read_uint32 (k5_ipc_stream io_stream,
+ uint32_t *out_uint32)
+{
+ int32_t err = 0;
+ uint32_t uint32 = 0;
+
+ if (!io_stream) { err = k5_check_error (EINVAL); }
+ if (!out_uint32) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ err = k5_ipc_stream_read (io_stream, &uint32, sizeof (uint32));
+ }
+
+ if (!err) {
+ *out_uint32 = ntohl (uint32);
+ }
+
+ return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write_uint32 (k5_ipc_stream io_stream,
+ uint32_t in_uint32)
+{
+ int32_t err = 0;
+ int32_t uint32 = htonl (in_uint32);
+
+ if (!io_stream) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ err = k5_ipc_stream_write (io_stream, &uint32, sizeof (uint32));
+ }
+
+ return k5_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read_int64 (k5_ipc_stream io_stream,
+ int64_t *out_int64)
+{
+ int32_t err = 0;
+ uint64_t int64 = 0;
+
+ if (!io_stream) { err = k5_check_error (EINVAL); }
+ if (!out_int64) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ err = k5_ipc_stream_read (io_stream, &int64, sizeof (int64));
+ }
+
+ if (!err) {
+ *out_int64 = ntohll (int64);
+ }
+
+ return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write_int64 (k5_ipc_stream io_stream,
+ int64_t in_int64)
+{
+ int32_t err = 0;
+ int64_t int64 = htonll (in_int64);
+
+ if (!io_stream) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ err = k5_ipc_stream_write (io_stream, &int64, sizeof (int64));
+ }
+
+ return k5_check_error (err);
+}
+
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read_uint64 (k5_ipc_stream io_stream,
+ uint64_t *out_uint64)
+{
+ int32_t err = 0;
+ uint64_t uint64 = 0;
+
+ if (!io_stream) { err = k5_check_error (EINVAL); }
+ if (!out_uint64) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ err = k5_ipc_stream_read (io_stream, &uint64, sizeof (uint64));
+ }
+
+ if (!err) {
+ *out_uint64 = ntohll (uint64);
+ }
+
+ return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write_uint64 (k5_ipc_stream io_stream,
+ uint64_t in_uint64)
+{
+ int32_t err = 0;
+ int64_t uint64 = htonll (in_uint64);
+
+ if (!io_stream) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ err = k5_ipc_stream_write (io_stream, &uint64, sizeof (uint64));
+ }
+
+ return k5_check_error (err);
+}
+
+#ifdef TARGET_OS_MAC
+#pragma mark -
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_read_time (k5_ipc_stream io_stream,
+ time_t *out_time)
+{
+ int32_t err = 0;
+ int64_t t = 0;
+
+ if (!io_stream) { err = k5_check_error (EINVAL); }
+ if (!out_time ) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ err = k5_ipc_stream_read_int64 (io_stream, &t);
+ }
+
+ if (!err) {
+ *out_time = t;
+ }
+
+ return k5_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+uint32_t k5_ipc_stream_write_time (k5_ipc_stream io_stream,
+ time_t in_time)
+{
+ int32_t err = 0;
+
+ if (!io_stream) { err = k5_check_error (EINVAL); }
+
+ if (!err) {
+ err = k5_ipc_stream_write_int64 (io_stream, in_time);
+ }
+
+ return k5_check_error (err);
+}