r11760: fix sequential reads in the eventlog; event viewer is behaving better now...
authorGerald Carter <jerry@samba.org>
Thu, 17 Nov 2005 17:41:02 +0000 (17:41 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:05:26 +0000 (11:05 -0500)
(This used to be commit ba2f94aeae1f8e69d53fc360785adf222a8c9c6e)

source3/rpc_parse/parse_eventlog.c
source3/rpc_server/srv_eventlog_nt.c

index 0f0b02748b3c26df453f09e621644f640521e046..5e28a4aba5dd4b671b4eea03f394b94c71e5a03f 100644 (file)
@@ -294,7 +294,7 @@ BOOL eventlog_io_r_read_eventlog(const char *desc,
 
        while(entry != NULL && record_written < record_total)
        {
-               DEBUG(10, ("eventlog_io_r_read_eventlog: writing record [%d] out of [%d].\n", record_written, record_total));
+               DEBUG(11, ("eventlog_io_r_read_eventlog: writing record [%d] out of [%d].\n", record_written, record_total));
 
                /* Encode the actual eventlog record record */
 
index 6413221031cf3ee808fa95fa5a3e4fa32577f807..0f0b73029ac25f8e285e63550d0efb7eb59780c7 100644 (file)
@@ -28,6 +28,7 @@
 typedef struct {
        char *logname;
        TDB_CONTEXT *tdb;
+       uint32 current_record;
        uint32 num_records;
        uint32 oldest_entry;
        uint32 flags;
@@ -130,6 +131,45 @@ static BOOL elog_validate_logname( const char *name )
        return False;
 }
 
+/********************************************************************
+********************************************************************/
+
+static BOOL get_num_records_hook( EVENTLOG_INFO * info )
+{
+       int next_record;
+       int oldest_record;
+
+       if ( !info->tdb ) {
+               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);
+
+       DEBUG( 8,
+              ( "Oldest Record %d; Next Record %d\n", oldest_record,
+                next_record ) );
+
+       info->num_records = ( next_record - oldest_record );
+       info->oldest_entry = oldest_record;
+
+       return True;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+static BOOL get_oldest_entry_hook( EVENTLOG_INFO * info )
+{
+       /* it's the same thing */
+       return get_num_records_hook( info );
+}
+
 /********************************************************************
  ********************************************************************/
 
@@ -199,6 +239,15 @@ static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hn
                return NT_STATUS_NO_MEMORY;
        }
 
+       /* set the initial current_record pointer */
+
+       if ( !get_oldest_entry_hook( elog ) ) {
+               DEBUG(3,("elog_open: Successfully opened eventlog but can't "
+                       "get any information on internal records!\n"));
+       }       
+
+       elog->current_record = elog->oldest_entry;
+
        return NT_STATUS_OK;
 }
 
@@ -397,45 +446,6 @@ static BOOL sync_eventlog_params( EVENTLOG_INFO *info )
        return True;
 }
 
-/********************************************************************
-********************************************************************/
-
-static BOOL get_num_records_hook( EVENTLOG_INFO * info )
-{
-       int next_record;
-       int oldest_record;
-
-       if ( !info->tdb ) {
-               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);
-
-       DEBUG( 8,
-              ( "Oldest Record %d; Next Record %d\n", oldest_record,
-                next_record ) );
-
-       info->num_records = ( next_record - oldest_record );
-       info->oldest_entry = oldest_record;
-
-       return True;
-}
-
-/********************************************************************
- ********************************************************************/
-
-static BOOL get_oldest_entry_hook( EVENTLOG_INFO * info )
-{
-       /* it's the same thing */
-       return get_num_records_hook( info );
-}
-
 /********************************************************************
  ********************************************************************/
 
@@ -661,71 +671,85 @@ NTSTATUS _eventlog_read_eventlog( pipes_struct * p,
 {
        EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle );
        Eventlog_entry entry, *ee_new;
-
        uint32 num_records_read = 0;
        prs_struct *ps;
        int bytes_left, record_number;
-       TDB_CONTEXT *tdb;
-
        info->flags = q_u->flags;
        ps = &p->out_data.rdata;
+       uint32 elog_read_type, elog_read_dir;
 
        bytes_left = q_u->max_read_size;
-       tdb = info->tdb;
-       if ( !tdb ) {
+
+       if ( !info->tdb ) 
                return NT_STATUS_ACCESS_DENIED;
+               
+       /* check for valid flags.  Can't use the sequential and seek flags together */
+
+       elog_read_type = q_u->flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ);
+       elog_read_dir = q_u->flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ);
+
+       if ( elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ) 
+               ||  elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ) )
+       {
+               DEBUG(3,("_eventlog_read_eventlog: Invalid flags [0x%x] for ReadEventLog\n", q_u->flags));
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       /* DEBUG(8,("Bytes left is %d\n",bytes_left)); */
+       /* a sequential read should ignore the offset */
 
-       record_number = q_u->offset;
+       if ( elog_read_type & EVENTLOG_SEQUENTIAL_READ )
+               record_number = info->current_record;
+       else 
+               record_number = q_u->offset;
 
        while ( bytes_left > 0 ) {
-               if ( get_eventlog_record
-                    ( ps, tdb, record_number, &entry ) ) {
-                       DEBUG( 8,
-                              ( "Retrieved record %d\n", record_number ) );
+
+               /* assume that when the record fetch fails, that we are done */
+
+               if ( !get_eventlog_record ( ps, info->tdb, record_number, &entry ) ) 
+                       break;
+
+               DEBUG( 8, ( "Retrieved record %d\n", record_number ) );
                               
-                       /* Now see if there is enough room to add */
-                       ee_new = read_package_entry( ps, q_u, r_u,&entry );
-                       if ( !ee_new )
-                               return NT_STATUS_NO_MEMORY;
-
-                       if ( r_u->num_bytes_in_resp + ee_new->record.length >
-                            q_u->max_read_size ) {
-                               r_u->bytes_in_next_record =
-                                       ee_new->record.length;
-                                       
-                               /* response would be too big to fit in client-size buffer */
+               /* Now see if there is enough room to add */
+
+               if ( !(ee_new = read_package_entry( ps, q_u, r_u,&entry )) )
+                       return NT_STATUS_NO_MEMORY;
+
+               if ( r_u->num_bytes_in_resp + ee_new->record.length > q_u->max_read_size ) {
+                       r_u->bytes_in_next_record = ee_new->record.length;
+
+                       /* response would be too big to fit in client-size buffer */
                                
-                               bytes_left = 0;
-                               break;
-                       }
+                       bytes_left = 0;
+                       break;
+               }
                        
-                       add_record_to_resp( r_u, ee_new );
-                       bytes_left -= ee_new->record.length;
-                       ZERO_STRUCT( entry );
-                       num_records_read =
-                               r_u->num_records - num_records_read;
+               add_record_to_resp( r_u, ee_new );
+               bytes_left -= ee_new->record.length;
+               ZERO_STRUCT( entry );
+               num_records_read = r_u->num_records - num_records_read;
                                
-                       DEBUG( 10,
-                              ( "_eventlog_read_eventlog: read [%d] records for a total of [%d] records using [%d] bytes out of a max of [%d].\n",
-                                num_records_read, r_u->num_records,
-                                r_u->num_bytes_in_resp,
-                                q_u->max_read_size ) );
-               } else {
-                       DEBUG( 8, ( "get_eventlog_record returned NULL\n" ) );
-                       return NT_STATUS_NO_MEMORY;     /* wrong error - but return one anyway */
-               }
-
+               DEBUG( 10, ( "_eventlog_read_eventlog: read [%d] records for a total "
+                       "of [%d] records using [%d] bytes out of a max of [%d].\n",
+                        num_records_read, r_u->num_records,
+                        r_u->num_bytes_in_resp,
+                        q_u->max_read_size ) );
 
                if ( info->flags & EVENTLOG_FORWARDS_READ )
                        record_number++;
                else
                        record_number--;
+               
+               /* update the eventlog record pointer */
+               
+               info->current_record = record_number;
        }
-       
-       return NT_STATUS_OK;
+
+       /* crazy by WinXP uses NT_STATUS_BUFFER_TOO_SMALL to 
+          say when there are no more records */
+
+       return (num_records_read ? NT_STATUS_OK : NT_STATUS_BUFFER_TOO_SMALL);
 }
 
 /********************************************************************