2016-07-21 17:53:15 +03:00
/*
Unix SMB / CIFS implementation .
Implementation of reliable cleanup events
Copyright ( C ) Ralph Boehme 2016
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 "cleanupdb.h"
struct cleanup_key {
pid_t pid ;
} ;
struct cleanup_rec {
/* Storing the pid here as well saves a few lines of code */
pid_t pid ;
bool unclean ;
} ;
static struct tdb_wrap * cleanup_db ( void )
{
static struct tdb_wrap * db ;
char * db_path = NULL ;
int tdbflags = TDB_INCOMPATIBLE_HASH | TDB_CLEAR_IF_FIRST |
TDB_MUTEX_LOCKING ;
if ( db ! = NULL ) {
return db ;
}
db_path = lock_path ( " smbd_cleanupd.tdb " ) ;
if ( db_path = = NULL ) {
return NULL ;
}
db = tdb_wrap_open ( NULL , db_path , 0 , tdbflags ,
O_CREAT | O_RDWR , 0644 ) ;
if ( db = = NULL ) {
DBG_ERR ( " Failed to open smbd_cleanupd.tdb \n " ) ;
}
TALLOC_FREE ( db_path ) ;
return db ;
}
bool cleanupdb_store_child ( const pid_t pid , const bool unclean )
{
struct tdb_wrap * db ;
struct cleanup_key key = { . pid = pid } ;
struct cleanup_rec rec = { . pid = pid , . unclean = unclean } ;
TDB_DATA tdbkey = { . dptr = ( uint8_t * ) & key , . dsize = sizeof ( key ) } ;
2017-04-19 15:00:21 +03:00
TDB_DATA tdbdata = { . dptr = ( uint8_t * ) & rec , . dsize = sizeof ( rec ) } ;
2016-07-21 17:53:15 +03:00
int result ;
db = cleanup_db ( ) ;
if ( db = = NULL ) {
return false ;
}
result = tdb_store ( db - > tdb , tdbkey , tdbdata , TDB_REPLACE ) ;
if ( result ! = 0 ) {
DBG_ERR ( " tdb_store failed for pid %d \n " , ( int ) pid ) ;
return false ;
}
return true ;
}
bool cleanupdb_delete_child ( const pid_t pid )
{
struct tdb_wrap * db ;
struct cleanup_key key = { . pid = pid } ;
TDB_DATA tdbkey = { . dptr = ( uint8_t * ) & key , . dsize = sizeof ( key ) } ;
int result ;
db = cleanup_db ( ) ;
if ( db = = NULL ) {
return false ;
}
result = tdb_delete ( db - > tdb , tdbkey ) ;
if ( result ! = 0 ) {
DBG_ERR ( " tdb_delete failed for pid %d \n " , ( int ) pid ) ;
return false ;
}
return true ;
}
static bool cleanup_rec_parse ( TDB_DATA tdbdata ,
struct cleanup_rec * cleanup_rec )
{
if ( tdbdata . dsize ! = sizeof ( struct cleanup_rec ) ) {
DBG_ERR ( " Found invalid value length %d in cleanup.tdb \n " ,
( int ) tdbdata . dsize ) ;
return false ;
}
memcpy ( cleanup_rec , tdbdata . dptr , sizeof ( struct cleanup_rec ) ) ;
return true ;
}
struct cleanup_read_state {
int ( * fn ) ( const pid_t pid , const bool cleanup , void * private_data ) ;
void * private_data ;
} ;
static int cleanup_traverse_fn ( struct tdb_context * tdb ,
TDB_DATA key , TDB_DATA value ,
void * private_data )
{
struct cleanup_read_state * state =
( struct cleanup_read_state * ) private_data ;
struct cleanup_rec rec ;
bool ok ;
int result ;
ok = cleanup_rec_parse ( value , & rec ) ;
if ( ! ok ) {
return - 1 ;
}
result = state - > fn ( rec . pid , rec . unclean , state - > private_data ) ;
if ( result ! = 0 ) {
return - 1 ;
}
return 0 ;
}
int cleanupdb_traverse_read ( int ( * fn ) ( const pid_t pid ,
const bool cleanup ,
void * private_data ) ,
void * private_data )
{
struct tdb_wrap * db ;
struct cleanup_read_state state ;
int result ;
db = cleanup_db ( ) ;
if ( db = = NULL ) {
return - 1 ;
}
state = ( struct cleanup_read_state ) {
. fn = fn ,
. private_data = private_data
} ;
result = tdb_traverse_read ( db - > tdb , cleanup_traverse_fn , & state ) ;
if ( result < 0 ) {
DBG_ERR ( " tdb_traverse_read failed \n " ) ;
return - 1 ;
}
return result ;
}