mirror of
https://github.com/samba-team/samba.git
synced 2025-01-26 10:04:02 +03:00
r11761: * fix clearing of event logs by truncating the tdb.
This feature got broken in some of the other updates. Now each open handle stores an pointer to an open tdb data structure (not the tdb pointer itself). Clearing can be done with a simple elog_close_tdb( elog, True ) to force a close and then calling elog_open_tdb( logname, True ) to force an tdb truncate. Permissions on existing tdbs are maintained which is important. * We don't currently handle backup. Haven't looked at the format of a backuped up eventlog to know what the deal is.
This commit is contained in:
parent
ba2f94aeae
commit
2df34c9403
@ -57,6 +57,16 @@
|
||||
#define ELOG_SYS "System"
|
||||
#define ELOG_SEC "Security"
|
||||
|
||||
typedef struct elog_tdb {
|
||||
struct elog_tdb *prev, *next;
|
||||
char *name;
|
||||
TDB_CONTEXT *tdb;
|
||||
int ref_count;
|
||||
} ELOG_TDB;
|
||||
|
||||
#define ELOG_TDB_CTX(x) ((x)->tdb)
|
||||
|
||||
|
||||
#define EVENTLOG_DATABASE_VERSION_V1 1
|
||||
|
||||
/***********************************/
|
||||
|
@ -24,14 +24,7 @@
|
||||
|
||||
/* maintain a list of open eventlog tdbs with reference counts */
|
||||
|
||||
struct elog_open_tdb {
|
||||
struct elog_open_tdb *prev, *next;
|
||||
char *name;
|
||||
TDB_CONTEXT *tdb;
|
||||
int ref_count;
|
||||
};
|
||||
|
||||
static struct elog_open_tdb *open_elog_list;
|
||||
static ELOG_TDB *open_elog_list;
|
||||
|
||||
/********************************************************************
|
||||
Init an Eventlog TDB, and return it. If null, something bad
|
||||
@ -317,14 +310,14 @@ BOOL can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed )
|
||||
/*******************************************************************
|
||||
*******************************************************************/
|
||||
|
||||
TDB_CONTEXT *elog_open_tdb( char *logname )
|
||||
ELOG_TDB *elog_open_tdb( char *logname, BOOL force_clear )
|
||||
{
|
||||
TDB_CONTEXT *tdb;
|
||||
TDB_CONTEXT *tdb = NULL;
|
||||
uint32 vers_id;
|
||||
struct elog_open_tdb *ptr;
|
||||
ELOG_TDB *ptr;
|
||||
char *tdbfilename;
|
||||
pstring tdbpath;
|
||||
struct elog_open_tdb *tdb_node;
|
||||
ELOG_TDB *tdb_node = NULL;
|
||||
char *eventlogdir;
|
||||
|
||||
/* first see if we have an open context */
|
||||
@ -332,7 +325,19 @@ TDB_CONTEXT *elog_open_tdb( char *logname )
|
||||
for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
|
||||
if ( strequal( ptr->name, logname ) ) {
|
||||
ptr->ref_count++;
|
||||
return ptr->tdb;
|
||||
|
||||
/* trick to alow clearing of the eventlog tdb.
|
||||
The force_clear flag should imply that someone
|
||||
has done a force close. So make sure the tdb
|
||||
is NULL. If this is a normal open, then just
|
||||
return the existing reference */
|
||||
|
||||
if ( force_clear ) {
|
||||
SMB_ASSERT( ptr->tdb == NULL );
|
||||
break;
|
||||
}
|
||||
else
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,27 +353,41 @@ TDB_CONTEXT *elog_open_tdb( char *logname )
|
||||
pstrcpy( tdbpath, tdbfilename );
|
||||
SAFE_FREE( tdbfilename );
|
||||
|
||||
DEBUG(7,("elog_open_tdb: Opening %s...\n", tdbpath ));
|
||||
DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n",
|
||||
tdbpath, force_clear?"True":"False" ));
|
||||
|
||||
/* the tdb wasn't already open or this is a forced clear open */
|
||||
|
||||
tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, O_RDWR , 0 );
|
||||
if ( tdb ) {
|
||||
vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
|
||||
if ( !force_clear ) {
|
||||
|
||||
if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) {
|
||||
DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
|
||||
vers_id, tdbpath));
|
||||
tdb_close( tdb );
|
||||
tdb = elog_init_tdb( tdbpath );
|
||||
tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, O_RDWR , 0 );
|
||||
if ( tdb ) {
|
||||
vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
|
||||
|
||||
if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) {
|
||||
DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
|
||||
vers_id, tdbpath));
|
||||
tdb_close( tdb );
|
||||
tdb = elog_init_tdb( tdbpath );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if ( !tdb )
|
||||
tdb = elog_init_tdb( tdbpath );
|
||||
}
|
||||
|
||||
/* if we got a valid context, then add it to the list */
|
||||
|
||||
if ( tdb ) {
|
||||
if ( !(tdb_node = TALLOC_ZERO_P( NULL, struct elog_open_tdb )) ) {
|
||||
/* on a forced clear, just reset the tdb context if we already
|
||||
have an open entry in the list */
|
||||
|
||||
if ( ptr ) {
|
||||
ptr->tdb = tdb;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
if ( !(tdb_node = TALLOC_ZERO_P( NULL, ELOG_TDB)) ) {
|
||||
DEBUG(0,("elog_open_tdb: talloc() failure!\n"));
|
||||
tdb_close( tdb );
|
||||
return NULL;
|
||||
@ -381,42 +400,34 @@ TDB_CONTEXT *elog_open_tdb( char *logname )
|
||||
DLIST_ADD( open_elog_list, tdb_node );
|
||||
}
|
||||
|
||||
return tdb;
|
||||
return tdb_node;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Wrapper to handle reference counts to the tdb
|
||||
*******************************************************************/
|
||||
|
||||
int elog_close_tdb( TDB_CONTEXT *tdb )
|
||||
int elog_close_tdb( ELOG_TDB *etdb, BOOL force_close )
|
||||
{
|
||||
struct elog_open_tdb *ptr;
|
||||
TDB_CONTEXT *tdb;
|
||||
|
||||
if ( !tdb )
|
||||
if ( !etdb )
|
||||
return 0;
|
||||
|
||||
/* See if we can just decrement the ref_count.
|
||||
Just compare pointer values (not names ) */
|
||||
etdb->ref_count--;
|
||||
|
||||
for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
|
||||
if ( tdb == ptr->tdb ) {
|
||||
ptr->ref_count--;
|
||||
break;
|
||||
}
|
||||
SMB_ASSERT( etdb->ref_count >= 0 );
|
||||
|
||||
if ( etdb->ref_count == 0 ) {
|
||||
tdb = etdb->tdb;
|
||||
DLIST_REMOVE( open_elog_list, etdb );
|
||||
TALLOC_FREE( etdb );
|
||||
return tdb_close( tdb );
|
||||
}
|
||||
|
||||
/* if we have a NULL pointer; it means we are trying to
|
||||
close a tdb not in the list of open eventlogs */
|
||||
|
||||
SMB_ASSERT( ptr != NULL );
|
||||
if ( !ptr )
|
||||
return tdb_close( tdb );
|
||||
|
||||
SMB_ASSERT( ptr->ref_count >= 0 );
|
||||
|
||||
if ( ptr->ref_count == 0 ) {
|
||||
DLIST_REMOVE( open_elog_list, ptr );
|
||||
TALLOC_FREE( ptr );
|
||||
if ( force_close ) {
|
||||
tdb = etdb->tdb;
|
||||
etdb->tdb = NULL;
|
||||
return tdb_close( tdb );
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
typedef struct {
|
||||
char *logname;
|
||||
TDB_CONTEXT *tdb;
|
||||
ELOG_TDB *etdb;
|
||||
uint32 current_record;
|
||||
uint32 num_records;
|
||||
uint32 oldest_entry;
|
||||
@ -42,8 +42,8 @@ static void free_eventlog_info( void *ptr )
|
||||
{
|
||||
EVENTLOG_INFO *elog = (EVENTLOG_INFO *)ptr;
|
||||
|
||||
if ( elog->tdb )
|
||||
elog_close_tdb( elog->tdb );
|
||||
if ( elog->etdb )
|
||||
elog_close_tdb( elog->etdb, False );
|
||||
|
||||
TALLOC_FREE( elog );
|
||||
}
|
||||
@ -139,17 +139,17 @@ static BOOL get_num_records_hook( EVENTLOG_INFO * info )
|
||||
int next_record;
|
||||
int oldest_record;
|
||||
|
||||
if ( !info->tdb ) {
|
||||
if ( !info->etdb ) {
|
||||
DEBUG( 10, ( "No open tdb for %s\n", info->logname ) );
|
||||
return False;
|
||||
}
|
||||
|
||||
/* lock the tdb since we have to get 2 records */
|
||||
|
||||
tdb_lock_bystring( info->tdb, EVT_NEXT_RECORD, 1 );
|
||||
next_record = tdb_fetch_int32( info->tdb, EVT_NEXT_RECORD);
|
||||
oldest_record = tdb_fetch_int32( info->tdb, EVT_OLDEST_ENTRY);
|
||||
tdb_unlock_bystring( info->tdb, EVT_NEXT_RECORD);
|
||||
tdb_lock_bystring( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD, 1 );
|
||||
next_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
|
||||
oldest_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_OLDEST_ENTRY);
|
||||
tdb_unlock_bystring( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
|
||||
|
||||
DEBUG( 8,
|
||||
( "Oldest Record %d; Next Record %d\n", oldest_record,
|
||||
@ -193,10 +193,10 @@ static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hn
|
||||
in a single process */
|
||||
|
||||
become_root();
|
||||
elog->tdb = elog_open_tdb( elog->logname );
|
||||
elog->etdb = elog_open_tdb( elog->logname, False );
|
||||
unbecome_root();
|
||||
|
||||
if ( !elog->tdb ) {
|
||||
if ( !elog->etdb ) {
|
||||
/* according to MSDN, if the logfile cannot be found, we should
|
||||
default to the "Application" log */
|
||||
|
||||
@ -213,11 +213,11 @@ static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hn
|
||||
}
|
||||
|
||||
become_root();
|
||||
elog->tdb = elog_open_tdb( elog->logname );
|
||||
elog->etdb = elog_open_tdb( elog->logname, False );
|
||||
unbecome_root();
|
||||
}
|
||||
|
||||
if ( !elog->tdb ) {
|
||||
if ( !elog->etdb ) {
|
||||
TALLOC_FREE( elog );
|
||||
return NT_STATUS_ACCESS_DENIED; /* ??? */
|
||||
}
|
||||
@ -226,7 +226,7 @@ static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hn
|
||||
/* now do the access check. Close the tdb if we fail here */
|
||||
|
||||
if ( !elog_check_access( elog, p->pipe_user.nt_user_token ) ) {
|
||||
elog_close_tdb( elog->tdb );
|
||||
elog_close_tdb( elog->etdb, False );
|
||||
TALLOC_FREE( elog );
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
@ -268,12 +268,12 @@ static NTSTATUS elog_close( pipes_struct *p, POLICY_HND *hnd )
|
||||
|
||||
static int elog_size( EVENTLOG_INFO *info )
|
||||
{
|
||||
if ( !info || !info->tdb ) {
|
||||
if ( !info || !info->etdb ) {
|
||||
DEBUG(0,("elog_size: Invalid info* structure!\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return elog_tdb_size( info->tdb, NULL, NULL );
|
||||
return elog_tdb_size( ELOG_TDB_CTX(info->etdb), NULL, NULL );
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
@ -397,7 +397,7 @@ static BOOL sync_eventlog_params( EVENTLOG_INFO *info )
|
||||
|
||||
DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname ) );
|
||||
|
||||
if ( !info->tdb ) {
|
||||
if ( !info->etdb ) {
|
||||
DEBUG( 4, ( "No open tdb! (%s)\n", info->logname ) );
|
||||
return False;
|
||||
}
|
||||
@ -440,8 +440,8 @@ static BOOL sync_eventlog_params( EVENTLOG_INFO *info )
|
||||
|
||||
regkey_close_internal( keyinfo );
|
||||
|
||||
tdb_store_int32( info->tdb, EVT_MAXSIZE, uiMaxSize );
|
||||
tdb_store_int32( info->tdb, EVT_RETENTION, uiRetention );
|
||||
tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_MAXSIZE, uiMaxSize );
|
||||
tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_RETENTION, uiRetention );
|
||||
|
||||
return True;
|
||||
}
|
||||
@ -610,7 +610,7 @@ NTSTATUS _eventlog_open_eventlog( pipes_struct * p,
|
||||
DEBUG(10,("_eventlog_open_eventlog: Size [%d]\n", elog_size( info )));
|
||||
|
||||
sync_eventlog_params( info );
|
||||
prune_eventlog( info->tdb );
|
||||
prune_eventlog( ELOG_TDB_CTX(info->etdb) );
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@ -634,20 +634,26 @@ NTSTATUS _eventlog_clear_eventlog( pipes_struct * p,
|
||||
rpcstr_pull( backup_file_name, q_u->backupfile.string->buffer,
|
||||
sizeof( backup_file_name ),
|
||||
q_u->backupfile.string->uni_str_len * 2, 0 );
|
||||
|
||||
DEBUG(8,( "_eventlog_clear_eventlog: Using [%s] as the backup "
|
||||
"file name for log [%s].",
|
||||
backup_file_name, info->logname ) );
|
||||
}
|
||||
|
||||
DEBUG( 8,
|
||||
( "_eventlog_clear_eventlog: Using [%s] as the backup file name for log [%s].",
|
||||
backup_file_name, info->logname ) );
|
||||
/* check for WRITE access to the file */
|
||||
|
||||
#if 0
|
||||
/* close the current one, reinit */
|
||||
|
||||
tdb_close( info->tdb );
|
||||
|
||||
if ( !(info->tdb = elog_init_tdb( ttdb[i].tdbfname )) )
|
||||
if ( !(info->access_granted&SA_RIGHT_FILE_WRITE_DATA) )
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
|
||||
/* Force a close and reopen */
|
||||
|
||||
elog_close_tdb( info->etdb, True );
|
||||
become_root();
|
||||
info->etdb = elog_open_tdb( info->logname, True );
|
||||
unbecome_root();
|
||||
|
||||
if ( !info->etdb )
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
#endif
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@ -680,7 +686,7 @@ NTSTATUS _eventlog_read_eventlog( pipes_struct * p,
|
||||
|
||||
bytes_left = q_u->max_read_size;
|
||||
|
||||
if ( !info->tdb )
|
||||
if ( !info->etdb )
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
|
||||
/* check for valid flags. Can't use the sequential and seek flags together */
|
||||
@ -706,7 +712,7 @@ NTSTATUS _eventlog_read_eventlog( pipes_struct * p,
|
||||
|
||||
/* assume that when the record fetch fails, that we are done */
|
||||
|
||||
if ( !get_eventlog_record ( ps, info->tdb, record_number, &entry ) )
|
||||
if ( !get_eventlog_record ( ps, ELOG_TDB_CTX(info->etdb), record_number, &entry ) )
|
||||
break;
|
||||
|
||||
DEBUG( 8, ( "Retrieved record %d\n", record_number ) );
|
||||
|
@ -136,7 +136,7 @@ END {
|
||||
gotstart = 1;
|
||||
}
|
||||
|
||||
if( $0 ~ /^NODE_STATUS_STRUCT|SMB_STRUCT_DIR/ ) {
|
||||
if( $0 ~ /^NODE_STATUS_STRUCT|SMB_STRUCT_DIR|ELOG_TDB/ ) {
|
||||
gotstart = 1;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user