2004-03-31 06:45:39 +00:00
/*
ldb database library
Copyright ( C ) Andrew Tridgell 2004
* * NOTE ! The following LGPL license applies to the ldb
* * library . This does NOT imply that all of Samba is released
* * under the LGPL
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
version 2 of the License , or ( at your option ) any later version .
This library 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
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
License along with this library ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
/*
* Name : ldb
*
* Component : ldb pack / unpack
*
* Description : pack / unpack routines for ldb messages as key / value blobs
*
* Author : Andrew Tridgell
*/
# include "includes.h"
2004-04-10 20:18:22 +00:00
# include "ldb/ldb_tdb/ldb_tdb.h"
2004-03-31 06:45:39 +00:00
/* change this if the data format ever changes */
# define LTDB_PACKING_FORMAT 0x26011966
/*
pack a ldb message into a linear buffer in a TDB_DATA
2004-04-03 12:29:21 +00:00
note that this routine avoids saving elements with zero values ,
as these are equivalent to having no element
2004-03-31 06:45:39 +00:00
caller frees the data buffer after use
*/
int ltdb_pack_data ( struct ldb_context * ctx ,
const struct ldb_message * message ,
struct TDB_DATA * data )
{
2004-04-03 12:29:21 +00:00
int i , j ;
2004-03-31 06:45:39 +00:00
size_t size ;
char * p ;
/* work out how big it needs to be */
size = 8 ;
for ( i = 0 ; i < message - > num_elements ; i + + ) {
2004-04-03 12:29:21 +00:00
if ( message - > elements [ i ] . num_values = = 0 ) {
continue ;
}
size + = 1 + strlen ( message - > elements [ i ] . name ) + 4 ;
for ( j = 0 ; j < message - > elements [ i ] . num_values ; j + + ) {
size + = 4 + message - > elements [ i ] . values [ j ] . length + 1 ;
}
2004-03-31 06:45:39 +00:00
}
/* allocate it */
data - > dptr = malloc ( size ) ;
if ( ! data - > dptr ) {
errno = ENOMEM ;
return - 1 ;
}
data - > dsize = size ;
p = data - > dptr ;
SIVAL ( p , 0 , LTDB_PACKING_FORMAT ) ;
SIVAL ( p , 4 , message - > num_elements ) ;
p + = 8 ;
for ( i = 0 ; i < message - > num_elements ; i + + ) {
2004-04-03 12:29:21 +00:00
size_t len ;
if ( message - > elements [ i ] . num_values = = 0 ) {
continue ;
}
len = strlen ( message - > elements [ i ] . name ) ;
2004-03-31 06:45:39 +00:00
memcpy ( p , message - > elements [ i ] . name , len + 1 ) ;
p + = len + 1 ;
2004-04-03 12:29:21 +00:00
SIVAL ( p , 0 , message - > elements [ i ] . num_values ) ;
p + = 4 ;
for ( j = 0 ; j < message - > elements [ i ] . num_values ; j + + ) {
SIVAL ( p , 0 , message - > elements [ i ] . values [ j ] . length ) ;
memcpy ( p + 4 , message - > elements [ i ] . values [ j ] . data ,
message - > elements [ i ] . values [ j ] . length ) ;
p [ 4 + message - > elements [ i ] . values [ j ] . length ] = 0 ;
p + = 4 + message - > elements [ i ] . values [ j ] . length + 1 ;
}
2004-03-31 06:45:39 +00:00
}
return 0 ;
}
2004-04-03 12:29:21 +00:00
/*
free the memory allocated from a ltdb_unpack_data ( )
*/
void ltdb_unpack_data_free ( struct ldb_message * message )
{
int i ;
for ( i = 0 ; i < message - > num_elements ; i + + ) {
if ( message - > elements [ i ] . values ) free ( message - > elements [ i ] . values ) ;
}
if ( message - > elements ) free ( message - > elements ) ;
}
2004-03-31 06:45:39 +00:00
/*
unpack a ldb message from a linear buffer in TDB_DATA
note that this does not fill in the class and key elements
2004-04-03 12:29:21 +00:00
caller frees . Memory for the elements [ ] and values [ ] arrays are
malloced , but the memory for the elements is re - used from the
TDB_DATA data . This means the caller only has to free the elements
and values arrays . This can be done with ltdb_unpack_data_free ( )
2004-03-31 06:45:39 +00:00
*/
int ltdb_unpack_data ( struct ldb_context * ctx ,
const struct TDB_DATA * data ,
struct ldb_message * message )
{
char * p ;
unsigned int remaining ;
2004-04-03 12:29:21 +00:00
int i , j ;
2004-03-31 06:45:39 +00:00
message - > elements = NULL ;
p = data - > dptr ;
if ( data - > dsize < 4 ) {
errno = EIO ;
goto failed ;
}
if ( IVAL ( p , 0 ) ! = LTDB_PACKING_FORMAT ) {
/* this is where we will cope with upgrading the
format if / when the format is ever changed */
errno = EIO ;
goto failed ;
}
message - > num_elements = IVAL ( p , 4 ) ;
p + = 8 ;
if ( message - > num_elements = = 0 ) {
message - > elements = NULL ;
return 0 ;
}
/* basic sanity check */
remaining = data - > dsize - 8 ;
if ( message - > num_elements > remaining / 6 ) {
errno = EIO ;
goto failed ;
}
message - > elements = malloc_array_p ( struct ldb_message_element ,
message - > num_elements ) ;
if ( ! message - > elements ) {
errno = ENOMEM ;
goto failed ;
}
for ( i = 0 ; i < message - > num_elements ; i + + ) {
size_t len ;
2004-04-03 12:29:21 +00:00
if ( remaining < 10 ) {
2004-03-31 06:45:39 +00:00
errno = EIO ;
goto failed ;
}
len = strnlen ( p , remaining - 6 ) ;
2004-04-03 12:29:21 +00:00
message - > elements [ i ] . flags = 0 ;
2004-03-31 06:45:39 +00:00
message - > elements [ i ] . name = p ;
remaining - = len + 1 ;
p + = len + 1 ;
2004-04-03 12:29:21 +00:00
message - > elements [ i ] . num_values = IVAL ( p , 0 ) ;
message - > elements [ i ] . values = NULL ;
if ( message - > elements [ i ] . num_values ! = 0 ) {
message - > elements [ i ] . values = malloc_array_p ( struct ldb_val ,
message - > elements [ i ] . num_values ) ;
if ( ! message - > elements [ i ] . values ) {
errno = ENOMEM ;
goto failed ;
}
}
p + = 4 ;
for ( j = 0 ; j < message - > elements [ i ] . num_values ; j + + ) {
len = IVAL ( p , 0 ) ;
if ( len > remaining - 5 ) {
errno = EIO ;
goto failed ;
}
message - > elements [ i ] . values [ j ] . length = len ;
message - > elements [ i ] . values [ j ] . data = p + 4 ;
remaining - = len + 4 + 1 ;
p + = len + 4 + 1 ;
2004-03-31 06:45:39 +00:00
}
}
return 0 ;
failed :
2004-04-03 12:29:21 +00:00
ltdb_unpack_data_free ( message ) ;
2004-03-31 06:45:39 +00:00
return - 1 ;
}