1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-27 03:21:53 +03:00
samba-mirror/source3/lib/membuffer.c
Jeremy Allison e300c0346f includes.h: Moved HPUX undefine of SEMMSL to where it actually does something.
ipc.c: Added Luke's debug statement.
locking_slow.c: Added FTRUNCATE_NEEDS_ROOT code for broken systems that
need it (not sure what these are yet).

membuffer.c ntdomain.h proto.h
lib/rpc/include/rpc_dce.h lib/rpc/include/rpc_srvsvc.h
lib/rpc/parse/parse_prs.c lib/rpc/parse/parse_rpc.c
lib/rpc/server/srv_pipe_hnd.c lib/rpc/server/srv_util.c:
   Re-merge of Luke's NTDOM changes 'cos he's a lazy git with
   carpel tunnel syndrome :-).

Jeremy.
(This used to be commit 52e3966fbc)
1998-04-10 18:21:16 +00:00

370 lines
9.8 KiB
C

/*
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, BOOL force_grow)
{
if (new_size + (*buf)->margin >= (*buf)->data_size)
{
if (io && !force_grow)
{
DEBUG(3,("mem_grow_data: cannot resize when reading from a data stream\n"));
}
else
{
return mem_realloc_data((*buf), new_size);
}
}
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;
}