RIP BOOL. Convert BOOL -> bool. I found a few interesting
[tprouty/samba.git] / source / rpc_server / srv_eventlog_lib.c
index 8c7ce4a648554264f82f20df2c061eca71c18b41..3f06f0f39fa99ac38c79724dedbf5c62b04e6856 100644 (file)
@@ -1,13 +1,13 @@
-
 /* 
  *  Unix SMB/CIFS implementation.
  *  Eventlog utility  routines
  *  Copyright (C) Marcin Krzysztof Porwit    2005,
+ *  Copyright (C) Brian Moran                2005.
  *  Copyright (C) Gerald (Jerry) Carter      2005.
  *  
  *  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 2 of the License, or
+ *  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,
  *  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, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "includes.h"
 
+/* maintain a list of open eventlog tdbs with reference counts */
+
+static ELOG_TDB *open_elog_list;
+
+/********************************************************************
+ Init an Eventlog TDB, and return it. If null, something bad 
+ happened.
+********************************************************************/
 
-/****************************************************************
-Init an Eventlog TDB, and return it. If null, something bad happened.
-****************************************************************/
-TDB_CONTEXT *init_eventlog_tdb( char *tdbfilename )
+TDB_CONTEXT *elog_init_tdb( char *tdbfilename )
 {
-       TDB_CONTEXT *the_tdb;
+       TDB_CONTEXT *tdb;
 
-       unlink( tdbfilename );
+       DEBUG(10,("elog_init_tdb: Initializing eventlog tdb (%s)\n",
+               tdbfilename));
 
-       the_tdb =
-               tdb_open_log( tdbfilename, 0, TDB_DEFAULT, O_RDWR | O_CREAT,
-                             0664 );
-       if ( the_tdb == NULL ) {
-               DEBUG( 1, ( "Can't open tdb for [%s]\n", tdbfilename ) );
+       tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT, 
+               O_RDWR|O_CREAT|O_TRUNC, 0660 );
+
+       if ( !tdb ) {
+               DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename ) );
                return NULL;
        }
-       tdb_store_int32( the_tdb, VN_oldest_entry, 1 );
-       tdb_store_int32( the_tdb, VN_next_record, 1 );
 
        /* initialize with defaults, copy real values in here from registry */
 
-       tdb_store_int32( the_tdb, VN_maxsize, 0x80000 );
-       tdb_store_int32( the_tdb, VN_retention, 0x93A80 );
-
-       tdb_store_int32( the_tdb, VN_version, EVENTLOG_DATABASE_VERSION_V1 );
-       return the_tdb;
-}
-
-/* make the tdb file name for an event log, given destination buffer and size */
-char *mk_tdbfilename( char *dest_buffer, char *eventlog_name, int size_dest )
-{
-       pstring ondisk_name;
-
-       if ( !dest_buffer )
-               return NULL;
-
-       pstrcpy( ondisk_name, "EV" );
-       pstrcat( ondisk_name, eventlog_name );
-       pstrcat( ondisk_name, ".tdb" );
+       tdb_store_int32( tdb, EVT_OLDEST_ENTRY, 1 );
+       tdb_store_int32( tdb, EVT_NEXT_RECORD, 1 );
+       tdb_store_int32( tdb, EVT_MAXSIZE, 0x80000 );
+       tdb_store_int32( tdb, EVT_RETENTION, 0x93A80 );
 
-       memset( dest_buffer, 0, size_dest );
+       tdb_store_int32( tdb, EVT_VERSION, EVENTLOG_DATABASE_VERSION_V1 );
 
-       /* BAD things could happen if the dest_buffer is not large enough... */
-       if ( strlen( ondisk_name ) > size_dest ) {
-               DEBUG( 3, ( "Buffer not big enough for filename\n" ) );
-               return NULL;
-       }
+       return tdb;
+}
 
-       strncpy( dest_buffer, ondisk_name, size_dest );
+/********************************************************************
+ make the tdb file name for an event log, given destination buffer 
+ and size. Caller must free memory.
+********************************************************************/
 
-       return dest_buffer;
+char *elog_tdbname( const char *name )
+{
+       fstring path;
+       char *tdb_fullpath;
+       char *eventlogdir = lock_path( "eventlog" );
+       
+       pstr_sprintf( path, "%s/%s.tdb", eventlogdir, name );
+       strlower_m( path );
+       tdb_fullpath = SMB_STRDUP( path );
+       
+       return tdb_fullpath;
 }
 
 
-/* count the number of bytes in the TDB */
-
-/* Arg! Static Globals! */
+/********************************************************************
+ this function is used to count up the number of bytes in a 
+ particular TDB
+********************************************************************/
 
-static int eventlog_tdbcount;
-static int eventlog_tdbsize;
+struct trav_size_struct {
+       int size;
+       int rec_count;
+};
 
-/* this function is used to count up the number of bytes in a particular TDB */
-int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
+static int eventlog_tdb_size_fn( TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
                          void *state )
 {
-       eventlog_tdbsize += data.dsize;
-       eventlog_tdbcount++;
+       struct trav_size_struct  *tsize = (struct trav_size_struct *)state;
+       
+       tsize->size += data.dsize;
+       tsize->rec_count++;
+       
        return 0;
 }
 
-/* returns the size of the eventlog, and if MaxSize is a non-null ptr, puts 
-   the MaxSize there. This is purely a way not to have yet another function that solely
-   reads the maxsize of the eventlog. Yeah, that's it.  */
+/********************************************************************
+ returns the size of the eventlog, and if MaxSize is a non-null 
+ ptr, puts the MaxSize there. This is purely a way not to have yet 
+ another function that solely reads the maxsize of the eventlog. 
+ Yeah, that's it.
+********************************************************************/
 
-int eventlog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention )
+int elog_tdb_size( TDB_CONTEXT * tdb, int *MaxSize, int *Retention )
 {
+       struct trav_size_struct tsize;
+       
        if ( !tdb )
                return 0;
-       eventlog_tdbcount = 0;
-       eventlog_tdbsize = 0;
+               
+       ZERO_STRUCT( tsize );
 
-       tdb_traverse( tdb, eventlog_tdb_size_fn, NULL );
+       tdb_traverse( tdb, eventlog_tdb_size_fn, &tsize );
 
        if ( MaxSize != NULL ) {
-               *MaxSize = tdb_fetch_int32( tdb, VN_maxsize );
+               *MaxSize = tdb_fetch_int32( tdb, EVT_MAXSIZE );
        }
 
        if ( Retention != NULL ) {
-               *Retention = tdb_fetch_int32( tdb, VN_retention );
+               *Retention = tdb_fetch_int32( tdb, EVT_RETENTION );
        }
 
        DEBUG( 1,
-              ( "eventlog size: [%d] for [%d] records\n", eventlog_tdbsize,
-                eventlog_tdbcount ) );
-       return eventlog_tdbsize;
+              ( "eventlog size: [%d] for [%d] records\n", tsize.size,
+                tsize.rec_count ) );
+       return tsize.size;
 }
 
+/********************************************************************
+ Discard early event logs until we have enough for 'needed' bytes...
+ NO checking done beforehand to see that we actually need to do 
+ this, and it's going to pluck records one-by-one. So, it's best 
+ to determine that this needs to be done before doing it.  
+
+ Setting whack_by_date to True indicates that eventlogs falling 
+ outside of the retention range need to go...
+ return True if we made enough room to accommodate needed bytes
+********************************************************************/
 
-/* 
-   Discard early event logs until we have enough for 'needed' bytes...
-   NO checking done beforehand to see that we actually need to do this, and
-   it's going to pluck records one-by-one. So, it's best to determine that this 
-   needs to be done before doing it.  
-
-   Setting whack_by_date to True indicates that eventlogs falling outside of the 
-   retention range need to go...
-
-*/
-
-/* return True if we made enough room to accommodate needed bytes */
-
-BOOL make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed,
-                            BOOL whack_by_date )
+bool make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed,
+                            bool whack_by_date )
 {
        int start_record, i, new_start;
        int end_record;
        int nbytes, reclen, len, Retention, MaxSize;
-
        int tresv1, trecnum, timegen, timewr;
-
        TDB_DATA key, ret;
        TALLOC_CTX *mem_ctx = NULL;
-
        time_t current_time, exp_time;
 
        /* discard some eventlogs */
@@ -158,12 +162,12 @@ BOOL make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed,
        if ( mem_ctx == NULL )
                return False;   /* can't allocate memory indicates bigger problems */
        /* lock */
-       tdb_lock_bystring( the_tdb, VN_next_record, 1 );
+       tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
        /* read */
-       end_record = tdb_fetch_int32( the_tdb, VN_next_record );
-       start_record = tdb_fetch_int32( the_tdb, VN_oldest_entry );
-       Retention = tdb_fetch_int32( the_tdb, VN_retention );
-       MaxSize = tdb_fetch_int32( the_tdb, VN_maxsize );
+       end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
+       start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY );
+       Retention = tdb_fetch_int32( the_tdb, EVT_RETENTION );
+       MaxSize = tdb_fetch_int32( the_tdb, EVT_MAXSIZE );
 
        time( &current_time );
 
@@ -183,19 +187,25 @@ BOOL make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed,
        for ( i = start_record; i < end_record; i++ ) {
                /* read a record, add the amt to nbytes */
                key.dsize = sizeof( int32 );
-               key.dptr = ( char * ) ( int32 * ) & i;
+               key.dptr = ( uint8 * ) ( int32 * ) & i;
                ret = tdb_fetch( the_tdb, key );
                if ( ret.dsize == 0 ) {
                        DEBUG( 8,
                               ( "Can't find a record for the key, record [%d]\n",
                                 i ) );
-                       tdb_unlock_bystring( the_tdb, VN_next_record );
+                       tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
                        return False;
                }
                nbytes += ret.dsize;    /* note this includes overhead */
 
                len = tdb_unpack( ret.dptr, ret.dsize, "ddddd", &reclen,
                                  &tresv1, &trecnum, &timegen, &timewr );
+               if (len == -1) {
+                       DEBUG( 10,("make_way_for_eventlogs: tdb_unpack failed.\n"));
+                       tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
+                       return False;
+               }
+
                DEBUG( 8,
                       ( "read record %d, record size is [%d], total so far [%d]\n",
                         i, reclen, nbytes ) );
@@ -222,22 +232,22 @@ BOOL make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed,
        if ( start_record != new_start ) {
                for ( i = start_record; i < new_start; i++ ) {
                        key.dsize = sizeof( int32 );
-                       key.dptr = ( char * ) ( int32 * ) & i;
+                       key.dptr = ( uint8 * ) ( int32 * ) & i;
                        tdb_delete( the_tdb, key );
                }
 
-               tdb_store_int32( the_tdb, VN_oldest_entry, new_start );
+               tdb_store_int32( the_tdb, EVT_OLDEST_ENTRY, new_start );
        }
-       tdb_unlock_bystring( the_tdb, VN_next_record );
+       tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
        return True;
 }
 
-/*
+/********************************************************************
   some hygiene for an eventlog - see how big it is, and then 
   calculate how many bytes we need to remove                   
-*/
+********************************************************************/
 
-BOOL prune_eventlog( TDB_CONTEXT * tdb )
+bool prune_eventlog( TDB_CONTEXT * tdb )
 {
        int MaxSize, Retention, CalcdSize;
 
@@ -246,7 +256,7 @@ BOOL prune_eventlog( TDB_CONTEXT * tdb )
                return False;
        }
 
-       CalcdSize = eventlog_tdb_size( tdb, &MaxSize, &Retention );
+       CalcdSize = elog_tdb_size( tdb, &MaxSize, &Retention );
        DEBUG( 3,
               ( "Calculated size [%d] MaxSize [%d]\n", CalcdSize,
                 MaxSize ) );
@@ -259,7 +269,10 @@ BOOL prune_eventlog( TDB_CONTEXT * tdb )
        return make_way_for_eventlogs( tdb, 0, True );
 }
 
-BOOL can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed )
+/********************************************************************
+********************************************************************/
+
+bool can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed )
 {
        int calcd_size;
        int MaxSize, Retention;
@@ -274,7 +287,7 @@ BOOL can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed )
        MaxSize = 0;
        Retention = 0;
 
-       calcd_size = eventlog_tdb_size( tdb, &MaxSize, &Retention );
+       calcd_size = elog_tdb_size( tdb, &MaxSize, &Retention );
 
        if ( calcd_size <= MaxSize )
                return True;    /* you betcha */
@@ -299,29 +312,146 @@ BOOL can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed )
        return make_way_for_eventlogs( tdb, calcd_size - MaxSize, False );
 }
 
-TDB_CONTEXT *open_eventlog_tdb( char *tdbfilename )
+/*******************************************************************
+*******************************************************************/
+
+ELOG_TDB *elog_open_tdb( char *logname, bool force_clear )
+{
+       TDB_CONTEXT *tdb = NULL;
+       uint32 vers_id;
+       ELOG_TDB *ptr;
+       char *tdbfilename;
+       pstring tdbpath;
+       ELOG_TDB *tdb_node = NULL;
+       char *eventlogdir;
+
+       /* first see if we have an open context */
+       
+       for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
+               if ( strequal( ptr->name, logname ) ) {
+                       ptr->ref_count++;
+
+                       /* 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;
+               }
+       }
+       
+       /* make sure that the eventlog dir exists */
+       
+       eventlogdir = lock_path( "eventlog" );
+       if ( !directory_exist( eventlogdir, NULL ) )
+               mkdir( eventlogdir, 0755 );     
+       
+       /* get the path on disk */
+       
+       tdbfilename = elog_tdbname( logname );
+       pstrcpy( tdbpath, tdbfilename );
+       SAFE_FREE( tdbfilename );
+
+       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 */
+
+       if ( !force_clear ) {
+
+               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 );
+                       }
+               }
+       }
+       
+       if ( !tdb )
+               tdb = elog_init_tdb( tdbpath );
+       
+       /* if we got a valid context, then add it to the list */
+       
+       if ( 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;
+               }
+               
+               tdb_node->name = talloc_strdup( tdb_node, logname );
+               tdb_node->tdb = tdb;
+               tdb_node->ref_count = 1;
+               
+               DLIST_ADD( open_elog_list, tdb_node );
+       }
+
+       return tdb_node;
+}
+
+/*******************************************************************
+ Wrapper to handle reference counts to the tdb
+*******************************************************************/
+
+int elog_close_tdb( ELOG_TDB *etdb, bool force_close )
 {
-       TDB_CONTEXT *the_tdb;
+       TDB_CONTEXT *tdb;
 
-       the_tdb =
-               tdb_open_log( tdbfilename, 0, TDB_DEFAULT, O_RDWR | O_CREAT,
-                             0664 );
-       if ( the_tdb == NULL ) {
-               return init_eventlog_tdb( tdbfilename );
+       if ( !etdb )
+               return 0;
+               
+       etdb->ref_count--;
+       
+       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 ( EVENTLOG_DATABASE_VERSION_V1 !=
-            tdb_fetch_int32( the_tdb, VN_version ) ) {
-               tdb_close( the_tdb );
-               return init_eventlog_tdb( tdbfilename );
+       
+       if ( force_close ) {
+               tdb = etdb->tdb;
+               etdb->tdb = NULL;
+               return tdb_close( tdb );
        }
-       return the_tdb;
+
+       return 0;
 }
 
-/* write an eventlog entry. Note that we have to lock, read next eventlog, increment, write, write the record, unlock */
 
-/* coming into this, ee has the eventlog record, and the auxilliary date (computer name, etc.) 
-   filled into the other structure. Before packing into a record, this routine will calc the 
-   appropriate padding, etc., and then blast out the record in a form that can be read back in */
+/*******************************************************************
+ write an eventlog entry. Note that we have to lock, read next 
+ eventlog, increment, write, write the record, unlock 
+ coming into this, ee has the eventlog record, and the auxilliary date 
+ (computer name, etc.) filled into the other structure. Before packing 
+ into a record, this routine will calc the appropriate padding, etc., 
+ and then blast out the record in a form that can be read back in
+*******************************************************************/
+#define MARGIN 512
+
 int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee )
 {
        int32 next_record;
@@ -344,8 +474,6 @@ int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee )
        if ( ee->record.time_generated == 0 )
                return 0;
 
-#define MARGIN 512
-
        /* todo - check for sanity in next_record */
 
        fixup_eventlog_entry( ee );
@@ -357,7 +485,7 @@ int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee )
        }
 
        /* alloc mem for the packed version */
-       packed_ee = TALLOC( mem_ctx, ee->record.length + MARGIN );
+       packed_ee = (uint8 *)TALLOC( mem_ctx, ee->record.length + MARGIN );
        if ( !packed_ee ) {
                talloc_destroy( mem_ctx );
                return 0;
@@ -366,12 +494,12 @@ int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee )
        /* need to read the record number and insert it into the entry here */
 
        /* lock */
-       tdb_lock_bystring( the_tdb, VN_next_record, 1 );
+       tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
        /* read */
-       next_record = tdb_fetch_int32( the_tdb, VN_next_record );
+       next_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
 
        n_packed =
-               tdb_pack( packed_ee, ee->record.length + MARGIN,
+               tdb_pack( (uint8 *)packed_ee, ee->record.length + MARGIN,
                          "ddddddwwwwddddddBBdBBBd", ee->record.length,
                          ee->record.reserved1, next_record,
                          ee->record.time_generated, ee->record.time_written,
@@ -400,25 +528,27 @@ int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee )
        /* increment the record count */
 
        kbuf.dsize = sizeof( int32 );
-       kbuf.dptr = ( uint8 * ) & next_record;
+       kbuf.dptr = (uint8 * ) & next_record;
 
        ebuf.dsize = n_packed;
-       ebuf.dptr = packed_ee;
+       ebuf.dptr = (uint8 *)packed_ee;
 
        if ( tdb_store( the_tdb, kbuf, ebuf, 0 ) ) {
                /* DEBUG(1,("write_eventlog_tdb: Can't write record %d to eventlog\n",next_record)); */
-               tdb_unlock_bystring( the_tdb, VN_next_record );
+               tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
                talloc_destroy( mem_ctx );
                return 0;
        }
        next_record++;
-       tdb_store_int32( the_tdb, VN_next_record, next_record );
-       tdb_unlock_bystring( the_tdb, VN_next_record );
+       tdb_store_int32( the_tdb, EVT_NEXT_RECORD, next_record );
+       tdb_unlock_bystring( the_tdb, EVT_NEXT_RECORD );
        talloc_destroy( mem_ctx );
        return ( next_record - 1 );
 }
 
-/* calculate the correct fields etc for an eventlog entry */
+/*******************************************************************
+ calculate the correct fields etc for an eventlog entry
+*******************************************************************/
 
 void fixup_eventlog_entry( Eventlog_entry * ee )
 {
@@ -454,13 +584,14 @@ void fixup_eventlog_entry( Eventlog_entry * ee )
 }
 
 /********************************************************************
-Note that it's a pretty good idea to initialize the Eventlog_entry structure to zero's before
-calling parse_logentry on an batch of lines that may resolve to a record.
-ALSO, it's a good idea to remove any linefeeds (that's EOL to you and me) on the lines going in.
-
+ Note that it's a pretty good idea to initialize the Eventlog_entry 
+ structure to zero's before calling parse_logentry on an batch of 
+ lines that may resolve to a record.  ALSO, it's a good idea to 
+ remove any linefeeds (that's EOL to you and me) on the lines 
+ going in.
 ********************************************************************/
 
-BOOL parse_logentry( char *line, Eventlog_entry * entry, BOOL * eor )
+bool parse_logentry( char *line, Eventlog_entry * entry, bool * eor )
 {
        char *start = NULL, *stop = NULL;
        pstring temp;
@@ -581,16 +712,13 @@ BOOL parse_logentry( char *line, Eventlog_entry * entry, BOOL * eor )
                memset( temp, 0, sizeof( temp ) );
                strncpy( temp, stop, temp_len );
                rpcstr_push( ( void * ) ( entry->data_record.strings +
-                                         entry->data_record.strings_len ),
+                                         ( entry->data_record.strings_len / 2 ) ),
                             temp,
                             sizeof( entry->data_record.strings ) -
-                            entry->data_record.strings_len, STR_TERMINATE );
-               entry->data_record.strings_len += temp_len + 1;
+                            ( entry->data_record.strings_len / 2 ), STR_TERMINATE );
+               entry->data_record.strings_len += ( temp_len * 2 ) + 2;
                entry->record.num_strings++;
        } else if ( 0 == strncmp( start, "DAT", stop - start ) ) {
-               /* Now that we're done processing the STR data, adjust the length to account for
-                  unicode, then proceed with the DAT data. */
-               entry->data_record.strings_len *= 2;
                /* skip past initial ":" */
                stop++;
                /* now skip any other leading whitespace */