2015-02-11 15:19:05 +03:00
/*
* talloc_report into a string
*
* Copyright Volker Lendecke < vl @ samba . org > 2015
*
* 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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "replace.h"
# include "talloc_report.h"
/*
* talloc_vasprintf into a buffer that doubles its size . The real string
* length is maintained in " pstr_len " .
*/
2016-08-02 11:11:17 +03:00
static char * talloc_vasprintf_append_largebuf ( char * buf , ssize_t * pstr_len ,
const char * fmt , va_list ap )
PRINTF_ATTRIBUTE ( 3 , 0 ) ;
2015-02-11 15:19:05 +03:00
static char * talloc_vasprintf_append_largebuf ( char * buf , ssize_t * pstr_len ,
const char * fmt , va_list ap )
{
ssize_t str_len = * pstr_len ;
2018-11-12 12:17:37 +03:00
size_t buflen , needed , space = 0 ;
char * start = NULL , * tmpbuf = NULL ;
2015-02-11 15:19:05 +03:00
va_list ap2 ;
int printlen ;
if ( str_len = = - 1 ) {
return NULL ;
}
if ( buf = = NULL ) {
return NULL ;
}
2016-06-22 10:17:07 +03:00
if ( fmt = = NULL ) {
return NULL ;
}
2015-02-11 15:19:05 +03:00
buflen = talloc_get_size ( buf ) ;
2019-06-21 08:11:49 +03:00
if ( buflen > ( size_t ) str_len ) {
2015-02-11 15:19:05 +03:00
start = buf + str_len ;
space = buflen - str_len ;
2019-05-21 13:48:18 +03:00
} else {
return NULL ;
2015-02-11 15:19:05 +03:00
}
va_copy ( ap2 , ap ) ;
printlen = vsnprintf ( start , space , fmt , ap2 ) ;
va_end ( ap2 ) ;
if ( printlen < 0 ) {
goto fail ;
}
needed = str_len + printlen + 1 ;
if ( needed > buflen ) {
buflen = MAX ( 128 , buflen ) ;
while ( buflen < needed ) {
buflen * = 2 ;
}
tmpbuf = talloc_realloc ( NULL , buf , char , buflen ) ;
if ( tmpbuf = = NULL ) {
goto fail ;
}
buf = tmpbuf ;
va_copy ( ap2 , ap ) ;
vsnprintf ( buf + str_len , buflen - str_len , fmt , ap2 ) ;
va_end ( ap2 ) ;
}
* pstr_len = ( needed - 1 ) ;
return buf ;
fail :
* pstr_len = - 1 ;
return buf ;
}
2016-08-02 11:11:17 +03:00
static char * talloc_asprintf_append_largebuf ( char * buf , ssize_t * pstr_len ,
const char * fmt , . . . )
PRINTF_ATTRIBUTE ( 3 , 4 ) ;
2015-02-11 15:19:05 +03:00
static char * talloc_asprintf_append_largebuf ( char * buf , ssize_t * pstr_len ,
const char * fmt , . . . )
{
va_list ap ;
va_start ( ap , fmt ) ;
buf = talloc_vasprintf_append_largebuf ( buf , pstr_len , fmt , ap ) ;
va_end ( ap ) ;
return buf ;
}
struct talloc_report_str_state {
ssize_t str_len ;
char * s ;
} ;
static void talloc_report_str_helper ( const void * ptr , int depth , int max_depth ,
int is_ref , void * private_data )
{
struct talloc_report_str_state * state = private_data ;
const char * name = talloc_get_name ( ptr ) ;
if ( ptr = = state - > s ) {
return ;
}
if ( is_ref ) {
state - > s = talloc_asprintf_append_largebuf (
state - > s , & state - > str_len ,
" %*sreference to: %s \n " , depth * 4 , " " , name ) ;
return ;
}
if ( depth = = 0 ) {
state - > s = talloc_asprintf_append_largebuf (
state - > s , & state - > str_len ,
" %stalloc report on '%s' "
" (total %6lu bytes in %3lu blocks) \n " ,
( max_depth < 0 ? " full " : " " ) , name ,
( unsigned long ) talloc_total_size ( ptr ) ,
( unsigned long ) talloc_total_blocks ( ptr ) ) ;
return ;
}
if ( strcmp ( name , " char " ) = = 0 ) {
/*
* Print out the first 50 bytes of the string
*/
state - > s = talloc_asprintf_append_largebuf (
state - > s , & state - > str_len ,
" %*s%-30s contains %6lu bytes in %3lu blocks "
2016-08-21 19:53:00 +03:00
" (ref %zu): %*s \n " , depth * 4 , " " , name ,
2015-02-11 15:19:05 +03:00
( unsigned long ) talloc_total_size ( ptr ) ,
( unsigned long ) talloc_total_blocks ( ptr ) ,
talloc_reference_count ( ptr ) ,
2016-08-21 19:53:00 +03:00
( int ) MIN ( 50 , talloc_get_size ( ptr ) ) ,
2015-02-11 15:19:05 +03:00
( const char * ) ptr ) ;
return ;
}
state - > s = talloc_asprintf_append_largebuf (
state - > s , & state - > str_len ,
2016-08-21 19:53:00 +03:00
" %*s%-30s contains %6lu bytes in %3lu blocks (ref %zu) %p \n " ,
2015-02-11 15:19:05 +03:00
depth * 4 , " " , name ,
( unsigned long ) talloc_total_size ( ptr ) ,
( unsigned long ) talloc_total_blocks ( ptr ) ,
2015-08-17 12:55:26 +03:00
talloc_reference_count ( ptr ) , ptr ) ;
2015-02-11 15:19:05 +03:00
}
char * talloc_report_str ( TALLOC_CTX * mem_ctx , TALLOC_CTX * root )
{
struct talloc_report_str_state state ;
state . s = talloc_strdup ( mem_ctx , " " ) ;
if ( state . s = = NULL ) {
return NULL ;
}
state . str_len = 0 ;
talloc_report_depth_cb ( root , 0 , - 1 , talloc_report_str_helper , & state ) ;
if ( state . str_len = = - 1 ) {
talloc_free ( state . s ) ;
return NULL ;
}
return talloc_realloc ( mem_ctx , state . s , char , state . str_len + 1 ) ;
}