2004-03-31 06:45:39 +00:00
/*
ldb database library
Copyright ( C ) Andrew Tridgell 2004
2004-10-20 19:28:02 +00:00
Copyright ( C ) Stefan Metzmacher 2004
2004-03-31 06:45:39 +00:00
* * 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 tdb backend
*
* Description : core functions for tdb backend
*
* Author : Andrew Tridgell
2004-10-20 19:28:02 +00:00
* Author : Stefan Metzmacher
2004-03-31 06:45:39 +00:00
*/
# include "includes.h"
2004-11-16 09:00:52 +00:00
# include "ldb/include/ldb.h"
# include "ldb/include/ldb_private.h"
2004-04-10 20:18:22 +00:00
# include "ldb/ldb_tdb/ldb_tdb.h"
2004-03-31 06:45:39 +00:00
2004-11-21 15:51:54 +00:00
# define LDBLOCK "INT_LDBLOCK"
2004-03-31 06:45:39 +00:00
/*
form a TDB_DATA for a record key
caller frees
2004-05-01 09:45:56 +00:00
note that the key for a record can depend on whether the
dn refers to a case sensitive index record or not
2004-03-31 06:45:39 +00:00
*/
2004-11-15 11:40:27 +00:00
struct TDB_DATA ltdb_key ( struct ldb_module * module , const char * dn )
2004-03-31 06:45:39 +00:00
{
2004-11-15 11:40:27 +00:00
struct ldb_context * ldb = module - > ldb ;
2004-03-31 06:45:39 +00:00
TDB_DATA key ;
char * key_str = NULL ;
2004-05-01 09:45:56 +00:00
char * dn_folded = NULL ;
const char * prefix = LTDB_INDEX " : " ;
const char * s ;
int flags ;
/*
most DNs are case insensitive . The exception is index DNs for
case sensitive attributes
2004-05-04 05:58:22 +00:00
there are 3 cases dealt with in this code :
1 ) if the dn doesn ' t start with @ INDEX : then uppercase whole dn
2 ) if the dn starts with @ INDEX : attr and ' attr ' is a case insensitive
attribute then uppercase whole dn
3 ) if the dn starts with @ INDEX : attr and ' attr ' is a case sensitive
attribute then uppercase up to the value of the attribute , but
not the value itself
2004-05-01 09:45:56 +00:00
*/
if ( strncmp ( dn , prefix , strlen ( prefix ) ) = = 0 & &
( s = strchr ( dn + strlen ( prefix ) , ' : ' ) ) ) {
char * attr_name , * attr_name_folded ;
2004-05-06 04:40:15 +00:00
attr_name = ldb_strndup ( ldb , dn + strlen ( prefix ) , ( s - ( dn + strlen ( prefix ) ) ) ) ;
2004-05-01 09:45:56 +00:00
if ( ! attr_name ) {
goto failed ;
}
2004-11-15 11:40:27 +00:00
flags = ltdb_attribute_flags ( module , attr_name ) ;
2004-05-01 09:45:56 +00:00
if ( flags & LTDB_FLAG_CASE_INSENSITIVE ) {
2004-05-06 04:40:15 +00:00
dn_folded = ldb_casefold ( ldb , dn ) ;
2004-05-01 09:45:56 +00:00
} else {
2004-05-06 04:40:15 +00:00
attr_name_folded = ldb_casefold ( ldb , attr_name ) ;
2004-05-01 09:45:56 +00:00
if ( ! attr_name_folded ) {
goto failed ;
}
2004-05-06 04:40:15 +00:00
ldb_asprintf ( ldb , & dn_folded , " %s:%s:%s " ,
2004-05-01 09:45:56 +00:00
prefix , attr_name_folded ,
s + 1 ) ;
2004-05-06 04:40:15 +00:00
ldb_free ( ldb , attr_name_folded ) ;
2004-05-01 09:45:56 +00:00
}
2004-05-06 04:40:15 +00:00
ldb_free ( ldb , attr_name ) ;
2004-05-01 09:45:56 +00:00
} else {
2004-05-06 04:40:15 +00:00
dn_folded = ldb_casefold ( ldb , dn ) ;
2004-05-01 09:45:56 +00:00
}
if ( ! dn_folded ) {
goto failed ;
}
2004-05-06 04:40:15 +00:00
ldb_asprintf ( ldb , & key_str , " DN=%s " , dn_folded ) ;
ldb_free ( ldb , dn_folded ) ;
2004-03-31 06:45:39 +00:00
if ( ! key_str ) {
2004-05-01 09:45:56 +00:00
goto failed ;
2004-03-31 06:45:39 +00:00
}
key . dptr = key_str ;
key . dsize = strlen ( key_str ) + 1 ;
return key ;
2004-05-01 09:45:56 +00:00
failed :
errno = ENOMEM ;
key . dptr = NULL ;
key . dsize = 0 ;
return key ;
2004-03-31 06:45:39 +00:00
}
2004-04-03 12:29:21 +00:00
/*
lock the database for write - currently a single lock is used
*/
2004-11-21 15:51:54 +00:00
static int ltdb_lock ( struct ldb_module * module , const char * lockname )
2004-04-03 12:29:21 +00:00
{
2004-11-15 11:40:27 +00:00
struct ldb_context * ldb = module - > ldb ;
struct ltdb_private * ltdb = module - > private_data ;
2004-04-03 12:29:21 +00:00
TDB_DATA key ;
int ret ;
2004-11-21 15:51:54 +00:00
if ( lockname = = NULL ) {
return - 1 ;
}
key = ltdb_key ( module , lockname ) ;
2004-04-03 12:29:21 +00:00
if ( ! key . dptr ) {
return - 1 ;
}
ret = tdb_chainlock ( ltdb - > tdb , key ) ;
2004-05-06 04:40:15 +00:00
ldb_free ( ldb , key . dptr ) ;
2004-04-03 12:29:21 +00:00
return ret ;
}
/*
unlock the database after a ltdb_lock ( )
*/
2004-11-21 15:51:54 +00:00
static int ltdb_unlock ( struct ldb_module * module , const char * lockname )
2004-04-03 12:29:21 +00:00
{
2004-11-15 11:40:27 +00:00
struct ldb_context * ldb = module - > ldb ;
struct ltdb_private * ltdb = module - > private_data ;
2004-04-03 12:29:21 +00:00
TDB_DATA key ;
2004-11-21 15:51:54 +00:00
if ( lockname = = NULL ) {
return - 1 ;
}
key = ltdb_key ( module , lockname ) ;
2004-04-03 12:29:21 +00:00
if ( ! key . dptr ) {
2004-11-21 15:51:54 +00:00
return - 1 ;
2004-04-03 12:29:21 +00:00
}
tdb_chainunlock ( ltdb - > tdb , key ) ;
2004-05-06 04:40:15 +00:00
ldb_free ( ldb , key . dptr ) ;
2004-11-21 15:51:54 +00:00
return 0 ;
2004-04-03 12:29:21 +00:00
}
2004-03-31 06:45:39 +00:00
2004-05-01 09:45:56 +00:00
/*
we ' ve made a modification to a dn - possibly reindex and
update sequence number
*/
2004-11-15 11:40:27 +00:00
static int ltdb_modified ( struct ldb_module * module , const char * dn )
2004-05-01 09:45:56 +00:00
{
int ret = 0 ;
if ( strcmp ( dn , LTDB_INDEXLIST ) = = 0 | |
strcmp ( dn , LTDB_ATTRIBUTES ) = = 0 ) {
2004-11-15 11:40:27 +00:00
ret = ltdb_reindex ( module ) ;
2004-05-01 09:45:56 +00:00
}
if ( ret = = 0 & &
strcmp ( dn , LTDB_BASEINFO ) ! = 0 ) {
2004-11-15 11:40:27 +00:00
ret = ltdb_increase_sequence_number ( module ) ;
2004-05-01 09:45:56 +00:00
}
return ret ;
}
2004-03-31 06:45:39 +00:00
/*
store a record into the db
*/
2004-11-15 11:40:27 +00:00
int ltdb_store ( struct ldb_module * module , const struct ldb_message * msg , int flgs )
2004-03-31 06:45:39 +00:00
{
2004-11-15 11:40:27 +00:00
struct ldb_context * ldb = module - > ldb ;
struct ltdb_private * ltdb = module - > private_data ;
2004-03-31 06:45:39 +00:00
TDB_DATA tdb_key , tdb_data ;
int ret ;
2004-11-15 11:40:27 +00:00
tdb_key = ltdb_key ( module , msg - > dn ) ;
2004-03-31 06:45:39 +00:00
if ( ! tdb_key . dptr ) {
return - 1 ;
}
2004-11-16 09:00:52 +00:00
ret = ltdb_pack_data ( module , msg , & tdb_data ) ;
2004-03-31 06:45:39 +00:00
if ( ret = = - 1 ) {
2004-05-06 04:40:15 +00:00
ldb_free ( ldb , tdb_key . dptr ) ;
2004-03-31 06:45:39 +00:00
return - 1 ;
}
ret = tdb_store ( ltdb - > tdb , tdb_key , tdb_data , flgs ) ;
if ( ret = = - 1 ) {
goto done ;
}
2004-11-15 11:40:27 +00:00
ret = ltdb_index_add ( module , msg ) ;
2004-03-31 06:45:39 +00:00
if ( ret = = - 1 ) {
tdb_delete ( ltdb - > tdb , tdb_key ) ;
}
done :
2004-05-06 04:40:15 +00:00
ldb_free ( ldb , tdb_key . dptr ) ;
ldb_free ( ldb , tdb_data . dptr ) ;
2004-03-31 06:45:39 +00:00
return ret ;
}
/*
add a record to the database
*/
2004-11-15 11:40:27 +00:00
static int ltdb_add ( struct ldb_module * module , const struct ldb_message * msg )
2004-03-31 06:45:39 +00:00
{
2004-11-15 11:40:27 +00:00
struct ltdb_private * ltdb = module - > private_data ;
2004-04-03 12:29:21 +00:00
int ret ;
2004-05-06 04:40:15 +00:00
ltdb - > last_err_string = NULL ;
2004-11-21 15:51:54 +00:00
if ( ltdb_lock ( module , LDBLOCK ) ! = 0 ) {
2004-04-03 12:29:21 +00:00
return - 1 ;
}
2004-05-01 09:45:56 +00:00
2004-11-15 11:40:27 +00:00
if ( ltdb_cache_load ( module ) ! = 0 ) {
2004-11-21 15:51:54 +00:00
ltdb_unlock ( module , LDBLOCK ) ;
2004-05-01 09:45:56 +00:00
return - 1 ;
}
2004-04-03 12:29:21 +00:00
2004-11-15 11:40:27 +00:00
ret = ltdb_store ( module , msg , TDB_INSERT ) ;
2004-04-03 12:29:21 +00:00
2004-05-01 09:45:56 +00:00
if ( ret = = 0 ) {
2004-11-15 11:40:27 +00:00
ltdb_modified ( module , msg - > dn ) ;
2004-04-23 13:05:27 +00:00
}
2004-11-21 15:51:54 +00:00
ltdb_unlock ( module , LDBLOCK ) ;
2004-04-03 12:29:21 +00:00
return ret ;
2004-03-31 06:45:39 +00:00
}
/*
delete a record from the database , not updating indexes ( used for deleting
index records )
*/
2004-11-15 11:40:27 +00:00
int ltdb_delete_noindex ( struct ldb_module * module , const char * dn )
2004-03-31 06:45:39 +00:00
{
2004-11-15 11:40:27 +00:00
struct ldb_context * ldb = module - > ldb ;
struct ltdb_private * ltdb = module - > private_data ;
2004-03-31 06:45:39 +00:00
TDB_DATA tdb_key ;
int ret ;
2004-11-15 11:40:27 +00:00
tdb_key = ltdb_key ( module , dn ) ;
2004-03-31 06:45:39 +00:00
if ( ! tdb_key . dptr ) {
return - 1 ;
}
ret = tdb_delete ( ltdb - > tdb , tdb_key ) ;
2004-05-06 04:40:15 +00:00
ldb_free ( ldb , tdb_key . dptr ) ;
2004-03-31 06:45:39 +00:00
return ret ;
}
/*
delete a record from the database
*/
2004-11-15 11:40:27 +00:00
static int ltdb_delete ( struct ldb_module * module , const char * dn )
2004-03-31 06:45:39 +00:00
{
2004-11-15 11:40:27 +00:00
struct ltdb_private * ltdb = module - > private_data ;
2004-03-31 06:45:39 +00:00
int ret ;
struct ldb_message msg ;
2004-05-06 04:40:15 +00:00
ltdb - > last_err_string = NULL ;
2004-11-21 15:51:54 +00:00
if ( ltdb_lock ( module , LDBLOCK ) ! = 0 ) {
2004-04-03 12:29:21 +00:00
return - 1 ;
}
2004-11-15 11:40:27 +00:00
if ( ltdb_cache_load ( module ) ! = 0 ) {
2004-11-21 15:51:54 +00:00
ltdb_unlock ( module , LDBLOCK ) ;
2004-05-01 09:45:56 +00:00
return - 1 ;
}
2004-03-31 06:45:39 +00:00
/* in case any attribute of the message was indexed, we need
to fetch the old record */
2004-11-15 11:40:27 +00:00
ret = ltdb_search_dn1 ( module , dn , & msg ) ;
2004-03-31 06:45:39 +00:00
if ( ret ! = 1 ) {
/* not finding the old record is an error */
2004-04-03 12:29:21 +00:00
goto failed ;
2004-03-31 06:45:39 +00:00
}
2004-11-15 11:40:27 +00:00
ret = ltdb_delete_noindex ( module , dn ) ;
2004-03-31 06:45:39 +00:00
if ( ret = = - 1 ) {
2004-11-15 11:40:27 +00:00
ltdb_search_dn1_free ( module , & msg ) ;
2004-04-03 12:29:21 +00:00
goto failed ;
2004-03-31 06:45:39 +00:00
}
/* remove any indexed attributes */
2004-11-15 11:40:27 +00:00
ret = ltdb_index_del ( module , & msg ) ;
2004-03-31 06:45:39 +00:00
2004-11-15 11:40:27 +00:00
ltdb_search_dn1_free ( module , & msg ) ;
2004-03-31 06:45:39 +00:00
2004-05-01 09:45:56 +00:00
if ( ret = = 0 ) {
2004-11-15 11:40:27 +00:00
ltdb_modified ( module , dn ) ;
2004-04-23 13:05:27 +00:00
}
2004-11-21 15:51:54 +00:00
ltdb_unlock ( module , LDBLOCK ) ;
2004-03-31 06:45:39 +00:00
return ret ;
2004-04-03 12:29:21 +00:00
failed :
2004-11-21 15:51:54 +00:00
ltdb_unlock ( module , LDBLOCK ) ;
2004-04-03 12:29:21 +00:00
return - 1 ;
}
/*
find an element by attribute name . At the moment this does a linear search , it should
be re - coded to use a binary search once all places that modify records guarantee
sorted order
return the index of the first matching element if found , otherwise - 1
*/
static int find_element ( const struct ldb_message * msg , const char * name )
{
2004-07-07 01:02:54 +00:00
unsigned int i ;
2004-04-03 12:29:21 +00:00
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
2004-05-01 09:45:56 +00:00
if ( ldb_attr_cmp ( msg - > elements [ i ] . name , name ) = = 0 ) {
2004-04-03 12:29:21 +00:00
return i ;
}
}
return - 1 ;
}
/*
add an element to an existing record . Assumes a elements array that we
can call re - alloc on , and assumed that we can re - use the data pointers from the
passed in additional values . Use with care !
returns 0 on success , - 1 on failure ( and sets errno )
*/
2004-05-06 04:40:15 +00:00
static int msg_add_element ( struct ldb_context * ldb ,
struct ldb_message * msg , struct ldb_message_element * el )
2004-04-03 12:29:21 +00:00
{
struct ldb_message_element * e2 ;
2004-07-07 01:02:54 +00:00
unsigned int i ;
2004-04-03 12:29:21 +00:00
2004-05-06 04:40:15 +00:00
e2 = ldb_realloc_p ( ldb , msg - > elements , struct ldb_message_element ,
2004-04-03 12:29:21 +00:00
msg - > num_elements + 1 ) ;
if ( ! e2 ) {
errno = ENOMEM ;
return - 1 ;
}
msg - > elements = e2 ;
e2 = & msg - > elements [ msg - > num_elements ] ;
e2 - > name = el - > name ;
e2 - > flags = el - > flags ;
e2 - > values = NULL ;
if ( el - > num_values ! = 0 ) {
2004-05-06 04:40:15 +00:00
e2 - > values = ldb_malloc_array_p ( ldb , struct ldb_val , el - > num_values ) ;
2004-04-03 12:29:21 +00:00
if ( ! e2 - > values ) {
errno = ENOMEM ;
return - 1 ;
}
}
for ( i = 0 ; i < el - > num_values ; i + + ) {
e2 - > values [ i ] = el - > values [ i ] ;
}
e2 - > num_values = el - > num_values ;
msg - > num_elements + + ;
return 0 ;
}
/*
delete all elements having a specified attribute name
*/
2004-05-06 04:40:15 +00:00
static int msg_delete_attribute ( struct ldb_context * ldb ,
struct ldb_message * msg , const char * name )
2004-04-03 12:29:21 +00:00
{
2004-07-07 01:02:54 +00:00
unsigned int i , count = 0 ;
2004-04-03 12:29:21 +00:00
struct ldb_message_element * el2 ;
2004-05-06 04:40:15 +00:00
el2 = ldb_malloc_array_p ( ldb , struct ldb_message_element , msg - > num_elements ) ;
2004-04-03 12:29:21 +00:00
if ( ! el2 ) {
errno = ENOMEM ;
return - 1 ;
}
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
2004-05-01 09:45:56 +00:00
if ( ldb_attr_cmp ( msg - > elements [ i ] . name , name ) ! = 0 ) {
2004-04-03 12:29:21 +00:00
el2 [ count + + ] = msg - > elements [ i ] ;
} else {
2004-05-06 04:40:15 +00:00
ldb_free ( ldb , msg - > elements [ i ] . values ) ;
2004-04-03 12:29:21 +00:00
}
}
msg - > num_elements = count ;
2004-05-06 04:40:15 +00:00
ldb_free ( ldb , msg - > elements ) ;
2004-04-03 12:29:21 +00:00
msg - > elements = el2 ;
return 0 ;
2004-03-31 06:45:39 +00:00
}
2004-04-03 12:29:21 +00:00
/*
delete all elements matching an attribute name / value
return 0 on success , - 1 on failure
*/
2004-11-15 11:40:27 +00:00
static int msg_delete_element ( struct ldb_module * module ,
2004-05-01 09:45:56 +00:00
struct ldb_message * msg ,
2004-04-03 12:29:21 +00:00
const char * name ,
const struct ldb_val * val )
{
2004-11-15 11:40:27 +00:00
struct ldb_context * ldb = module - > ldb ;
2004-07-07 01:02:54 +00:00
unsigned int i ;
int found ;
2004-04-03 12:29:21 +00:00
struct ldb_message_element * el ;
2004-07-07 01:02:54 +00:00
found = find_element ( msg , name ) ;
if ( found = = - 1 ) {
2004-04-03 12:29:21 +00:00
return - 1 ;
}
2004-07-07 01:02:54 +00:00
el = & msg - > elements [ found ] ;
2004-04-03 12:29:21 +00:00
for ( i = 0 ; i < el - > num_values ; i + + ) {
2004-11-16 09:00:52 +00:00
if ( ltdb_val_equal ( module , msg - > elements [ i ] . name , & el - > values [ i ] , val ) ) {
2004-04-03 12:29:21 +00:00
if ( i < el - > num_values - 1 ) {
memmove ( & el - > values [ i ] , & el - > values [ i + 1 ] ,
2004-05-06 04:40:15 +00:00
sizeof ( el - > values [ i ] ) * ( el - > num_values - ( i + 1 ) ) ) ;
2004-04-03 12:29:21 +00:00
}
el - > num_values - - ;
2004-05-07 23:54:41 +00:00
if ( el - > num_values = = 0 ) {
return msg_delete_attribute ( ldb , msg , name ) ;
}
2004-04-03 12:29:21 +00:00
return 0 ;
}
}
2004-05-07 23:54:41 +00:00
2004-04-03 12:29:21 +00:00
return - 1 ;
}
2004-03-31 06:45:39 +00:00
2004-05-01 09:45:56 +00:00
2004-03-31 06:45:39 +00:00
/*
2004-05-01 09:45:56 +00:00
modify a record - internal interface
2004-04-03 12:29:21 +00:00
yuck - this is O ( n ^ 2 ) . Luckily n is usually small so we probably
get away with it , but if we ever have really large attribute lists
then we ' ll need to look at this again
2004-03-31 06:45:39 +00:00
*/
2004-11-15 11:40:27 +00:00
int ltdb_modify_internal ( struct ldb_module * module , const struct ldb_message * msg )
2004-03-31 06:45:39 +00:00
{
2004-11-15 11:40:27 +00:00
struct ldb_context * ldb = module - > ldb ;
struct ltdb_private * ltdb = module - > private_data ;
2004-03-31 06:45:39 +00:00
TDB_DATA tdb_key , tdb_data ;
struct ldb_message msg2 ;
2004-07-07 01:02:54 +00:00
unsigned i , j ;
int ret ;
2004-04-03 12:29:21 +00:00
2004-11-15 11:40:27 +00:00
tdb_key = ltdb_key ( module , msg - > dn ) ;
2004-03-31 06:45:39 +00:00
if ( ! tdb_key . dptr ) {
2004-05-01 09:45:56 +00:00
return - 1 ;
2004-03-31 06:45:39 +00:00
}
tdb_data = tdb_fetch ( ltdb - > tdb , tdb_key ) ;
if ( ! tdb_data . dptr ) {
2004-07-15 07:16:15 +00:00
ldb_free ( ldb , tdb_key . dptr ) ;
2004-05-01 09:45:56 +00:00
return - 1 ;
2004-03-31 06:45:39 +00:00
}
2004-11-16 09:00:52 +00:00
ret = ltdb_unpack_data ( module , & tdb_data , & msg2 ) ;
2004-03-31 06:45:39 +00:00
if ( ret = = - 1 ) {
2004-05-06 04:40:15 +00:00
ldb_free ( ldb , tdb_key . dptr ) ;
2004-03-31 06:45:39 +00:00
free ( tdb_data . dptr ) ;
2004-05-01 09:45:56 +00:00
return - 1 ;
2004-03-31 06:45:39 +00:00
}
2004-05-01 09:45:56 +00:00
if ( ! msg2 . dn ) {
msg2 . dn = msg - > dn ;
}
2004-04-03 12:29:21 +00:00
2004-03-31 06:45:39 +00:00
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
switch ( msg - > elements [ i ] . flags & LDB_FLAG_MOD_MASK ) {
2004-04-03 12:29:21 +00:00
2004-03-31 06:45:39 +00:00
case LDB_FLAG_MOD_ADD :
2004-04-03 12:29:21 +00:00
/* add this element to the message. fail if it
already exists */
2004-03-31 06:45:39 +00:00
ret = find_element ( & msg2 , msg - > elements [ i ] . name ) ;
if ( ret ! = - 1 ) {
2004-05-07 23:54:41 +00:00
ltdb - > last_err_string = " Attribute exists " ;
2004-03-31 06:45:39 +00:00
goto failed ;
}
2004-05-06 04:40:15 +00:00
if ( msg_add_element ( ldb , & msg2 , & msg - > elements [ i ] ) ! = 0 ) {
2004-04-03 12:29:21 +00:00
goto failed ;
}
break ;
case LDB_FLAG_MOD_REPLACE :
/* replace all elements of this attribute name with the elements
2004-05-22 00:52:04 +00:00
listed . The attribute not existing is not an error */
msg_delete_attribute ( ldb , & msg2 , msg - > elements [ i ] . name ) ;
/* add the replacement element, if not empty */
if ( msg - > elements [ i ] . num_values ! = 0 & &
msg_add_element ( ldb , & msg2 , & msg - > elements [ i ] ) ! = 0 ) {
2004-04-03 12:29:21 +00:00
goto failed ;
}
break ;
case LDB_FLAG_MOD_DELETE :
/* we could be being asked to delete all
values or just some values */
if ( msg - > elements [ i ] . num_values = = 0 ) {
2004-05-06 04:40:15 +00:00
if ( msg_delete_attribute ( ldb , & msg2 ,
msg - > elements [ i ] . name ) ! = 0 ) {
2004-05-07 23:54:41 +00:00
ltdb - > last_err_string = " No such attribute " ;
2004-04-03 12:29:21 +00:00
goto failed ;
}
break ;
}
for ( j = 0 ; j < msg - > elements [ i ] . num_values ; j + + ) {
2004-11-15 11:40:27 +00:00
if ( msg_delete_element ( module ,
2004-05-01 09:45:56 +00:00
& msg2 ,
msg - > elements [ i ] . name ,
& msg - > elements [ i ] . values [ j ] ) ! = 0 ) {
2004-05-07 23:54:41 +00:00
ltdb - > last_err_string = " No such attribute " ;
2004-04-03 12:29:21 +00:00
goto failed ;
}
}
break ;
2004-03-31 06:45:39 +00:00
}
}
2004-04-03 12:29:21 +00:00
/* we've made all the mods - save the modified record back into the database */
2004-11-15 11:40:27 +00:00
ret = ltdb_store ( module , & msg2 , TDB_MODIFY ) ;
2004-04-03 12:29:21 +00:00
2004-05-06 04:40:15 +00:00
ldb_free ( ldb , tdb_key . dptr ) ;
2004-04-03 12:29:21 +00:00
free ( tdb_data . dptr ) ;
2004-11-16 09:00:52 +00:00
ltdb_unpack_data_free ( module , & msg2 ) ;
2004-04-03 12:29:21 +00:00
return ret ;
failed :
2004-05-06 04:40:15 +00:00
ldb_free ( ldb , tdb_key . dptr ) ;
2004-03-31 06:45:39 +00:00
free ( tdb_data . dptr ) ;
2004-11-16 09:00:52 +00:00
ltdb_unpack_data_free ( module , & msg2 ) ;
2004-05-01 09:45:56 +00:00
return - 1 ;
}
/*
modify a record
*/
2004-11-15 11:40:27 +00:00
static int ltdb_modify ( struct ldb_module * module , const struct ldb_message * msg )
2004-05-01 09:45:56 +00:00
{
2004-11-15 11:40:27 +00:00
struct ltdb_private * ltdb = module - > private_data ;
2004-05-01 09:45:56 +00:00
int ret ;
2004-05-06 04:40:15 +00:00
ltdb - > last_err_string = NULL ;
2004-11-21 15:51:54 +00:00
if ( ltdb_lock ( module , LDBLOCK ) ! = 0 ) {
2004-05-01 09:45:56 +00:00
return - 1 ;
}
2004-11-15 11:40:27 +00:00
if ( ltdb_cache_load ( module ) ! = 0 ) {
2004-11-21 15:51:54 +00:00
ltdb_unlock ( module , LDBLOCK ) ;
2004-05-01 09:45:56 +00:00
return - 1 ;
}
2004-11-15 11:40:27 +00:00
ret = ltdb_modify_internal ( module , msg ) ;
2004-05-01 09:45:56 +00:00
if ( ret = = 0 ) {
2004-11-15 11:40:27 +00:00
ltdb_modified ( module , msg - > dn ) ;
2004-05-01 09:45:56 +00:00
}
2004-04-03 12:29:21 +00:00
2004-11-21 15:51:54 +00:00
ltdb_unlock ( module , LDBLOCK ) ;
2004-05-01 09:45:56 +00:00
return ret ;
2004-03-31 06:45:39 +00:00
}
2004-10-20 19:28:02 +00:00
/*
rename a record
*/
2004-11-15 11:40:27 +00:00
static int ltdb_rename ( struct ldb_module * module , const char * olddn , const char * newdn )
2004-10-20 19:28:02 +00:00
{
2004-11-15 11:40:27 +00:00
struct ldb_context * ldb = module - > ldb ;
struct ltdb_private * ltdb = module - > private_data ;
2004-10-20 19:28:02 +00:00
int ret ;
struct ldb_message msg ;
const char * error_str ;
ltdb - > last_err_string = NULL ;
2004-11-21 15:51:54 +00:00
if ( ltdb_lock ( module , LDBLOCK ) ! = 0 ) {
2004-10-20 19:28:02 +00:00
return - 1 ;
}
/* in case any attribute of the message was indexed, we need
to fetch the old record */
2004-11-15 11:40:27 +00:00
ret = ltdb_search_dn1 ( module , olddn , & msg ) ;
2004-10-20 19:28:02 +00:00
if ( ret ! = 1 ) {
/* not finding the old record is an error */
goto failed ;
}
msg . dn = ldb_strdup ( ldb , newdn ) ;
if ( ! msg . dn ) {
2004-11-15 11:40:27 +00:00
ltdb_search_dn1_free ( module , & msg ) ;
2004-10-20 19:28:02 +00:00
goto failed ;
}
2004-11-15 11:40:27 +00:00
ret = ltdb_add ( module , & msg ) ;
2004-10-20 19:28:02 +00:00
if ( ret = = - 1 ) {
2004-10-20 20:48:31 +00:00
ldb_free ( ldb , msg . dn ) ;
2004-11-15 11:40:27 +00:00
ltdb_search_dn1_free ( module , & msg ) ;
2004-10-20 19:28:02 +00:00
goto failed ;
}
2004-10-20 20:48:31 +00:00
ldb_free ( ldb , msg . dn ) ;
2004-11-15 11:40:27 +00:00
ltdb_search_dn1_free ( module , & msg ) ;
2004-10-20 19:28:02 +00:00
2004-11-15 11:40:27 +00:00
ret = ltdb_delete ( module , olddn ) ;
2004-10-20 19:28:02 +00:00
error_str = ltdb - > last_err_string ;
if ( ret = = - 1 ) {
2004-11-15 11:40:27 +00:00
ltdb_delete ( module , newdn ) ;
2004-10-20 19:28:02 +00:00
}
ltdb - > last_err_string = error_str ;
2004-11-21 15:51:54 +00:00
ltdb_unlock ( module , LDBLOCK ) ;
2004-10-20 19:28:02 +00:00
return ret ;
failed :
2004-11-21 15:51:54 +00:00
ltdb_unlock ( module , LDBLOCK ) ;
2004-10-20 19:28:02 +00:00
return - 1 ;
}
2004-03-31 06:45:39 +00:00
/*
close database
*/
2004-11-15 11:40:27 +00:00
static int ltdb_close ( struct ldb_module * module )
2004-03-31 06:45:39 +00:00
{
2004-11-15 11:40:27 +00:00
struct ldb_context * ldb = module - > ldb ;
struct ltdb_private * ltdb = module - > private_data ;
2004-03-31 06:45:39 +00:00
int ret ;
2004-05-01 09:45:56 +00:00
2004-05-06 04:40:15 +00:00
ltdb - > last_err_string = NULL ;
2004-11-15 11:40:27 +00:00
ltdb_cache_free ( module ) ;
2004-05-06 04:40:15 +00:00
ldb_set_alloc ( ldb , NULL , NULL ) ;
2004-05-01 09:45:56 +00:00
2004-03-31 06:45:39 +00:00
ret = tdb_close ( ltdb - > tdb ) ;
2004-05-06 04:40:15 +00:00
ldb_free ( ldb , ltdb ) ;
2004-03-31 06:45:39 +00:00
free ( ldb ) ;
return ret ;
}
/*
return extended error information
*/
2004-11-15 11:40:27 +00:00
static const char * ltdb_errstring ( struct ldb_module * module )
2004-03-31 06:45:39 +00:00
{
2004-11-15 11:40:27 +00:00
struct ltdb_private * ltdb = module - > private_data ;
2004-05-06 04:40:15 +00:00
if ( ltdb - > last_err_string ) {
return ltdb - > last_err_string ;
}
2004-03-31 06:45:39 +00:00
return tdb_errorstr ( ltdb - > tdb ) ;
}
2004-11-15 11:40:27 +00:00
static const struct ldb_module_ops ltdb_ops = {
" tdb " ,
2004-03-31 06:45:39 +00:00
ltdb_close ,
ltdb_search ,
ltdb_search_free ,
ltdb_add ,
ltdb_modify ,
ltdb_delete ,
2004-10-20 19:28:02 +00:00
ltdb_rename ,
2004-11-21 15:51:54 +00:00
ltdb_lock ,
ltdb_unlock ,
2004-05-06 04:40:15 +00:00
ltdb_errstring ,
ltdb_cache_free
2004-03-31 06:45:39 +00:00
} ;
/*
connect to the database
*/
struct ldb_context * ltdb_connect ( const char * url ,
unsigned int flags ,
const char * options [ ] )
{
const char * path ;
int tdb_flags , open_flags ;
struct ltdb_private * ltdb ;
TDB_CONTEXT * tdb ;
struct ldb_context * ldb ;
2004-05-06 04:40:15 +00:00
ldb = calloc ( 1 , sizeof ( struct ldb_context ) ) ;
if ( ! ldb ) {
errno = ENOMEM ;
return NULL ;
}
2004-03-31 06:45:39 +00:00
/* parse the url */
2004-05-03 09:34:18 +00:00
if ( strchr ( url , ' : ' ) ) {
if ( strncmp ( url , " tdb:// " , 6 ) ! = 0 ) {
errno = EINVAL ;
return NULL ;
}
path = url + 6 ;
} else {
path = url ;
2004-03-31 06:45:39 +00:00
}
tdb_flags = TDB_DEFAULT ;
if ( flags & LDB_FLG_RDONLY ) {
open_flags = O_RDONLY ;
} else {
open_flags = O_CREAT | O_RDWR ;
}
2004-04-27 07:10:16 +00:00
/* note that we use quite a large default hash size */
tdb = tdb_open ( path , 10000 , tdb_flags , open_flags , 0666 ) ;
2004-03-31 06:45:39 +00:00
if ( ! tdb ) {
2004-05-06 04:40:15 +00:00
free ( ldb ) ;
2004-03-31 06:45:39 +00:00
return NULL ;
}
2004-05-06 04:40:15 +00:00
ltdb = ldb_malloc_p ( ldb , struct ltdb_private ) ;
2004-03-31 06:45:39 +00:00
if ( ! ltdb ) {
tdb_close ( tdb ) ;
2004-05-06 04:40:15 +00:00
free ( ldb ) ;
2004-03-31 06:45:39 +00:00
errno = ENOMEM ;
return NULL ;
}
ltdb - > tdb = tdb ;
2004-05-01 09:45:56 +00:00
ltdb - > sequence_number = 0 ;
memset ( & ltdb - > cache , 0 , sizeof ( ltdb - > cache ) ) ;
2004-03-31 06:45:39 +00:00
2004-11-15 11:40:27 +00:00
ldb - > modules = ldb_malloc_p ( ldb , struct ldb_module ) ;
if ( ! ldb - > modules ) {
tdb_close ( tdb ) ;
free ( ldb ) ;
errno = ENOMEM ;
return NULL ;
}
ldb - > modules - > ldb = ldb ;
ldb - > modules - > prev = ldb - > modules - > next = NULL ;
ldb - > modules - > private_data = ltdb ;
ldb - > modules - > ops = & ltdb_ops ;
2004-03-31 06:45:39 +00:00
return ldb ;
}