summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2005-11-17 20:08:59 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:05:26 -0500
commit5251618c7fff7635a4b64072f88eaf5e4e25761e (patch)
tree71005176976553554ba598799e8dca8155a09683
parent70cac98b6e1871cf93b379a4834de1778853de86 (diff)
downloadsamba-5251618c7fff7635a4b64072f88eaf5e4e25761e.tar.gz
samba-5251618c7fff7635a4b64072f88eaf5e4e25761e.tar.bz2
samba-5251618c7fff7635a4b64072f88eaf5e4e25761e.zip
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 used to be commit 2df34c9403446d12f1ceeac38cbda5d3ba805b02)
-rw-r--r--source3/include/rpc_eventlog.h10
-rw-r--r--source3/rpc_server/srv_eventlog_lib.c107
-rw-r--r--source3/rpc_server/srv_eventlog_nt.c64
-rw-r--r--source3/script/mkproto.awk2
4 files changed, 105 insertions, 78 deletions
diff --git a/source3/include/rpc_eventlog.h b/source3/include/rpc_eventlog.h
index 67e03edbc6..5bede97d1c 100644
--- a/source3/include/rpc_eventlog.h
+++ b/source3/include/rpc_eventlog.h
@@ -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
/***********************************/
diff --git a/source3/rpc_server/srv_eventlog_lib.c b/source3/rpc_server/srv_eventlog_lib.c
index b21c2a2529..ec5edf2f34 100644
--- a/source3/rpc_server/srv_eventlog_lib.c
+++ b/source3/rpc_server/srv_eventlog_lib.c
@@ -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 ) */
-
- for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
- if ( tdb == ptr->tdb ) {
- ptr->ref_count--;
- break;
- }
- }
+ etdb->ref_count--;
- /* 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 )
+ 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 );
+ }
- 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 );
}
diff --git a/source3/rpc_server/srv_eventlog_nt.c b/source3/rpc_server/srv_eventlog_nt.c
index 0f0b73029a..05feb51f95 100644
--- a/source3/rpc_server/srv_eventlog_nt.c
+++ b/source3/rpc_server/srv_eventlog_nt.c
@@ -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 ( !(info->access_granted&SA_RIGHT_FILE_WRITE_DATA) )
+ return NT_STATUS_ACCESS_DENIED;
-#if 0
- /* close the current one, reinit */
+ /* Force a close and reopen */
- tdb_close( info->tdb );
+ elog_close_tdb( info->etdb, True );
+ become_root();
+ info->etdb = elog_open_tdb( info->logname, True );
+ unbecome_root();
- if ( !(info->tdb = elog_init_tdb( ttdb[i].tdbfname )) )
+ 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 ) );
diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk
index 73a1c2b3f0..a0f3096c84 100644
--- a/source3/script/mkproto.awk
+++ b/source3/script/mkproto.awk
@@ -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;
}