Coverage Report

Created: 2026-08-31 07:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwtcdb/libwtcdb/libwtcdb_cache_entry.c
Line
Count
Source
1
/*
2
 * Cache entry functions
3
 *
4
 * Copyright (C) 2010-2026, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <types.h>
25
26
#include "libwtcdb_cache_entry.h"
27
#include "libwtcdb_crc.h"
28
#include "libwtcdb_debug.h"
29
#include "libwtcdb_definitions.h"
30
#include "libwtcdb_io_handle.h"
31
#include "libwtcdb_libbfio.h"
32
#include "libwtcdb_libcerror.h"
33
#include "libwtcdb_libcnotify.h"
34
#include "libwtcdb_libuna.h"
35
36
#include "wtcdb_cache_entry.h"
37
38
/* Creates a cache entry
39
 * Make sure the value cache_entry is referencing, is set to NULL
40
 * Returns 1 if successful or -1 on error
41
 */
42
int libwtcdb_cache_entry_initialize(
43
     libwtcdb_cache_entry_t **cache_entry,
44
     libcerror_error_t **error )
45
3.50k
{
46
3.50k
  static char *function = "libwtcdb_cache_entry_initialize";
47
48
3.50k
  if( cache_entry == NULL )
49
0
  {
50
0
    libcerror_error_set(
51
0
     error,
52
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
53
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
54
0
     "%s: invalid cache entry.",
55
0
     function );
56
57
0
    return( -1 );
58
0
  }
59
3.50k
  if( *cache_entry != NULL )
60
0
  {
61
0
    libcerror_error_set(
62
0
     error,
63
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
64
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
65
0
     "%s: invalid cache entry value already set.",
66
0
     function );
67
68
0
    return( -1 );
69
0
  }
70
3.50k
  *cache_entry = memory_allocate_structure(
71
3.50k
                  libwtcdb_cache_entry_t );
72
73
3.50k
  if( *cache_entry == NULL )
74
0
  {
75
0
    libcerror_error_set(
76
0
     error,
77
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
78
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
79
0
     "%s: unable to create cache entry.",
80
0
     function );
81
82
0
    goto on_error;
83
0
  }
84
3.50k
  if( memory_set(
85
3.50k
       *cache_entry,
86
3.50k
       0,
87
3.50k
       sizeof( libwtcdb_cache_entry_t ) ) == NULL )
88
0
  {
89
0
    libcerror_error_set(
90
0
     error,
91
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
92
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
93
0
     "%s: unable to clear cache entry.",
94
0
     function );
95
96
0
    goto on_error;
97
0
  }
98
3.50k
  return( 1 );
99
100
0
on_error:
101
0
  if( *cache_entry != NULL )
102
0
  {
103
0
    memory_free(
104
0
     *cache_entry );
105
106
0
    *cache_entry = NULL;
107
0
  }
108
0
  return( -1 );
109
3.50k
}
110
111
/* Frees a cache entry
112
 * Returns 1 if successful or -1 on error
113
 */
114
int libwtcdb_cache_entry_free(
115
     libwtcdb_cache_entry_t **cache_entry,
116
     libcerror_error_t **error )
117
3.50k
{
118
3.50k
  static char *function = "libwtcdb_cache_entry_free";
119
120
3.50k
  if( cache_entry == NULL )
121
0
  {
122
0
    libcerror_error_set(
123
0
     error,
124
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
125
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
126
0
     "%s: invalid cache entry.",
127
0
     function );
128
129
0
    return( -1 );
130
0
  }
131
3.50k
  if( *cache_entry != NULL )
132
3.50k
  {
133
3.50k
    if( ( *cache_entry )->identifier != NULL )
134
597
    {
135
597
      memory_free(
136
597
       ( *cache_entry )->identifier );
137
597
    }
138
3.50k
    memory_free(
139
3.50k
     *cache_entry );
140
141
3.50k
    *cache_entry = NULL;
142
3.50k
  }
143
3.50k
  return( 1 );
144
3.50k
}
145
146
/* Reads a cache entry header
147
 * Returns 1 if successful or -1 on error
148
 */
149
int libwtcdb_cache_entry_header_read_data(
150
     libwtcdb_cache_entry_t *cache_entry,
151
     libwtcdb_io_handle_t *io_handle,
152
     const uint8_t *data,
153
     size_t data_size,
154
     libcerror_error_t **error )
155
3.43k
{
156
3.43k
  static char *function          = "libwtcdb_cache_entry_header_read_data";
157
3.43k
  size_t cache_entry_header_size = 0;
158
3.43k
  uint64_t calculated_crc        = 0;
159
3.43k
  uint64_t stored_header_crc     = 0;
160
161
#if defined( HAVE_DEBUG_OUTPUT )
162
  uint64_t value_64bit           = 0;
163
  uint32_t value_32bit           = 0;
164
#endif
165
166
3.43k
  if( cache_entry == NULL )
167
0
  {
168
0
    libcerror_error_set(
169
0
     error,
170
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
171
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
172
0
     "%s: invalid cache entry.",
173
0
     function );
174
175
0
    return( -1 );
176
0
  }
177
3.43k
  if( io_handle == NULL )
178
0
  {
179
0
    libcerror_error_set(
180
0
     error,
181
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
182
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
183
0
     "%s: invalid IO handle.",
184
0
     function );
185
186
0
    return( -1 );
187
0
  }
188
3.43k
  if( io_handle->file_type != LIBWTCDB_FILE_TYPE_CACHE )
189
0
  {
190
0
    libcerror_error_set(
191
0
     error,
192
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
193
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
194
0
     "%s: invalid IO handle - unsupported file type.",
195
0
     function );
196
197
0
    return( -1 );
198
0
  }
199
3.43k
  if( ( io_handle->format_version != 20 )
200
3.05k
   && ( io_handle->format_version != 21 )
201
1.40k
   && ( io_handle->format_version != 30 )
202
903
   && ( io_handle->format_version != 31 )
203
386
   && ( io_handle->format_version != 32 ) )
204
0
  {
205
0
    libcerror_error_set(
206
0
     error,
207
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
208
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
209
0
     "%s: invalid IO handle - unsupported format version: %" PRIu32 ".",
210
0
     function,
211
0
     io_handle->format_version );
212
213
0
    return( -1 );
214
0
  }
215
3.43k
  if( io_handle->format_version == 20 )
216
383
  {
217
383
    cache_entry_header_size = sizeof( wtcdb_cache_entry_v20_t );
218
383
  }
219
3.05k
  else if( io_handle->format_version == 21 )
220
1.64k
  {
221
1.64k
    cache_entry_header_size = sizeof( wtcdb_cache_entry_v21_t );
222
1.64k
  }
223
1.40k
  else if( ( io_handle->format_version == 30 )
224
903
        || ( io_handle->format_version == 31 )
225
386
        || ( io_handle->format_version == 32 ) )
226
1.40k
  {
227
1.40k
    cache_entry_header_size = sizeof( wtcdb_cache_entry_v30_t );
228
1.40k
  }
229
3.43k
  if( data == NULL )
230
0
  {
231
0
    libcerror_error_set(
232
0
     error,
233
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
234
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
235
0
     "%s: invalid data.",
236
0
     function );
237
238
0
    return( -1 );
239
0
  }
240
3.43k
  if( data_size < cache_entry_header_size )
241
0
  {
242
0
    libcerror_error_set(
243
0
     error,
244
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
245
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
246
0
     "%s: invalid data size value too small.",
247
0
     function );
248
249
0
    return( -1 );
250
0
  }
251
3.43k
  if( data_size > (size_t) SSIZE_MAX )
252
0
  {
253
0
    libcerror_error_set(
254
0
     error,
255
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
256
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
257
0
     "%s: invalid data size value exceeds maximum.",
258
0
     function );
259
260
0
    return( -1 );
261
0
  }
262
#if defined( HAVE_DEBUG_OUTPUT )
263
  if( libcnotify_verbose != 0 )
264
  {
265
    libcnotify_printf(
266
     "%s: cache entry header data:\n",
267
     function );
268
    libcnotify_print_data(
269
     data,
270
     data_size,
271
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
272
  }
273
#endif
274
3.43k
  if( memory_compare(
275
3.43k
       ( (wtcdb_cache_entry_v20_t *) data )->signature,
276
3.43k
       wtcdb_cache_file_signature,
277
3.43k
       4 ) != 0 )
278
4
  {
279
4
    libcerror_error_set(
280
4
     error,
281
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
282
4
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
283
4
     "%s: invalid signature.",
284
4
     function );
285
286
4
    return( -1 );
287
4
  }
288
3.42k
  byte_stream_copy_to_uint32_little_endian(
289
3.42k
   ( (wtcdb_cache_entry_v20_t *) data )->size,
290
3.42k
   cache_entry->data_size );
291
292
3.42k
  byte_stream_copy_to_uint64_little_endian(
293
3.42k
   ( (wtcdb_cache_entry_v20_t *) data )->entry_hash,
294
3.42k
   cache_entry->hash );
295
296
3.42k
  if( io_handle->format_version == 20 )
297
383
  {
298
383
    byte_stream_copy_to_uint32_little_endian(
299
383
     ( (wtcdb_cache_entry_v20_t *) data )->identifier_string_size,
300
383
     cache_entry->identifier_size );
301
302
383
    byte_stream_copy_to_uint32_little_endian(
303
383
     ( (wtcdb_cache_entry_v20_t *) data )->padding_size,
304
383
     cache_entry->padding_size );
305
306
383
    byte_stream_copy_to_uint32_little_endian(
307
383
     ( (wtcdb_cache_entry_v20_t *) data )->data_size,
308
383
     cache_entry->cached_data_size );
309
310
383
    byte_stream_copy_to_uint64_little_endian(
311
383
     ( (wtcdb_cache_entry_v20_t *) data )->header_checksum,
312
383
     stored_header_crc );
313
314
383
    byte_stream_copy_to_uint64_little_endian(
315
383
     ( (wtcdb_cache_entry_v20_t *) data )->data_checksum,
316
383
     cache_entry->data_crc );
317
383
  }
318
3.04k
  else if( io_handle->format_version == 21 )
319
1.64k
  {
320
1.64k
    byte_stream_copy_to_uint32_little_endian(
321
1.64k
     ( (wtcdb_cache_entry_v21_t *) data )->identifier_string_size,
322
1.64k
     cache_entry->identifier_size );
323
324
1.64k
    byte_stream_copy_to_uint32_little_endian(
325
1.64k
     ( (wtcdb_cache_entry_v21_t *) data )->padding_size,
326
1.64k
     cache_entry->padding_size );
327
328
1.64k
    byte_stream_copy_to_uint32_little_endian(
329
1.64k
     ( (wtcdb_cache_entry_v21_t *) data )->data_size,
330
1.64k
     cache_entry->cached_data_size );
331
332
1.64k
    byte_stream_copy_to_uint64_little_endian(
333
1.64k
     ( (wtcdb_cache_entry_v21_t *) data )->data_checksum,
334
1.64k
     cache_entry->data_crc );
335
336
1.64k
    byte_stream_copy_to_uint64_little_endian(
337
1.64k
     ( (wtcdb_cache_entry_v21_t *) data )->header_checksum,
338
1.64k
     stored_header_crc );
339
1.64k
  }
340
1.40k
  else if( ( io_handle->format_version == 30 )
341
902
        || ( io_handle->format_version == 31 )
342
386
        || ( io_handle->format_version == 32 ) )
343
1.40k
  {
344
1.40k
    byte_stream_copy_to_uint32_little_endian(
345
1.40k
     ( (wtcdb_cache_entry_v30_t *) data )->identifier_string_size,
346
1.40k
     cache_entry->identifier_size );
347
348
1.40k
    byte_stream_copy_to_uint32_little_endian(
349
1.40k
     ( (wtcdb_cache_entry_v30_t *) data )->padding_size,
350
1.40k
     cache_entry->padding_size );
351
352
1.40k
    byte_stream_copy_to_uint32_little_endian(
353
1.40k
     ( (wtcdb_cache_entry_v30_t *) data )->data_size,
354
1.40k
     cache_entry->cached_data_size );
355
356
1.40k
    byte_stream_copy_to_uint64_little_endian(
357
1.40k
     ( (wtcdb_cache_entry_v30_t *) data )->data_checksum,
358
1.40k
     cache_entry->data_crc );
359
360
1.40k
    byte_stream_copy_to_uint64_little_endian(
361
1.40k
     ( (wtcdb_cache_entry_v30_t *) data )->header_checksum,
362
1.40k
     stored_header_crc );
363
1.40k
  }
364
#if defined( HAVE_DEBUG_OUTPUT )
365
  if( libcnotify_verbose != 0 )
366
  {
367
    libcnotify_printf(
368
     "%s: signature\t\t\t: %c%c%c%c\n",
369
     function,
370
     ( (wtcdb_cache_entry_v20_t *) data )->signature[ 0 ],
371
     ( (wtcdb_cache_entry_v20_t *) data )->signature[ 1 ],
372
     ( (wtcdb_cache_entry_v20_t *) data )->signature[ 2 ],
373
     ( (wtcdb_cache_entry_v20_t *) data )->signature[ 3 ] );
374
375
    libcnotify_printf(
376
     "%s: size\t\t\t\t: %" PRIu32 "\n",
377
     function,
378
     cache_entry->data_size );
379
380
    libcnotify_printf(
381
     "%s: entry hash\t\t\t: 0x%08" PRIx64 "\n",
382
     function,
383
     cache_entry->hash );
384
385
    if( io_handle->format_version == 20 )
386
    {
387
/* TODO make a string of this ?*/
388
      libcnotify_printf(
389
       "%s: file extension\t\t\t: ",
390
       function );
391
392
      if( ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 0 ] == 0 )
393
      {
394
        libcnotify_printf(
395
         "(none)" );
396
      }
397
      else
398
      {
399
        libcnotify_printf(
400
         "%c",
401
         ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 0 ] );
402
      }
403
      if( ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 2 ] != 0 )
404
      {
405
        libcnotify_printf(
406
         "%c",
407
         ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 2 ] );
408
      }
409
      if( ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 4 ] != 0 )
410
      {
411
        libcnotify_printf(
412
         "%c",
413
         ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 4 ] );
414
      }
415
      if( ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 6 ] != 0 )
416
      {
417
        libcnotify_printf(
418
         "%c",
419
         ( (wtcdb_cache_entry_v20_t *) data )->file_extension[ 6 ] );
420
      }
421
      libcnotify_printf(
422
       "\n" );
423
    }
424
    libcnotify_printf(
425
     "%s: identifier string size\t\t: %" PRIu32 "\n",
426
     function,
427
     cache_entry->identifier_size );
428
429
    libcnotify_printf(
430
     "%s: padding size\t\t\t: %" PRIu32 "\n",
431
     function,
432
     cache_entry->padding_size );
433
434
    libcnotify_printf(
435
     "%s: data size\t\t\t: %" PRIu32 "\n",
436
     function,
437
     cache_entry->cached_data_size );
438
439
    if( io_handle->format_version == 20 )
440
    {
441
      byte_stream_copy_to_uint32_little_endian(
442
       ( (wtcdb_cache_entry_v20_t *) data )->unknown1,
443
       value_32bit );
444
    }
445
    else if( ( io_handle->format_version == 21 )
446
          || ( io_handle->format_version == 30 )
447
          || ( io_handle->format_version == 31 )
448
          || ( io_handle->format_version == 32 ) )
449
    {
450
      byte_stream_copy_to_uint32_little_endian(
451
       ( (wtcdb_cache_entry_v21_t *) data )->unknown1,
452
       value_32bit );
453
    }
454
    libcnotify_printf(
455
     "%s: unknown1\t\t\t\t: 0x%08" PRIx32 "\n",
456
     function,
457
     value_32bit );
458
459
    if( ( io_handle->format_version == 30 )
460
     || ( io_handle->format_version == 31 )
461
     || ( io_handle->format_version == 32 ) )
462
    {
463
      byte_stream_copy_to_uint64_little_endian(
464
       ( (wtcdb_cache_entry_v30_t *) data )->unknown2,
465
       value_64bit );
466
      libcnotify_printf(
467
       "%s: unknown2\t\t\t\t: 0x%08" PRIx64 "\n",
468
       function,
469
       value_64bit );
470
    }
471
    libcnotify_printf(
472
     "%s: data checksum\t\t\t: 0x%08" PRIx64 "\n",
473
     function,
474
     cache_entry->data_crc );
475
476
    libcnotify_printf(
477
     "%s: header checksum\t\t\t: 0x%08" PRIx64 "\n",
478
     function,
479
     stored_header_crc );
480
481
    libcnotify_printf(
482
     "\n" );
483
  }
484
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
485
486
#if ( SIZEOF_SIZE_T <= 4 )
487
  if( ( cache_entry->data_size < cache_entry_header_size )
488
   || ( cache_entry->data_size > (uint32_t) SSIZE_MAX ) )
489
#else
490
3.42k
  if( cache_entry->data_size < cache_entry_header_size )
491
12
#endif
492
12
  {
493
12
    libcerror_error_set(
494
12
     error,
495
12
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
496
12
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
497
12
     "%s: invalid cache entry - data value out of bounds.",
498
12
     function );
499
500
12
    return( -1 );
501
12
  }
502
3.41k
  if( libwtcdb_crc64_weak_calculate(
503
3.41k
       &calculated_crc,
504
3.41k
       data,
505
3.41k
       cache_entry_header_size - 8,
506
3.41k
       (uint64_t) -1,
507
3.41k
       error ) != 1 )
508
0
  {
509
0
    libcerror_error_set(
510
0
     error,
511
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
512
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
513
0
     "%s: unable to calculate CRC-64.",
514
0
     function );
515
516
0
    return( -1 );
517
0
  }
518
3.41k
  if( stored_header_crc != calculated_crc )
519
3.41k
  {
520
#if defined( HAVE_DEBUG_OUTPUT )
521
    if( libcnotify_verbose != 0 )
522
    {
523
      libcnotify_printf(
524
       "%s: mismatch in header CRC-64 ( 0x%08" PRIx64 " != 0x%08" PRIx64 " ).\n",
525
       function,
526
       stored_header_crc,
527
       calculated_crc );
528
    }
529
#endif
530
3.41k
  }
531
3.41k
  return( 1 );
532
3.41k
}
533
534
/* Reads a cache entry
535
 * Returns 1 if successful or -1 on error
536
 */
537
int libwtcdb_cache_entry_read_file_io_handle(
538
     libwtcdb_cache_entry_t *cache_entry,
539
     libwtcdb_io_handle_t *io_handle,
540
     libbfio_handle_t *file_io_handle,
541
     off64_t file_offset,
542
     libcerror_error_t **error )
543
3.50k
{
544
3.50k
  uint8_t cache_entry_data[ sizeof( wtcdb_cache_entry_v20_t ) ];
545
546
3.50k
  static char *function            = "libwtcdb_cache_entry_read_file_io_handle";
547
3.50k
  uint32_t cache_entry_header_size = 0;
548
3.50k
  size_t data_offset               = 0;
549
3.50k
  ssize_t read_count               = 0;
550
551
#if defined( HAVE_DEBUG_OUTPUT )
552
  uint8_t *padding_data            = NULL;
553
#endif
554
555
3.50k
  if( cache_entry == NULL )
556
0
  {
557
0
    libcerror_error_set(
558
0
     error,
559
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
560
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
561
0
     "%s: invalid cache entry.",
562
0
     function );
563
564
0
    return( -1 );
565
0
  }
566
3.50k
  if( io_handle == NULL )
567
0
  {
568
0
    libcerror_error_set(
569
0
     error,
570
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
571
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
572
0
     "%s: invalid IO handle.",
573
0
     function );
574
575
0
    return( -1 );
576
0
  }
577
3.50k
  if( io_handle->file_type != LIBWTCDB_FILE_TYPE_CACHE )
578
0
  {
579
0
    libcerror_error_set(
580
0
     error,
581
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
582
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
583
0
     "%s: invalid IO handle - unsupported file type.",
584
0
     function );
585
586
0
    return( -1 );
587
0
  }
588
3.50k
  if( ( io_handle->format_version != 20 )
589
3.10k
   && ( io_handle->format_version != 21 )
590
1.43k
   && ( io_handle->format_version != 30 )
591
924
   && ( io_handle->format_version != 31 )
592
397
   && ( io_handle->format_version != 32 ) )
593
0
  {
594
0
    libcerror_error_set(
595
0
     error,
596
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
597
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
598
0
     "%s: invalid IO handle - unsupported format version: %" PRIu32 ".",
599
0
     function,
600
0
     io_handle->format_version );
601
602
0
    return( -1 );
603
0
  }
604
3.50k
  if( io_handle->format_version == 20 )
605
394
  {
606
394
    cache_entry_header_size = sizeof( wtcdb_cache_entry_v20_t );
607
394
  }
608
3.10k
  else if( io_handle->format_version == 21 )
609
1.67k
  {
610
1.67k
    cache_entry_header_size = sizeof( wtcdb_cache_entry_v21_t );
611
1.67k
  }
612
1.43k
  else if( ( io_handle->format_version == 30 )
613
924
        || ( io_handle->format_version == 31 )
614
397
        || ( io_handle->format_version == 32 ) )
615
1.43k
  {
616
1.43k
    cache_entry_header_size = sizeof( wtcdb_cache_entry_v30_t );
617
1.43k
  }
618
3.50k
  if( cache_entry->identifier != NULL )
619
0
  {
620
0
    memory_free(
621
0
     cache_entry->identifier );
622
623
0
    cache_entry->identifier = NULL;
624
0
  }
625
#if defined( HAVE_DEBUG_OUTPUT )
626
  if( libcnotify_verbose != 0 )
627
  {
628
    libcnotify_printf(
629
     "%s: reading cache entry header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
630
     function,
631
     file_offset,
632
     file_offset );
633
  }
634
#endif
635
3.50k
  read_count = libbfio_handle_read_buffer_at_offset(
636
3.50k
                file_io_handle,
637
3.50k
                cache_entry_data,
638
3.50k
                cache_entry_header_size,
639
3.50k
                file_offset,
640
3.50k
                error );
641
642
3.50k
  if( read_count != (ssize_t) cache_entry_header_size )
643
67
  {
644
67
    libcerror_error_set(
645
67
     error,
646
67
     LIBCERROR_ERROR_DOMAIN_IO,
647
67
     LIBCERROR_IO_ERROR_READ_FAILED,
648
67
     "%s: unable to read cache entry header data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
649
67
     function,
650
67
     file_offset,
651
67
     file_offset );
652
653
67
    goto on_error;
654
67
  }
655
3.43k
  if( libwtcdb_cache_entry_header_read_data(
656
3.43k
       cache_entry,
657
3.43k
       io_handle,
658
3.43k
       cache_entry_data,
659
3.43k
       cache_entry_header_size,
660
3.43k
       error ) != 1 )
661
16
  {
662
16
    libcerror_error_set(
663
16
     error,
664
16
     LIBCERROR_ERROR_DOMAIN_IO,
665
16
     LIBCERROR_IO_ERROR_READ_FAILED,
666
16
     "%s: unable to read cache entry header.",
667
16
     function );
668
669
16
    goto on_error;
670
16
  }
671
3.41k
  data_offset = cache_entry_header_size;
672
673
3.41k
  if( cache_entry->identifier_size > 0 )
674
763
  {
675
763
    if( cache_entry->identifier_size > MEMORY_MAXIMUM_ALLOCATION_SIZE )
676
41
    {
677
41
      libcerror_error_set(
678
41
       error,
679
41
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
680
41
       LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
681
41
       "%s: invalid cache entry - identifier size value exceeds maximum allocation size.",
682
41
       function );
683
684
41
      goto on_error;
685
41
    }
686
722
    if( ( cache_entry->identifier_size > cache_entry->data_size )
687
699
     || ( data_offset > ( cache_entry->data_size - cache_entry->identifier_size ) ) )
688
31
    {
689
31
      libcerror_error_set(
690
31
       error,
691
31
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
692
31
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
693
31
       "%s: invalid identifier size value out of bounds.",
694
31
       function );
695
696
31
      goto on_error;
697
31
    }
698
691
    cache_entry->identifier = (uint8_t *) memory_allocate(
699
691
                                           sizeof( uint8_t ) * cache_entry->identifier_size );
700
701
691
    if( cache_entry->identifier == NULL )
702
0
    {
703
0
      libcerror_error_set(
704
0
       error,
705
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
706
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
707
0
       "%s: unable to create identifier string.",
708
0
       function );
709
710
0
      goto on_error;
711
0
    }
712
691
    read_count = libbfio_handle_read_buffer(
713
691
                  file_io_handle,
714
691
                  cache_entry->identifier,
715
691
                  cache_entry->identifier_size,
716
691
                  error );
717
718
691
    if( read_count != (ssize_t) cache_entry->identifier_size )
719
93
    {
720
93
      libcerror_error_set(
721
93
       error,
722
93
       LIBCERROR_ERROR_DOMAIN_IO,
723
93
       LIBCERROR_IO_ERROR_READ_FAILED,
724
93
       "%s: unable to read cache entry identifier string.",
725
93
       function );
726
727
93
      goto on_error;
728
93
    }
729
#if defined( HAVE_DEBUG_OUTPUT )
730
    if( libcnotify_verbose != 0 )
731
    {
732
      libcnotify_printf(
733
       "%s: identifier string data:\n",
734
       function );
735
      libcnotify_print_data(
736
       cache_entry->identifier,
737
       cache_entry->identifier_size,
738
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
739
    }
740
#endif
741
#if defined( HAVE_DEBUG_OUTPUT )
742
    if( libcnotify_verbose != 0 )
743
    {
744
      if( libwtcdb_debug_print_utf16_string_value(
745
           function,
746
           "identifier string\t\t",
747
           cache_entry->identifier,
748
           cache_entry->identifier_size,
749
           LIBUNA_ENDIAN_LITTLE,
750
           error ) != 1 )
751
      {
752
        libcerror_error_set(
753
         error,
754
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
755
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
756
         "%s: unable to print UTF-16 string value.",
757
         function );
758
759
        goto on_error;
760
      }
761
    }
762
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
763
764
598
    data_offset += cache_entry->identifier_size;
765
598
  }
766
3.25k
  if( cache_entry->padding_size > 0 )
767
471
  {
768
471
    if( cache_entry->padding_size > MEMORY_MAXIMUM_ALLOCATION_SIZE )
769
38
    {
770
38
      libcerror_error_set(
771
38
       error,
772
38
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
773
38
       LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
774
38
       "%s: invalid cache entry - padding size value exceeds maximum allocation size.",
775
38
       function );
776
777
38
      goto on_error;
778
38
    }
779
433
    if( ( cache_entry->padding_size > cache_entry->data_size )
780
422
     || ( data_offset > ( cache_entry->data_size - cache_entry->padding_size ) ) )
781
13
    {
782
13
      libcerror_error_set(
783
13
       error,
784
13
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
785
13
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
786
13
       "%s: invalid padding size value out of bounds.",
787
13
       function );
788
789
13
      goto on_error;
790
13
    }
791
#if defined( HAVE_DEBUG_OUTPUT )
792
    if( libcnotify_verbose != 0 )
793
    {
794
      padding_data = (uint8_t *) memory_allocate(
795
                                  sizeof( uint8_t ) * cache_entry->padding_size );
796
797
      if( padding_data == NULL )
798
      {
799
        libcerror_error_set(
800
         error,
801
         LIBCERROR_ERROR_DOMAIN_MEMORY,
802
         LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
803
         "%s: unable to create padding data.",
804
         function );
805
806
        goto on_error;
807
      }
808
      read_count = libbfio_handle_read_buffer(
809
                    file_io_handle,
810
                    padding_data,
811
                    cache_entry->padding_size,
812
                    error );
813
814
      if( read_count != (ssize_t) cache_entry->padding_size )
815
      {
816
        libcerror_error_set(
817
         error,
818
         LIBCERROR_ERROR_DOMAIN_IO,
819
         LIBCERROR_IO_ERROR_READ_FAILED,
820
         "%s: unable to read cache entry padding data.",
821
         function );
822
823
        goto on_error;
824
      }
825
      libcnotify_printf(
826
       "%s: padding data:\n",
827
       function );
828
      libcnotify_print_data(
829
       padding_data,
830
       cache_entry->padding_size,
831
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
832
    }
833
    data_offset += cache_entry->padding_size;
834
835
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
836
433
  }
837
#if defined( HAVE_DEBUG_OUTPUT )
838
  else if( libcnotify_verbose != 0 )
839
  {
840
    libcnotify_printf(
841
     "\n" );
842
  }
843
#endif
844
3.20k
  return( 1 );
845
846
299
on_error:
847
299
  if( cache_entry->identifier != NULL )
848
94
  {
849
94
    memory_free(
850
94
     cache_entry->identifier );
851
852
    cache_entry->identifier = NULL;
853
94
  }
854
299
  return( -1 );
855
3.25k
}
856