2000-06-09 06:59:50 +04:00
# include "parser.h"
2000-05-12 18:35:13 +04:00
/*******************************************************************
Attempt , if needed , to grow a data buffer .
Also depends on the data stream mode ( io ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
BOOL io_grow ( io_struct * ps , uint32 extra_space )
2000-05-12 18:35:13 +04:00
{
uint32 new_size ;
char * new_data ;
2000-05-15 13:56:30 +04:00
ps - > grow_size = MAX ( ps - > grow_size , ps - > data_offset + extra_space ) ;
2000-05-12 18:35:13 +04:00
if ( ps - > data_offset + extra_space < = ps - > buffer_size )
return True ;
/*
* We cannot grow the buffer if we ' re not reading
2000-05-31 09:39:54 +04:00
* into the io_struct , or if we don ' t own the memory .
2000-05-12 18:35:13 +04:00
*/
if ( UNMARSHALLING ( ps ) | | ! ps - > is_dynamic ) {
2000-05-31 09:39:54 +04:00
DEBUG ( 0 , ( " io_grow: Buffer overflow - unable to expand buffer by %u bytes. \n " ,
2000-05-12 18:35:13 +04:00
( 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 ) {
2000-06-09 06:59:50 +04:00
new_size = extra_space ;
2000-05-12 18:35:13 +04:00
if ( ( new_data = malloc ( new_size ) ) = = NULL ) {
2000-05-31 09:39:54 +04:00
DEBUG ( 0 , ( " io_grow: Malloc failure for size %u. \n " , ( unsigned int ) new_size ) ) ;
2000-05-12 18:35:13 +04:00
return False ;
}
memset ( new_data , ' \0 ' , 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 = Realloc ( ps - > data_p , new_size ) ) = = NULL ) {
2000-05-31 09:39:54 +04:00
DEBUG ( 0 , ( " io_grow: Realloc failure for size %u. \n " ,
2000-05-12 18:35:13 +04:00
( unsigned int ) new_size ) ) ;
return False ;
}
}
ps - > buffer_size = new_size ;
ps - > data_p = new_data ;
return True ;
}
/*******************************************************************
Ensure we can read / write to a given offset .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
char * io_mem_get ( io_struct * ps , uint32 extra_size )
2000-05-12 18:35:13 +04:00
{
if ( UNMARSHALLING ( ps ) ) {
/*
* If reading , ensure that we can read the requested size item .
*/
if ( ps - > data_offset + extra_size > ps - > buffer_size ) {
2000-05-31 09:39:54 +04:00
DEBUG ( 0 , ( " io_mem_get: reading data of size %u would overrun buffer. \n " ,
2000-05-12 18:35:13 +04:00
( unsigned int ) extra_size ) ) ;
return NULL ;
}
} else {
/*
* Writing - grow the buffer if needed .
*/
2000-05-31 09:39:54 +04:00
if ( ! io_grow ( ps , extra_size ) )
2000-05-12 18:35:13 +04:00
return False ;
}
return & ps - > data_p [ ps - > data_offset ] ;
}
/*******************************************************************
Initialise a parse structure - malloc the data if requested .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
BOOL io_init ( io_struct * ps , uint32 size , BOOL io )
2000-05-12 18:35:13 +04:00
{
ZERO_STRUCTP ( ps ) ;
ps - > io = io ;
ps - > bigendian_data = False ;
ps - > is_dynamic = False ;
ps - > data_offset = 0 ;
ps - > buffer_size = 0 ;
ps - > data_p = NULL ;
if ( size ! = 0 ) {
ps - > buffer_size = size ;
if ( ( ps - > data_p = ( char * ) malloc ( ( size_t ) size ) ) = = NULL ) {
2000-05-31 09:39:54 +04:00
DEBUG ( 0 , ( " io_init: malloc fail for %u bytes. \n " , ( unsigned int ) size ) ) ;
2000-05-12 18:35:13 +04:00
return False ;
}
ps - > is_dynamic = True ; /* We own this memory. */
}
return True ;
}
/*******************************************************************
debug output for parsing info .
XXXX side - effect of this function is to increase the debug depth XXXX
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
void io_debug ( io_struct * ps , int depth , char * desc , char * fn_name )
2000-05-12 18:35:13 +04:00
{
DEBUG ( 5 + depth , ( " %s%06x %s %s \n " , tab_depth ( depth ) , ps - > data_offset , fn_name , desc ) ) ;
}
/*******************************************************************
Align a the data_len to a multiple of align bytes - filling with
zeros .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
BOOL io_align2 ( io_struct * ps , int offset )
2000-05-12 18:35:13 +04:00
{
2000-05-29 00:05:30 +04:00
uint32 mod = ( ps - > data_offset + offset ) & ( 2 - 1 ) ;
if ( mod ! = 0 ) {
uint32 extra_space = ( 2 - mod ) ;
2000-05-31 09:39:54 +04:00
if ( ! io_grow ( ps , extra_space ) )
2000-05-29 00:05:30 +04:00
return False ;
memset ( & ps - > data_p [ ps - > data_offset ] , ' \0 ' , ( size_t ) extra_space ) ;
ps - > data_offset + = extra_space ;
}
return True ;
}
2000-05-31 09:39:54 +04:00
BOOL io_align4 ( io_struct * ps , int offset )
2000-05-29 00:05:30 +04:00
{
uint32 mod = ( ps - > data_offset + offset ) & ( 4 - 1 ) ;
if ( mod ! = 0 ) {
uint32 extra_space = ( 4 - mod ) ;
2000-05-31 09:39:54 +04:00
if ( ! io_grow ( ps , extra_space ) )
2000-05-29 00:05:30 +04:00
return False ;
memset ( & ps - > data_p [ ps - > data_offset ] , ' \0 ' , ( size_t ) extra_space ) ;
ps - > data_offset + = extra_space ;
}
2000-05-12 18:35:13 +04:00
2000-05-27 05:21:27 +04:00
return True ;
2000-05-29 00:05:30 +04:00
}
2000-05-27 05:21:27 +04:00
2000-05-29 00:05:30 +04:00
/*******************************************************************
Align a the data_len to a multiple of align bytes - filling with
zeros .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
BOOL io_align ( io_struct * ps , int align )
2000-05-29 00:05:30 +04:00
{
2000-06-09 06:59:50 +04:00
uint32 mod ;
if ( ! ps - > autoalign ) return True ;
mod = ps - > data_offset & ( align - 1 ) ;
2000-05-29 00:05:30 +04:00
2000-05-22 13:09:37 +04:00
if ( align ! = 0 & & mod ! = 0 ) {
uint32 extra_space = ( align - mod ) ;
2000-05-31 09:39:54 +04:00
if ( ! io_grow ( ps , extra_space ) )
2000-05-12 18:35:13 +04:00
return False ;
memset ( & ps - > data_p [ ps - > data_offset ] , ' \0 ' , ( size_t ) extra_space ) ;
ps - > data_offset + = extra_space ;
}
return True ;
}
/*******************************************************************
read from a socket into memory .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
BOOL io_read ( io_struct * ps , int fd , size_t len , int timeout )
2000-05-12 18:35:13 +04:00
{
BOOL ok ;
size_t prev_size = ps - > buffer_size ;
2000-05-31 09:39:54 +04:00
if ( ! io_grow ( ps , len ) )
2000-05-12 18:35:13 +04:00
{
return False ;
}
if ( timeout > 0 )
{
ok = ( read ( fd , & ps - > data_p [ prev_size ] , len ) = = len ) ;
}
else
{
ok = ( read ( fd , & ps - > data_p [ prev_size ] , len ) = = len ) ;
}
return ok ;
}
2000-05-16 15:55:06 +04:00
2000-05-12 18:35:13 +04:00
/*******************************************************************
2000-05-16 15:55:06 +04:00
do IO on a uint32 .
2000-05-12 18:35:13 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
BOOL io_uint32 ( char * name , io_struct * ps , int depth , uint32 * data32 , unsigned flags )
2000-05-12 18:35:13 +04:00
{
2000-05-16 15:55:06 +04:00
char * q ;
if ( ! ( flags & PARSE_SCALARS ) ) return True ;
2000-05-31 09:39:54 +04:00
if ( ! io_align ( ps , 4 ) ) return False ;
2000-05-22 13:09:37 +04:00
2000-05-31 09:39:54 +04:00
q = io_mem_get ( ps , sizeof ( uint32 ) ) ;
2000-05-16 15:55:06 +04:00
if ( q = = NULL ) return False ;
DBG_RW_IVAL ( name , depth , ps - > data_offset , ps - > io , ps - > bigendian_data , q , * data32 )
ps - > data_offset + = sizeof ( uint32 ) ;
2000-05-14 18:05:10 +04:00
return True ;
2000-05-12 18:35:13 +04:00
}
2000-05-16 15:55:06 +04:00
/*******************************************************************
do IO on a uint16 .
2000-05-14 18:05:10 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
BOOL io_uint16 ( char * name , io_struct * ps , int depth , uint16 * data16 , unsigned flags )
2000-05-12 18:35:13 +04:00
{
2000-05-16 15:55:06 +04:00
char * q ;
2000-05-12 18:35:13 +04:00
2000-05-16 15:55:06 +04:00
if ( ! ( flags & PARSE_SCALARS ) ) return True ;
2000-05-31 09:39:54 +04:00
if ( ! io_align ( ps , 2 ) ) return False ;
2000-05-22 13:09:37 +04:00
2000-05-31 09:39:54 +04:00
q = io_mem_get ( ps , sizeof ( uint16 ) ) ;
2000-05-16 15:55:06 +04:00
if ( q = = NULL ) return False ;
2000-05-31 09:39:54 +04:00
DBG_RW_SVAL ( name , depth , ps - > data_offset , ps - > io , ps - > bigendian_data , q , * data16 )
2000-05-16 15:55:06 +04:00
ps - > data_offset + = sizeof ( uint16 ) ;
2000-05-12 18:35:13 +04:00
return True ;
}
2000-05-16 15:55:06 +04:00
/*******************************************************************
do IO on a uint8 .
2000-05-12 18:35:13 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
BOOL io_uint8 ( char * name , io_struct * ps , int depth , uint8 * data8 , unsigned flags )
2000-05-12 18:35:13 +04:00
{
2000-05-16 15:55:06 +04:00
char * q ;
if ( ! ( flags & PARSE_SCALARS ) ) return True ;
2000-05-31 09:39:54 +04:00
q = io_mem_get ( ps , sizeof ( uint8 ) ) ;
2000-05-16 15:55:06 +04:00
if ( q = = NULL ) return False ;
2000-05-12 18:35:13 +04:00
2000-05-16 15:55:06 +04:00
DBG_RW_IVAL ( name , depth , ps - > data_offset , ps - > io , ps - > bigendian_data , q , * data8 )
ps - > data_offset + = sizeof ( uint8 ) ;
2000-05-12 18:35:13 +04:00
return True ;
}
2000-05-14 18:44:59 +04:00
/*******************************************************************
2000-05-16 15:55:06 +04:00
do IO on a pointer
2000-05-14 18:44:59 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
BOOL io_pointer ( char * desc , io_struct * ps , int depth , void * * p , unsigned flags )
2000-05-16 15:55:06 +04:00
{
uint32 v ;
if ( ! ( flags & PARSE_SCALARS ) ) return True ;
2000-05-14 18:44:59 +04:00
2000-05-17 06:16:44 +04:00
v = ( * p ) ? 0xdeadbeef : 0 ;
2000-05-16 15:55:06 +04:00
if ( ! io_uint32 ( desc , ps , depth , & v , flags ) ) return False ;
2000-05-17 06:16:44 +04:00
* p = ( void * ) ( v ? 0xdeadbeef : 0 ) ;
2000-05-16 15:55:06 +04:00
return True ;
}
2000-05-27 05:21:27 +04:00
/*******************************************************************
Stream a null - terminated string .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
BOOL io_SMBSTR ( char * name , io_struct * ps , int depth , char * * str , unsigned flags )
2000-05-27 05:21:27 +04:00
{
char * q ;
uint8 * start ;
int i ;
2000-05-27 14:18:36 +04:00
size_t len ;
2000-05-29 00:05:30 +04:00
int start_offset = ps - > data_offset ;
2000-05-27 05:21:27 +04:00
if ( ! ( flags & PARSE_SCALARS ) ) return True ;
2000-05-27 14:18:36 +04:00
if ( UNMARSHALLING ( ps ) ) {
2000-05-31 09:39:54 +04:00
* str = io_mem_get ( ps , 0 ) ;
2000-05-27 14:18:36 +04:00
if ( * str = = NULL )
2000-05-27 05:21:27 +04:00
return False ;
2000-05-27 14:18:36 +04:00
len = strlen ( * str ) ;
ps - > data_offset + = len + 1 ;
2000-05-27 05:21:27 +04:00
}
2000-05-27 14:18:36 +04:00
else
{
2000-05-31 09:39:54 +04:00
len = strlen ( * str ) + 1 ;
2000-05-27 14:18:36 +04:00
start = ( uint8 * ) q ;
for ( i = 0 ; i < len ; i + + ) {
2000-05-31 09:39:54 +04:00
q = io_mem_get ( ps , 1 ) ;
2000-05-27 14:18:36 +04:00
if ( q = = NULL )
return False ;
RW_CVAL ( ps - > io , q , ( * str ) [ i ] , 0 ) ;
ps - > data_offset + + ;
}
}
2000-05-27 05:21:27 +04:00
2000-05-29 00:05:30 +04:00
DEBUG ( 5 , ( " %s%04x %s: %s \n " , tab_depth ( depth ) ,
start_offset , name , * str ) ) ;
2000-05-27 05:21:27 +04:00
return True ;
}
/******************************************************************
do IO on a byte array
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
BOOL io_uint8s ( char * name , io_struct * ps , int depth , uint8 * * data8s , int len , unsigned flags )
2000-05-27 05:21:27 +04:00
{
char * q ;
2000-05-27 14:18:36 +04:00
size_t num_bytes = len * sizeof ( uint8 ) ;
2000-05-27 05:21:27 +04:00
if ( ! ( flags & PARSE_SCALARS ) ) return True ;
2000-05-31 09:39:54 +04:00
q = io_mem_get ( ps , num_bytes ) ;
2000-05-27 05:21:27 +04:00
if ( q = = NULL ) return False ;
2000-05-27 14:18:36 +04:00
if ( MARSHALLING ( ps ) )
{
DBG_RW_PCVAL ( True , name , depth , ps - > data_offset , ps - > io , q , * data8s , len )
}
else
{
* data8s = q ;
2000-05-31 09:39:54 +04:00
dump_data ( depth + 5 , * data8s , num_bytes ) ;
2000-05-27 14:18:36 +04:00
}
ps - > data_offset + = num_bytes ;
2000-05-27 05:21:27 +04:00
return True ;
}
2000-05-31 09:39:54 +04:00
/******************************************************************
do IO on a fixed - size byte array
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL io_uint8s_fixed ( char * name , io_struct * ps , int depth , uint8 * data8s , int len , unsigned flags )
{
char * q ;
size_t num_bytes = len * sizeof ( uint8 ) ;
if ( ! ( flags & PARSE_SCALARS ) ) return True ;
q = io_mem_get ( ps , num_bytes ) ;
if ( q = = NULL ) return False ;
DBG_RW_PCVAL ( True , name , depth , ps - > data_offset , ps - > io , q , data8s , len )
ps - > data_offset + = num_bytes ;
return True ;
}
/******************************************************************
do IO on an io ( eh ? ? : )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL io_io_struct ( char * name , io_struct * ps , int depth , io_struct * io , unsigned flags )
{
char * q ;
uint16 len ;
if ( ! ( flags & PARSE_SCALARS ) ) return True ;
2000-05-27 05:21:27 +04:00
2000-05-31 09:39:54 +04:00
q = io_mem_get ( ps , sizeof ( uint16 ) ) ;
if ( q = = NULL ) return False ;
/* length first */
if ( MARSHALLING ( ps ) )
{
len = io - > data_offset ;
}
if ( ! io_uint16 ( " len " , ps , depth + 1 , & len , flags ) )
{
return False ;
}
if ( UNMARSHALLING ( ps ) )
{
if ( ! io_init ( io , len , UNMARSHALL ) )
{
return False ;
}
}
/* now data */
q = io_mem_get ( ps , len * sizeof ( uint8 ) ) ;
if ( q = = NULL ) return False ;
if ( MARSHALLING ( ps ) )
{
DBG_RW_PCVAL ( False , name , depth + 1 , ps - > data_offset , ps - > io , q , io - > data_p , len )
}
else
{
io - > data_p = q ;
dump_data ( depth + 5 , q , len ) ;
}
ps - > data_offset + = len ;
return True ;
}
2000-05-27 05:21:27 +04:00
2000-05-16 15:55:06 +04:00
/******************************************************************
do IO on a unicode array
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
BOOL io_wstring ( char * name , io_struct * ps , int depth , uint16 * data16s , int len , unsigned flags )
2000-05-14 18:44:59 +04:00
{
2000-05-16 15:55:06 +04:00
char * q ;
2000-05-14 18:44:59 +04:00
2000-05-16 15:55:06 +04:00
if ( ! ( flags & PARSE_SCALARS ) ) return True ;
2000-05-31 09:39:54 +04:00
if ( ! io_align ( ps , 2 ) ) return False ;
2000-05-22 13:09:37 +04:00
2000-05-31 09:39:54 +04:00
q = io_mem_get ( ps , len * sizeof ( uint16 ) ) ;
2000-05-16 15:55:06 +04:00
if ( q = = NULL ) return False ;
2000-06-09 06:59:50 +04:00
DBG_RW_PSVAL ( True , name , depth , ps - > data_offset , ps - > io , ps - > bigendian_data , q , data16s , len )
2000-05-16 15:55:06 +04:00
ps - > data_offset + = ( len * sizeof ( uint16 ) ) ;
2000-05-14 18:44:59 +04:00
return True ;
}
2000-05-16 15:55:06 +04:00
/******************************************************************
allocate some memory for a parse structure
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
void io_free ( io_struct * ps )
{
if ( ps - > is_dynamic & & ps - > data_p )
{
free ( ps - > data_p ) ;
ps - > data_p = NULL ;
}
}
/******************************************************************
allocate some memory for a parse structure
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL io_alloc ( char * name , io_struct * ps , void * * ptr , unsigned size )
2000-05-16 15:55:06 +04:00
{
( * ptr ) = ( void * ) malloc ( size ) ;
if ( * ptr ) return True ;
return False ;
}
2000-05-27 05:21:27 +04:00
/******************************************************************
realloc some memory for a parse structure
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-31 09:39:54 +04:00
BOOL io_realloc ( char * name , io_struct * ps , void * * ptr , unsigned size )
2000-05-27 05:21:27 +04:00
{
2001-08-12 21:30:01 +04:00
BOOL ret = True ;
void * tp ;
tp = ( void * ) Realloc ( * ptr , size ) ;
if ( tp ) * ptr = tp ;
else ret = False ;
return ret ;
2000-05-27 05:21:27 +04:00
}