2006-11-30 03:05:55 +00:00
/*
Unix SMB / CIFS implementation .
trivial database library
Copyright ( C ) Jeremy Allison 2006
* * NOTE ! The following LGPL license applies to the tdb
* * 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
2007-07-10 01:44:42 +00:00
version 3 of the License , or ( at your option ) any later version .
2006-11-30 03:05:55 +00:00
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
2007-07-10 03:42:26 +00:00
License along with this library ; if not , see < http : //www.gnu.org/licenses/>.
2006-11-30 03:05:55 +00:00
*/
# include "tdb_private.h"
/* Check the freelist is good and contains no loops.
Very memory intensive - only do this as a consistency
checker . Heh heh - uses an in memory tdb as the storage
for the " seen " record list . For some reason this strikes
me as extremely clever as I don ' t have to write another tree
data structure implementation : - ) .
*/
static int seen_insert ( struct tdb_context * mem_tdb , tdb_off_t rec_ptr )
{
TDB_DATA key , data ;
memset ( & data , ' \0 ' , sizeof ( data ) ) ;
2007-03-29 09:35:51 +00:00
key . dptr = ( unsigned char * ) & rec_ptr ;
2006-11-30 03:05:55 +00:00
key . dsize = sizeof ( rec_ptr ) ;
return tdb_store ( mem_tdb , key , data , TDB_INSERT ) ;
}
int tdb_validate_freelist ( struct tdb_context * tdb , int * pnum_entries )
{
struct tdb_context * mem_tdb = NULL ;
2009-10-23 13:51:03 +02:00
struct tdb_record rec ;
2006-11-30 03:05:55 +00:00
tdb_off_t rec_ptr , last_ptr ;
int ret = - 1 ;
* pnum_entries = 0 ;
mem_tdb = tdb_open ( " flval " , tdb - > header . hash_size ,
TDB_INTERNAL , O_RDWR , 0600 ) ;
if ( ! mem_tdb ) {
return - 1 ;
}
if ( tdb_lock ( tdb , - 1 , F_WRLCK ) = = - 1 ) {
tdb_close ( mem_tdb ) ;
return 0 ;
}
last_ptr = FREELIST_TOP ;
/* Store the FREELIST_TOP record. */
if ( seen_insert ( mem_tdb , last_ptr ) = = - 1 ) {
2009-10-22 00:09:43 +10:30
tdb - > ecode = TDB_ERR_CORRUPT ;
ret = - 1 ;
2006-11-30 03:05:55 +00:00
goto fail ;
}
/* read in the freelist top */
if ( tdb_ofs_read ( tdb , FREELIST_TOP , & rec_ptr ) = = - 1 ) {
goto fail ;
}
while ( rec_ptr ) {
/* If we can't store this record (we've seen it
before ) then the free list has a loop and must
be corrupt . */
if ( seen_insert ( mem_tdb , rec_ptr ) ) {
2009-10-22 00:09:43 +10:30
tdb - > ecode = TDB_ERR_CORRUPT ;
ret = - 1 ;
2006-11-30 03:05:55 +00:00
goto fail ;
}
2007-04-17 17:07:14 +00:00
if ( tdb_rec_free_read ( tdb , rec_ptr , & rec ) = = - 1 ) {
2006-11-30 03:05:55 +00:00
goto fail ;
}
/* move to the next record */
last_ptr = rec_ptr ;
rec_ptr = rec . next ;
* pnum_entries + = 1 ;
}
ret = 0 ;
fail :
tdb_close ( mem_tdb ) ;
tdb_unlock ( tdb , - 1 , F_WRLCK ) ;
return ret ;
}