summaryrefslogtreecommitdiff
path: root/source3/lib/membuffer.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>1998-03-11 21:11:04 +0000
committerJeremy Allison <jra@samba.org>1998-03-11 21:11:04 +0000
commitfdeea341ed1bae670382e45eb731db1b5838ad21 (patch)
treebdbc5138a9340bdbd5c12cee243e6acfb2e64daf /source3/lib/membuffer.c
parent4c6230afd2f144322c07c7e4c46147d3e5d2ddde (diff)
downloadsamba-fdeea341ed1bae670382e45eb731db1b5838ad21.tar.gz
samba-fdeea341ed1bae670382e45eb731db1b5838ad21.tar.bz2
samba-fdeea341ed1bae670382e45eb731db1b5838ad21.zip
"For I have laboured mightily on Luke's code, and hath broken
all I saw" - the book of Jeremy, chapter 1 :-). So here is the mega-merge of the NTDOM branch server code. It doesn't include the new client side pieces, we'll look at that later. This should give the same functionality, server wise, as the NTDOM branch does, only merged into the main branch. Any fixes to domain controler functionality should be added to the main branch, not the NTDOM branch. This code compiles without warnings on gcc2.8, but will need further testing before we are sure all the working functionality of the NTDOM server branch has been correctly carried over. I hereby declare the server side of the NTDOM branch dead (and all who sail in her :-). Jeremy. (This used to be commit 118ba4d77a33248e762a2cf843fb7cbc906ee6e7)
Diffstat (limited to 'source3/lib/membuffer.c')
-rw-r--r--source3/lib/membuffer.c370
1 files changed, 370 insertions, 0 deletions
diff --git a/source3/lib/membuffer.c b/source3/lib/membuffer.c
new file mode 100644
index 0000000000..0665b19ead
--- /dev/null
+++ b/source3/lib/membuffer.c
@@ -0,0 +1,370 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ Samba memory buffer functions
+ Copyright (C) Andrew Tridgell 1992-1997
+ Copyright (C) Luke Kenneth Casson Leighton 1996-1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*******************************************************************
+ *
+ * Description: memory buffer / stream management.
+ * Author : Luke K C Leighton
+ * Created : Dec 1997
+ *
+
+ * this module is intended for use in streaming data in and out of
+ * buffers. it is intended that a single data stream be subdivided
+ * into manageable sections.
+
+ * for example, an rpc header contains a length field, but until the
+ * data has been created, the length is unknown. using this module,
+ * the header section can be tacked onto the front of the data memory
+ * list once the size of the data section preceding it is known.
+
+ * the "margin" can be used to over-run and retrospectively lengthen
+ * the buffer. this is to save time in some of the loops, where it is
+ * not particularly desirable to realloc data by 1, 2 or 4 bytes
+ * repetitively...
+
+ * each memory buffer contains a start and end offset. the end of
+ * one buffer should equal to the start of the next in the chain.
+ * (end - start = len, instead of end - start + 1 = len)
+
+ * the debug log levels are very high in some of the routines: you
+ * have no idea how boring it gets staring at debug output from these
+
+ ********************************************************************/
+
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+/*******************************************************************
+ initialise a memory buffer.
+ ********************************************************************/
+void mem_init(struct mem_buf *buf, int margin)
+{
+ buf->dynamic = True;
+ buf->data = NULL;
+ buf->data_size = 0;
+ buf->data_used = 0;
+
+ buf->margin = margin;
+
+ buf->next = NULL;
+
+ buf->offset.start = 0;
+ buf->offset.end = 0;
+}
+
+/*******************************************************************
+ initialise a memory buffer.
+
+ dynamic indicates memory has been dynamically allocated.
+ if mem_free is called, the memory will be freed.
+ ********************************************************************/
+void mem_create(struct mem_buf *buf, char *data, int size, int margin, BOOL dynamic)
+{
+ buf->dynamic = dynamic;
+ buf->data = data;
+ buf->data_size = size;
+ buf->data_used = size;
+
+ buf->margin = margin;
+
+ buf->next = NULL;
+
+ buf->offset.start = 0;
+ buf->offset.end = size;
+}
+
+/*******************************************************************
+ takes a memory buffer out of one structure: puts it in the other.
+ NULLs the one that the buffer is being stolen from.
+ ********************************************************************/
+void mem_take(struct mem_buf *mem_to, struct mem_buf *mem_from)
+{
+ memcpy(mem_to, mem_from, sizeof(*mem_to));
+
+ mem_init(mem_from, mem_from->margin);
+}
+
+/*******************************************************************
+ allocate a memory buffer. assume it's empty
+ ********************************************************************/
+BOOL mem_alloc_data(struct mem_buf *buf, int size)
+{
+ if (!buf->dynamic)
+ {
+ DEBUG(3,("mem_alloc_data: warning - memory buffer type is set to static\n"));
+ }
+
+ buf->data_size = size + buf->margin;
+ buf->data_used = size;
+
+ buf->data = malloc(buf->data_size);
+
+ if (buf->data == NULL)
+ {
+ DEBUG(3,("mem_alloc: could not malloc size %d\n",
+ buf->data_size));
+ mem_init(buf, buf->margin);
+
+ return False;
+ }
+
+ bzero(buf->data, buf->data_size);
+
+ return True;
+}
+
+/*******************************************************************
+ allocates a memory buffer structure
+ ********************************************************************/
+BOOL mem_buf_copy(char *copy_into, struct mem_buf *buf,
+ uint32 offset, uint32 len)
+{
+ uint32 end = offset + len;
+ char *q = NULL;
+ uint32 data_len = mem_buf_len(buf);
+ uint32 start_offset = offset;
+ struct mem_buf **bcp = &buf;
+
+ if (buf == NULL || copy_into == NULL) return False;
+
+ DEBUG(200,("mem_buf_copy: data[%d..%d] offset %d len %d\n",
+ buf->offset.start, data_len, offset, len));
+
+ /* there's probably an off-by-one bug, here, and i haven't even tested the code :-) */
+ while (offset < end && ((q = mem_data(bcp, offset)) != NULL))
+ {
+ uint32 copy_len = (*bcp)->offset.end - offset;
+
+ DEBUG(200,("\tdata[%d..%d] - offset %d len %d\n",
+ (*bcp)->offset.start, (*bcp)->offset.end,
+ offset, copy_len));
+
+ memcpy(copy_into, q, copy_len);
+
+ offset += copy_len;
+ copy_into += copy_len;
+ }
+
+ if ((*bcp) != NULL)
+ {
+ DEBUG(200,("mem_buf_copy: copied %d bytes\n", offset - start_offset));
+ }
+ else
+ {
+ DEBUG(200,("mem_buf_copy: failed\n"));
+ }
+
+ return buf != NULL;
+}
+
+/*******************************************************************
+ allocates a memory buffer structure
+ ********************************************************************/
+BOOL mem_buf_init(struct mem_buf **buf, uint32 margin)
+{
+ if (buf == NULL) return False;
+
+ if ((*buf) == NULL)
+ {
+ (*buf) = malloc(sizeof(**buf));
+ if ((*buf) != NULL)
+ {
+ mem_init((*buf), margin);
+ return True;
+ }
+ }
+ else
+ {
+ (*buf)->margin = margin;
+ return True;
+ }
+ return False;
+}
+
+/*******************************************************************
+ frees up a memory buffer.
+ ********************************************************************/
+void mem_buf_free(struct mem_buf **buf)
+{
+ if (buf == NULL) return;
+ if ((*buf) == NULL) return;
+
+ mem_free_data(*buf); /* delete memory data */
+ free(*buf); /* delete item */
+ (*buf) = NULL;
+}
+
+/*******************************************************************
+ frees a memory buffer chain. assumes that all items are malloced.
+ ********************************************************************/
+void mem_free_chain(struct mem_buf **buf)
+{
+ if (buf == NULL) return;
+ if ((*buf) == NULL) return;
+
+ if ((*buf)->next != NULL)
+ {
+ mem_free_chain(&((*buf)->next)); /* delete all other items in chain */
+ }
+ mem_buf_free(buf);
+}
+
+/*******************************************************************
+ frees a memory buffer.
+ ********************************************************************/
+void mem_free_data(struct mem_buf *buf)
+{
+ if (buf == NULL) return;
+
+ if (buf->data != NULL && buf->dynamic)
+ {
+ free(buf->data); /* delete data in this structure */
+ }
+ mem_init(buf, buf->margin);
+}
+
+/*******************************************************************
+ reallocate a memory buffer, including a safety margin
+ ********************************************************************/
+BOOL mem_realloc_data(struct mem_buf *buf, int new_size)
+{
+ char *new_data;
+
+ if (!buf->dynamic)
+ {
+ DEBUG(3,("mem_realloc_data: memory buffer has not been dynamically allocated!\n"));
+ return False;
+ }
+
+ if (new_size == 0)
+ {
+ mem_free_data(buf);
+ return True;
+ }
+
+ new_data = Realloc(buf->data, new_size + buf->margin);
+
+ if (new_data != NULL)
+ {
+ buf->data = new_data;
+ buf->data_size = new_size + buf->margin;
+ buf->data_used = new_size;
+ }
+ else if (buf->data_size <= new_size)
+ {
+ DEBUG(3,("mem_realloc: warning - could not realloc to %d(+%d)\n",
+ new_size, buf->margin));
+
+ buf->data_used = new_size;
+ }
+ else
+ {
+ DEBUG(3,("mem_realloc: error - could not realloc to %d\n",
+ new_size));
+
+ mem_free_data(buf);
+ return False;
+ }
+
+ return True;
+}
+
+/*******************************************************************
+ reallocate a memory buffer, retrospectively :-)
+ ********************************************************************/
+BOOL mem_grow_data(struct mem_buf **buf, BOOL io, int new_size)
+{
+ if (new_size + (*buf)->margin >= (*buf)->data_size)
+ {
+ if (io)
+ {
+ DEBUG(3,("mem_grow_data: cannot resize when reading from a data stream\n"));
+ }
+ else
+ {
+ return mem_realloc_data((*buf), new_size);
+ return False;
+ }
+ }
+ return True;
+}
+
+/*******************************************************************
+ search for a memory buffer that falls within the specified offset
+ ********************************************************************/
+BOOL mem_find(struct mem_buf **buf, uint32 offset)
+{
+ struct mem_buf *f;
+ if (buf == NULL) return False;
+
+ f = *buf;
+
+ DEBUG(200,("mem_find: data[%d..%d] offset: %d\n",
+ f->offset.start, f->offset.end, offset));
+
+ while (f != NULL && offset >= f->offset.end)
+ {
+ f = f->next;
+
+ DEBUG(200,("mem_find: next[%d..%d]\n",
+ f->offset.start, f->offset.end));
+ }
+
+ (*buf) = f;
+
+ DEBUG(200,("mem_find: found data[%d..%d]\n",
+ (*buf)->offset.start,(*buf)->offset.end));
+
+ return f != NULL;
+}
+
+
+/*******************************************************************
+ add up the lengths of all sections.
+ ********************************************************************/
+uint32 mem_buf_len(struct mem_buf *buf)
+{
+ int len = 0;
+ while (buf != NULL)
+ {
+ len += buf->offset.end - buf->offset.start;
+ buf = buf->next;
+ }
+ return len;
+}
+
+
+/*******************************************************************
+ return the memory location specified by offset. may return NULL.
+ ********************************************************************/
+char *mem_data(struct mem_buf **buf, uint32 offset)
+{
+ if (mem_find(buf, offset))
+ {
+ return &((*buf)->data[offset - (*buf)->offset.start]);
+ }
+ return NULL;
+}
+
+