parse_prs.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 1,734 行 · 第 1/4 页

C
1,734
字号
/*    Unix SMB/CIFS implementation.   Samba memory buffer functions   Copyright (C) Andrew Tridgell              1992-1997   Copyright (C) Luke Kenneth Casson Leighton 1996-1997   Copyright (C) Jeremy Allison               1999   Copyright (C) Andrew Bartlett              2003.      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.*/#include "includes.h"#undef DBGC_CLASS#define DBGC_CLASS DBGC_RPC_PARSE/** * Dump a prs to a file: from the current location through to the end. **/void prs_dump(char *name, int v, prs_struct *ps){	prs_dump_region(name, v, ps, ps->data_offset, ps->buffer_size);}/** * Dump from the start of the prs to the current location. **/void prs_dump_before(char *name, int v, prs_struct *ps){	prs_dump_region(name, v, ps, 0, ps->data_offset);}/** * Dump everything from the start of the prs up to the current location. **/void prs_dump_region(char *name, int v, prs_struct *ps,		     int from_off, int to_off){	int fd, i;	pstring fname;	ssize_t sz;	if (DEBUGLEVEL < 50) return;	for (i=1;i<100;i++) {		if (v != -1) {			slprintf(fname,sizeof(fname)-1, "/tmp/%s_%d.%d.prs", name, v, i);		} else {			slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.prs", name, i);		}		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);		if (fd != -1 || errno != EEXIST) break;	}	if (fd != -1) {		sz = write(fd, ps->data_p + from_off, to_off - from_off);		i = close(fd);		if ( (sz != to_off-from_off) || (i != 0) ) {			DEBUG(0,("Error writing/closing %s: %ld!=%ld %d\n", fname, (unsigned long)sz, (unsigned long)to_off-from_off, i ));		} else {			DEBUG(0,("created %s\n", fname));		}	}}/******************************************************************* Debug output for parsing info XXXX side-effect of this function is to increase the debug depth XXXX.********************************************************************/void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name){	DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->data_offset, fn_name, desc));}/** * Initialise an expandable parse structure. * * @param size Initial buffer size.  If >0, a new buffer will be * created with malloc(). * * @return False if allocation fails, otherwise True. **/BOOL prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, BOOL io){	ZERO_STRUCTP(ps);	ps->io = io;	ps->bigendian_data = RPC_LITTLE_ENDIAN;	ps->align = RPC_PARSE_ALIGN;	ps->is_dynamic = False;	ps->data_offset = 0;	ps->buffer_size = 0;	ps->data_p = NULL;	ps->mem_ctx = ctx;	if (size != 0) {		ps->buffer_size = size;		if((ps->data_p = (char *)SMB_MALLOC((size_t)size)) == NULL) {			DEBUG(0,("prs_init: malloc fail for %u bytes.\n", (unsigned int)size));			return False;		}		memset(ps->data_p, '\0', (size_t)size);		ps->is_dynamic = True; /* We own this memory. */	} else if (MARSHALLING(ps)) {		/* If size is zero and we're marshalling we should allocate memory on demand. */		ps->is_dynamic = True;	}	return True;}/******************************************************************* Delete the memory in a parse structure - if we own it. ********************************************************************/void prs_mem_free(prs_struct *ps){	if(ps->is_dynamic)		SAFE_FREE(ps->data_p);	ps->is_dynamic = False;	ps->buffer_size = 0;	ps->data_offset = 0;}/******************************************************************* Clear the memory in a parse structure. ********************************************************************/void prs_mem_clear(prs_struct *ps){	if (ps->buffer_size)		memset(ps->data_p, '\0', (size_t)ps->buffer_size);}/******************************************************************* Allocate memory when unmarshalling... Always zero clears. ********************************************************************/#if defined(PARANOID_MALLOC_CHECKER)char *prs_alloc_mem_(prs_struct *ps, size_t size, unsigned int count)#elsechar *prs_alloc_mem(prs_struct *ps, size_t size, unsigned int count)#endif{	char *ret = NULL;	if (size) {		/* We can't call the type-safe version here. */		ret = _talloc_zero_array(ps->mem_ctx, size, count, "parse_prs");	}	return ret;}/******************************************************************* Return the current talloc context we're using. ********************************************************************/TALLOC_CTX *prs_get_mem_context(prs_struct *ps){	return ps->mem_ctx;}/******************************************************************* Hand some already allocated memory to a prs_struct. ********************************************************************/void prs_give_memory(prs_struct *ps, char *buf, uint32 size, BOOL is_dynamic){	ps->is_dynamic = is_dynamic;	ps->data_p = buf;	ps->buffer_size = size;}/******************************************************************* Take some memory back from a prs_struct. ********************************************************************/char *prs_take_memory(prs_struct *ps, uint32 *psize){	char *ret = ps->data_p;	if(psize)		*psize = ps->buffer_size;	ps->is_dynamic = False;	prs_mem_free(ps);	return ret;}/******************************************************************* Set a prs_struct to exactly a given size. Will grow or tuncate if neccessary. ********************************************************************/BOOL prs_set_buffer_size(prs_struct *ps, uint32 newsize){	if (newsize > ps->buffer_size)		return prs_force_grow(ps, newsize - ps->buffer_size);	if (newsize < ps->buffer_size) {		char *new_data_p = SMB_REALLOC(ps->data_p, newsize);		/* if newsize is zero, Realloc acts like free() & returns NULL*/		if (new_data_p == NULL && newsize != 0) {			DEBUG(0,("prs_set_buffer_size: Realloc failure for size %u.\n",				(unsigned int)newsize));			DEBUG(0,("prs_set_buffer_size: Reason %s\n",strerror(errno)));			return False;		}		ps->data_p = new_data_p;		ps->buffer_size = newsize;	}	return True;}/******************************************************************* Attempt, if needed, to grow a data buffer. Also depends on the data stream mode (io). ********************************************************************/BOOL prs_grow(prs_struct *ps, uint32 extra_space){	uint32 new_size;	char *new_data;	ps->grow_size = MAX(ps->grow_size, ps->data_offset + extra_space);	if(ps->data_offset + extra_space <= ps->buffer_size)		return True;	/*	 * We cannot grow the buffer if we're not reading	 * into the prs_struct, or if we don't own the memory.	 */	if(UNMARSHALLING(ps) || !ps->is_dynamic) {		DEBUG(0,("prs_grow: Buffer overflow - unable to expand buffer by %u bytes.\n",				(unsigned int)extra_space));		return False;	}		/*	 * Decide how much extra space we really need.	 */	extra_space -= (ps->buffer_size - ps->data_offset);	if(ps->buffer_size == 0) {		/*		 * Ensure we have at least a PDU's length, or extra_space, whichever		 * is greater.		 */		new_size = MAX(RPC_MAX_PDU_FRAG_LEN,extra_space);		if((new_data = SMB_MALLOC(new_size)) == NULL) {			DEBUG(0,("prs_grow: Malloc failure for size %u.\n", (unsigned int)new_size));			return False;		}		memset(new_data, '\0', (size_t)new_size );	} else {		/*		 * If the current buffer size is bigger than the space needed, just 		 * double it, else add extra_space.		 */		new_size = MAX(ps->buffer_size*2, ps->buffer_size + extra_space);				if ((new_data = SMB_REALLOC(ps->data_p, new_size)) == NULL) {			DEBUG(0,("prs_grow: Realloc failure for size %u.\n",				(unsigned int)new_size));			return False;		}		memset(&new_data[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size));	}	ps->buffer_size = new_size;	ps->data_p = new_data;	return True;}/******************************************************************* Attempt to force a data buffer to grow by len bytes. This is only used when appending more data onto a prs_struct when reading an rpc reply, before unmarshalling it. ********************************************************************/BOOL prs_force_grow(prs_struct *ps, uint32 extra_space){	uint32 new_size = ps->buffer_size + extra_space;	char *new_data;	if(!UNMARSHALLING(ps) || !ps->is_dynamic) {		DEBUG(0,("prs_force_grow: Buffer overflow - unable to expand buffer by %u bytes.\n",				(unsigned int)extra_space));		return False;	}	if((new_data = SMB_REALLOC(ps->data_p, new_size)) == NULL) {		DEBUG(0,("prs_force_grow: Realloc failure for size %u.\n",			(unsigned int)new_size));		return False;	}	memset(&new_data[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size));	ps->buffer_size = new_size;	ps->data_p = new_data;	return True;}/******************************************************************* Get the data pointer (external interface).********************************************************************/char *prs_data_p(prs_struct *ps){	return ps->data_p;}/******************************************************************* Get the current data size (external interface). ********************************************************************/uint32 prs_data_size(prs_struct *ps){	return ps->buffer_size;}/******************************************************************* Fetch the current offset (external interface). ********************************************************************/uint32 prs_offset(prs_struct *ps){	return ps->data_offset;}/******************************************************************* Set the current offset (external interface). ********************************************************************/BOOL prs_set_offset(prs_struct *ps, uint32 offset){	if(offset <= ps->data_offset) {		ps->data_offset = offset;		return True;	}	if(!prs_grow(ps, offset - ps->data_offset))		return False;	ps->data_offset = offset;	return True;}/******************************************************************* Append the data from one parse_struct into another. ********************************************************************/BOOL prs_append_prs_data(prs_struct *dst, prs_struct *src){	if (prs_offset(src) == 0)		return True;	if(!prs_grow(dst, prs_offset(src)))		return False;	memcpy(&dst->data_p[dst->data_offset], src->data_p, (size_t)prs_offset(src));	dst->data_offset += prs_offset(src);	return True;}/******************************************************************* Append some data from one parse_struct into another. ********************************************************************/BOOL prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start, uint32 len){		if (len == 0)		return True;	if(!prs_grow(dst, len))		return False;		memcpy(&dst->data_p[dst->data_offset], src->data_p + start, (size_t)len);	dst->data_offset += len;	return True;}/******************************************************************* Append the data from a buffer into a parse_struct. ********************************************************************/BOOL prs_copy_data_in(prs_struct *dst, const char *src, uint32 len){	if (len == 0)		return True;	if(!prs_grow(dst, len))		return False;	memcpy(&dst->data_p[dst->data_offset], src, (size_t)len);	dst->data_offset += len;	return True;}/******************************************************************* Copy some data from a parse_struct into a buffer. ********************************************************************/BOOL prs_copy_data_out(char *dst, prs_struct *src, uint32 len){	if (len == 0)		return True;	if(!prs_mem_get(src, len))		return False;	memcpy(dst, &src->data_p[src->data_offset], (size_t)len);	src->data_offset += len;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?