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 + -
显示快捷键?