Coverage Report

Created: 2025-06-22 07:35

/src/libpff/libpff/libpff_file_header.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * File header functions
3
 *
4
 * Copyright (C) 2008-2024, 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 <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libpff_checksum.h"
28
#include "libpff_debug.h"
29
#include "libpff_definitions.h"
30
#include "libpff_file_header.h"
31
#include "libpff_io_handle.h"
32
#include "libpff_libcerror.h"
33
#include "libpff_libcnotify.h"
34
35
#include "pff_file_header.h"
36
37
/* Creates file header
38
 * Make sure the value file_header is referencing, is set to NULL
39
 * Returns 1 if successful or -1 on error
40
 */
41
int libpff_file_header_initialize(
42
     libpff_file_header_t **file_header,
43
     libcerror_error_t **error )
44
9.87k
{
45
9.87k
  static char *function = "libpff_file_header_initialize";
46
47
9.87k
  if( file_header == NULL )
48
0
  {
49
0
    libcerror_error_set(
50
0
     error,
51
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
52
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
53
0
     "%s: invalid file header.",
54
0
     function );
55
56
0
    return( -1 );
57
0
  }
58
9.87k
  if( *file_header != NULL )
59
0
  {
60
0
    libcerror_error_set(
61
0
     error,
62
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
63
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
64
0
     "%s: invalid file header value already set.",
65
0
     function );
66
67
0
    return( -1 );
68
0
  }
69
9.87k
  *file_header = memory_allocate_structure(
70
9.87k
                  libpff_file_header_t );
71
72
9.87k
  if( *file_header == NULL )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
77
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
78
0
     "%s: unable to create file header.",
79
0
     function );
80
81
0
    goto on_error;
82
0
  }
83
9.87k
  if( memory_set(
84
9.87k
       *file_header,
85
9.87k
       0,
86
9.87k
       sizeof( libpff_file_header_t ) ) == NULL )
87
0
  {
88
0
    libcerror_error_set(
89
0
     error,
90
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
91
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
92
0
     "%s: unable to clear file header.",
93
0
     function );
94
95
0
    goto on_error;
96
0
  }
97
9.87k
  return( 1 );
98
99
0
on_error:
100
0
  if( *file_header != NULL )
101
0
  {
102
0
    memory_free(
103
0
     *file_header );
104
105
0
    *file_header = NULL;
106
0
  }
107
0
  return( -1 );
108
9.87k
}
109
110
/* Frees file header
111
 * Returns 1 if successful or -1 on error
112
 */
113
int libpff_file_header_free(
114
     libpff_file_header_t **file_header,
115
     libcerror_error_t **error )
116
9.87k
{
117
9.87k
  static char *function = "libpff_file_header_free";
118
119
9.87k
  if( file_header == NULL )
120
0
  {
121
0
    libcerror_error_set(
122
0
     error,
123
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
124
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
125
0
     "%s: invalid file header.",
126
0
     function );
127
128
0
    return( -1 );
129
0
  }
130
9.87k
  if( *file_header != NULL )
131
9.87k
  {
132
9.87k
    memory_free(
133
9.87k
     *file_header );
134
135
9.87k
    *file_header = NULL;
136
9.87k
  }
137
9.87k
  return( 1 );
138
9.87k
}
139
140
/* Reads the file header data
141
 * Returns 1 if successful or -1 on error
142
 */
143
int libpff_file_header_read_data(
144
     libpff_file_header_t *file_header,
145
     const uint8_t *data,
146
     size_t data_size,
147
     libcerror_error_t **error )
148
9.79k
{
149
9.79k
  const uint8_t *file_header_data                  = NULL;
150
9.79k
  static char *function                            = "libpff_file_header_read_data";
151
9.79k
  uint64_t safe_descriptors_index_root_node_offset = 0;
152
9.79k
  uint64_t safe_offsets_index_root_node_offset     = 0;
153
9.79k
  uint32_t calculated_checksum                     = 0;
154
9.79k
  uint32_t stored_checksum                         = 0;
155
9.79k
  uint16_t content_type                            = 0;
156
9.79k
  uint16_t data_version                            = 0;
157
158
#if defined( HAVE_DEBUG_OUTPUT )
159
  const uint8_t *value_data                        = 0;
160
  uint64_t value_64bit                             = 0;
161
  uint32_t value_32bit                             = 0;
162
  uint16_t value_16bit                             = 0;
163
  uint8_t sentinel                                 = 0;
164
  int value_iterator                               = 0;
165
#endif
166
167
9.79k
  if( file_header == NULL )
168
0
  {
169
0
    libcerror_error_set(
170
0
     error,
171
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
172
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
173
0
     "%s: invalid file header.",
174
0
     function );
175
176
0
    return( -1 );
177
0
  }
178
9.79k
  if( data == NULL )
179
0
  {
180
0
    libcerror_error_set(
181
0
     error,
182
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
183
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
184
0
     "%s: invalid data.",
185
0
     function );
186
187
0
    return( -1 );
188
0
  }
189
9.79k
  if( ( data_size < 564 )
190
9.79k
   || ( data_size > (size_t) SSIZE_MAX ) )
191
0
  {
192
0
    libcerror_error_set(
193
0
     error,
194
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
195
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
196
0
     "%s: invalid data size value out of bounds.",
197
0
     function );
198
199
0
    return( -1 );
200
0
  }
201
9.79k
  file_header_data = &( data[ sizeof( pff_file_header_t ) ] );
202
203
#if defined( HAVE_DEBUG_OUTPUT )
204
  if( libcnotify_verbose != 0 )
205
  {
206
    libcnotify_printf(
207
     "%s: file header:\n",
208
     function );
209
    libcnotify_print_data(
210
     data,
211
     sizeof( pff_file_header_t ),
212
     0 );
213
  }
214
#endif
215
9.79k
  if( memory_compare(
216
9.79k
       ( (pff_file_header_t *) data )->signature,
217
9.79k
       pff_file_signature,
218
9.79k
       4 ) != 0 )
219
113
  {
220
113
    libcerror_error_set(
221
113
     error,
222
113
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
223
113
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
224
113
     "%s: invalid file signature.",
225
113
     function );
226
227
113
    return( -1 );
228
113
  }
229
9.68k
  byte_stream_copy_to_uint32_little_endian(
230
9.68k
   ( (pff_file_header_t *) data )->checksum,
231
9.68k
   stored_checksum );
232
233
9.68k
  byte_stream_copy_to_uint16_little_endian(
234
9.68k
   ( (pff_file_header_t *) data )->content_type,
235
9.68k
   content_type );
236
237
9.68k
  if( content_type == PFF_FILE_HEADER_CONTENT_TYPE_PAB )
238
198
  {
239
198
    file_header->file_content_type = LIBPFF_FILE_CONTENT_TYPE_PAB;
240
198
  }
241
9.48k
  else if( content_type == PFF_FILE_HEADER_CONTENT_TYPE_PST )
242
9.30k
  {
243
9.30k
    file_header->file_content_type = LIBPFF_FILE_CONTENT_TYPE_PST;
244
9.30k
  }
245
182
  else if( content_type == PFF_FILE_HEADER_CONTENT_TYPE_OST )
246
54
  {
247
54
    file_header->file_content_type = LIBPFF_FILE_CONTENT_TYPE_OST;
248
54
  }
249
128
  else
250
128
  {
251
128
    libcerror_error_set(
252
128
     error,
253
128
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
254
128
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
255
128
     "%s: unsupported content type: 0x%04" PRIx16 ".",
256
128
     function,
257
128
     content_type );
258
259
128
    return( -1 );
260
128
  }
261
9.55k
  byte_stream_copy_to_uint16_little_endian(
262
9.55k
   ( (pff_file_header_t *) data )->data_version,
263
9.55k
   data_version );
264
265
9.55k
  if( data_version <= 0x000f )
266
4.91k
  {
267
4.91k
    file_header->file_type = LIBPFF_FILE_TYPE_32BIT;
268
4.91k
  }
269
4.63k
  else if( data_version >= 0x0024 )
270
768
  {
271
768
    file_header->file_type = LIBPFF_FILE_TYPE_64BIT_4K_PAGE;
272
768
  }
273
3.86k
  else if( data_version >= 0x0015 )
274
3.47k
  {
275
3.47k
    file_header->file_type = LIBPFF_FILE_TYPE_64BIT;
276
3.47k
  }
277
391
  else
278
391
  {
279
391
    if( ( ( (pff_file_header_data_32bit_t *) file_header_data )->sentinel == 0x80 )
280
391
     && ( ( (pff_file_header_data_64bit_t *) file_header_data )->sentinel != 0x80 ) )
281
339
    {
282
#if defined( HAVE_DEBUG_OUTPUT )
283
      if( libcnotify_verbose != 0 )
284
      {
285
        libcnotify_printf(
286
         "%s: detected 32-bit file type for unsupported data version: 0x%04" PRIx16 ".\n",
287
         function,
288
         data_version );
289
      }
290
#endif
291
339
      file_header->file_type = LIBPFF_FILE_TYPE_32BIT;
292
339
    }
293
52
    else if( ( ( (pff_file_header_data_32bit_t *) file_header_data )->sentinel != 0x80 )
294
52
          && ( ( (pff_file_header_data_64bit_t *) file_header_data )->sentinel == 0x80 ) )
295
16
    {
296
#if defined( HAVE_DEBUG_OUTPUT )
297
      if( libcnotify_verbose != 0 )
298
      {
299
        libcnotify_printf(
300
         "%s: detected 64-bit file type for unsupported data version: 0x%04" PRIx16 ".\n",
301
         function,
302
         data_version );
303
      }
304
#endif
305
16
      file_header->file_type = LIBPFF_FILE_TYPE_64BIT;
306
16
    }
307
#if defined( HAVE_DEBUG_OUTPUT )
308
    else if( libcnotify_verbose != 0 )
309
    {
310
      libcnotify_printf(
311
       "%s: unsupported data version: 0x%04" PRIx16 ".\n",
312
       function,
313
       data_version );
314
    }
315
#endif
316
391
  }
317
9.55k
  if( ( file_header->file_type != LIBPFF_FILE_TYPE_32BIT )
318
9.55k
   && ( file_header->file_type != LIBPFF_FILE_TYPE_64BIT )
319
9.55k
   && ( file_header->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
320
36
  {
321
36
    libcerror_error_set(
322
36
     error,
323
36
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
324
36
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
325
36
     "%s: unable to determine file type.",
326
36
     function );
327
328
36
    return( -1 );
329
36
  }
330
#if defined( HAVE_DEBUG_OUTPUT )
331
  if( libcnotify_verbose != 0 )
332
  {
333
    libcnotify_printf(
334
     "%s: signature\t\t\t\t\t: %c%c%c%c\n",
335
     function,
336
     ( (pff_file_header_t *) data )->signature[ 0 ],
337
     ( (pff_file_header_t *) data )->signature[ 1 ],
338
     ( (pff_file_header_t *) data )->signature[ 2 ],
339
     ( (pff_file_header_t *) data )->signature[ 3 ] );
340
341
    libcnotify_printf(
342
     "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n",
343
     function,
344
     stored_checksum );
345
346
    libcnotify_printf(
347
     "%s: content type\t\t\t\t: %c%c\n",
348
     function,
349
     ( (pff_file_header_t *) data )->content_type[ 0 ],
350
     ( (pff_file_header_t *) data )->content_type[ 1 ] );
351
352
    libcnotify_printf(
353
     "%s: data version\t\t\t\t: %" PRIu16 "\n",
354
     function,
355
     data_version );
356
    byte_stream_copy_to_uint16_little_endian(
357
     ( (pff_file_header_t *) data )->content_version,
358
     value_16bit );
359
360
    libcnotify_printf(
361
     "%s: content version\t\t\t\t: %" PRIu16 "\n",
362
     function,
363
     value_16bit );
364
365
    libcnotify_printf(
366
     "%s: creation platform\t\t\t\t: 0x%02" PRIx8 "\n",
367
     function,
368
     ( (pff_file_header_t *) data )->creation_platform );
369
370
    libcnotify_printf(
371
     "%s: access platform\t\t\t\t: 0x%02" PRIx8 "\n",
372
     function,
373
     ( (pff_file_header_t *) data )->access_platform );
374
375
    byte_stream_copy_to_uint32_little_endian(
376
     ( (pff_file_header_t *) data )->unknown1,
377
     value_32bit );
378
    libcnotify_printf(
379
     "%s: unknown1\t\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n",
380
     function,
381
     value_32bit,
382
     value_32bit );
383
384
    byte_stream_copy_to_uint32_little_endian(
385
     ( (pff_file_header_t *) data )->unknown2,
386
     value_32bit );
387
    libcnotify_printf(
388
     "%s: unknown2\t\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n",
389
     function,
390
     value_32bit,
391
     value_32bit );
392
393
    libcnotify_printf(
394
     "\n" );
395
  }
396
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
397
398
9.51k
  if( libpff_checksum_calculate_weak_crc32(
399
9.51k
       &calculated_checksum,
400
9.51k
       &( data[ 8 ] ),
401
9.51k
       471,
402
9.51k
       0,
403
9.51k
       error ) != 1 )
404
0
  {
405
0
    libcerror_error_set(
406
0
     error,
407
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
408
0
     LIBCERROR_RUNTIME_ERROR_GENERIC,
409
0
     "%s: unable to calculate weak CRC-32.",
410
0
     function );
411
412
0
    return( -1 );
413
0
  }
414
9.51k
  if( stored_checksum != calculated_checksum )
415
149
  {
416
149
    libcerror_error_set(
417
149
     error,
418
149
     LIBCERROR_ERROR_DOMAIN_INPUT,
419
149
     LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
420
149
     "%s: mismatch in file header checksum ( %" PRIu32 " != %" PRIu32 " ).",
421
149
     function,
422
149
     stored_checksum,
423
149
     calculated_checksum );
424
425
149
    return( -1 );
426
149
  }
427
#if defined( HAVE_DEBUG_OUTPUT )
428
  if( libcnotify_verbose != 0 )
429
  {
430
    if( file_header->file_type == LIBPFF_FILE_TYPE_32BIT )
431
    {
432
      data_size = sizeof( pff_file_header_data_32bit_t );
433
    }
434
    else if( ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT )
435
          || ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
436
    {
437
      data_size = sizeof( pff_file_header_data_64bit_t );
438
    }
439
    else
440
    {
441
      data_size = 564;
442
    }
443
    libcnotify_printf(
444
     "%s: file header data:\n",
445
     function );
446
    libcnotify_print_data(
447
     file_header_data,
448
     data_size,
449
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
450
  }
451
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
452
453
9.36k
  if( file_header->file_type == LIBPFF_FILE_TYPE_32BIT )
454
5.16k
  {
455
5.16k
    byte_stream_copy_to_uint32_little_endian(
456
5.16k
     ( (pff_file_header_data_32bit_t *) file_header_data )->file_size,
457
5.16k
     file_header->file_size );
458
459
5.16k
    byte_stream_copy_to_uint32_little_endian(
460
5.16k
     ( (pff_file_header_data_32bit_t *) file_header_data )->descriptors_index_back_pointer,
461
5.16k
     file_header->descriptors_index_root_node_back_pointer );
462
463
5.16k
    byte_stream_copy_to_uint32_little_endian(
464
5.16k
     ( (pff_file_header_data_32bit_t *) file_header_data )->descriptors_index_root_node_offset,
465
5.16k
     safe_descriptors_index_root_node_offset );
466
467
5.16k
    byte_stream_copy_to_uint32_little_endian(
468
5.16k
     ( (pff_file_header_data_32bit_t *) file_header_data )->offsets_index_back_pointer,
469
5.16k
     file_header->offsets_index_root_node_back_pointer );
470
471
5.16k
    byte_stream_copy_to_uint32_little_endian(
472
5.16k
     ( (pff_file_header_data_32bit_t *) file_header_data )->offsets_index_root_node_offset,
473
5.16k
     safe_offsets_index_root_node_offset );
474
475
#if defined( HAVE_DEBUG_OUTPUT )
476
    sentinel = ( (pff_file_header_data_32bit_t *) file_header_data )->sentinel;
477
#endif
478
5.16k
    file_header->encryption_type = ( (pff_file_header_data_32bit_t *) file_header_data )->encryption_type;
479
5.16k
  }
480
4.20k
  else if( ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT )
481
4.20k
        || ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
482
4.20k
  {
483
4.20k
    byte_stream_copy_to_uint64_little_endian(
484
4.20k
     ( (pff_file_header_data_64bit_t *) file_header_data )->file_size,
485
4.20k
     file_header->file_size );
486
487
4.20k
    byte_stream_copy_to_uint64_little_endian(
488
4.20k
     ( (pff_file_header_data_64bit_t *) file_header_data )->descriptors_index_back_pointer,
489
4.20k
     file_header->descriptors_index_root_node_back_pointer );
490
491
4.20k
    byte_stream_copy_to_uint64_little_endian(
492
4.20k
     ( (pff_file_header_data_64bit_t *) file_header_data )->descriptors_index_root_node_offset,
493
4.20k
     safe_descriptors_index_root_node_offset );
494
495
4.20k
    byte_stream_copy_to_uint64_little_endian(
496
4.20k
     ( (pff_file_header_data_64bit_t *) file_header_data )->offsets_index_back_pointer,
497
4.20k
     file_header->offsets_index_root_node_back_pointer );
498
499
4.20k
    byte_stream_copy_to_uint64_little_endian(
500
4.20k
     ( (pff_file_header_data_64bit_t *) file_header_data )->offsets_index_root_node_offset,
501
4.20k
     safe_offsets_index_root_node_offset );
502
503
#if defined( HAVE_DEBUG_OUTPUT )
504
    sentinel = ( (pff_file_header_data_64bit_t *) file_header_data )->sentinel;
505
#endif
506
4.20k
    file_header->encryption_type = ( (pff_file_header_data_64bit_t *) file_header_data )->encryption_type;
507
508
4.20k
    byte_stream_copy_to_uint32_little_endian(
509
4.20k
     ( (pff_file_header_data_64bit_t *) file_header_data )->checksum,
510
4.20k
     stored_checksum );
511
4.20k
  }
512
#if defined( HAVE_DEBUG_OUTPUT )
513
  if( libcnotify_verbose != 0 )
514
  {
515
    if( file_header->file_type == LIBPFF_FILE_TYPE_32BIT )
516
    {
517
      byte_stream_copy_to_uint32_little_endian(
518
       ( (pff_file_header_data_32bit_t *) file_header_data )->next_index_pointer,
519
       value_32bit );
520
      libcnotify_printf(
521
       "%s: next index pointer\t\t\t: %" PRIu32 "\n",
522
       function,
523
       value_32bit );
524
525
      byte_stream_copy_to_uint32_little_endian(
526
       ( (pff_file_header_data_32bit_t *) file_header_data )->next_index_back_pointer,
527
       value_32bit );
528
      libcnotify_printf(
529
       "%s: next index back pointer\t\t\t: %" PRIu32 "\n",
530
       function,
531
       value_32bit );
532
533
      byte_stream_copy_to_uint32_little_endian(
534
       ( (pff_file_header_data_32bit_t *) file_header_data )->seed_value,
535
       value_32bit );
536
      libcnotify_printf(
537
       "%s: seed value\t\t\t\t: 0x%08" PRIx32 "\n",
538
       function,
539
       value_32bit );
540
541
      value_data = ( (pff_file_header_data_32bit_t *) file_header_data )->descriptors_index_high_water_marks;
542
543
      for( value_iterator = 0;
544
           value_iterator < 32;
545
           value_iterator++ )
546
      {
547
        byte_stream_copy_to_uint32_little_endian(
548
         value_data,
549
         value_32bit );
550
        libcnotify_printf(
551
         "%s: high water mark: %02d value\t\t\t: %" PRIu32 "\n",
552
         function,
553
         value_iterator,
554
         value_32bit );
555
556
        value_data += 4;
557
      }
558
      libcnotify_printf(
559
       "\n" );
560
    }
561
    else if( ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT )
562
          || ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
563
    {
564
      libcnotify_printf(
565
       "%s: unknown3:\n",
566
       function );
567
      libcnotify_print_data(
568
       ( (pff_file_header_data_64bit_t *) file_header_data )->unknown3,
569
       8,
570
       0 );
571
572
      byte_stream_copy_to_uint64_little_endian(
573
       ( (pff_file_header_data_64bit_t *) file_header_data )->next_index_back_pointer,
574
       value_64bit );
575
      libcnotify_printf(
576
       "%s: next index back pointer\t\t\t: %" PRIu64 "\n",
577
       function,
578
       value_64bit );
579
580
      byte_stream_copy_to_uint32_little_endian(
581
       ( (pff_file_header_data_64bit_t *) file_header_data )->seed_value,
582
       value_32bit );
583
      libcnotify_printf(
584
       "%s: seed value\t\t\t\t: 0x%08" PRIx32 "\n",
585
       function,
586
       value_32bit );
587
588
      value_data = ( (pff_file_header_data_64bit_t *) file_header_data )->descriptors_index_high_water_marks;
589
590
      for( value_iterator = 0;
591
           value_iterator < 32;
592
           value_iterator++ )
593
      {
594
        byte_stream_copy_to_uint32_little_endian(
595
         value_data,
596
         value_32bit );
597
        libcnotify_printf(
598
         "%s: high water mark: %02d value\t\t\t: %" PRIu32 "\n",
599
         function,
600
         value_iterator,
601
         value_32bit );
602
603
        value_data += 4;
604
      }
605
      libcnotify_printf(
606
       "\n" );
607
      libcnotify_printf(
608
       "%s: unknown4:\n",
609
       function );
610
      libcnotify_print_data(
611
       ( (pff_file_header_data_64bit_t *) file_header_data )->unknown4,
612
       8,
613
       0 );
614
    }
615
    libcnotify_printf(
616
     "%s: file header data root:\n",
617
     function );
618
619
    if( file_header->file_type == LIBPFF_FILE_TYPE_32BIT )
620
    {
621
      libcnotify_printf(
622
       "%s: unknown5:\n",
623
       function );
624
      libcnotify_print_data(
625
       ( (pff_file_header_data_32bit_t *) file_header_data )->unknown5,
626
       4,
627
       0 );
628
    }
629
    else if( ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT )
630
          || ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
631
    {
632
      libcnotify_printf(
633
       "%s: unknown5:\n",
634
       function );
635
      libcnotify_print_data(
636
       ( (pff_file_header_data_64bit_t *) file_header_data )->unknown5,
637
       4,
638
       0 );
639
    }
640
    libcnotify_printf(
641
     "%s: file size\t\t\t\t\t: %" PRIu64 "\n",
642
     function,
643
     file_header->file_size );
644
645
    if( file_header->file_type == LIBPFF_FILE_TYPE_32BIT )
646
    {
647
      byte_stream_copy_to_uint32_little_endian(
648
       ( (pff_file_header_data_32bit_t *) file_header_data )->last_data_allocation_table_offset,
649
       value_32bit );
650
      libcnotify_printf(
651
       "%s: last data allocation table offset\t\t: %" PRIu32 "\n",
652
       function,
653
       value_32bit );
654
655
      byte_stream_copy_to_uint32_little_endian(
656
       ( (pff_file_header_data_32bit_t *) file_header_data )->total_available_data_size,
657
       value_32bit );
658
      libcnotify_printf(
659
       "%s: total available data size\t\t\t: %" PRIu32 "\n",
660
       function,
661
       value_32bit );
662
663
      byte_stream_copy_to_uint32_little_endian(
664
       ( (pff_file_header_data_32bit_t *) file_header_data )->total_available_page_size,
665
       value_32bit );
666
      libcnotify_printf(
667
       "%s: total available page size\t\t\t: %" PRIu32 "\n",
668
       function,
669
       value_32bit );
670
    }
671
    else if( ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT )
672
          || ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
673
    {
674
      byte_stream_copy_to_uint64_little_endian(
675
       ( (pff_file_header_data_64bit_t *) file_header_data )->last_data_allocation_table_offset,
676
       value_64bit );
677
      libcnotify_printf(
678
       "%s: last data allocation table offset\t\t: %" PRIu64 "\n",
679
       function,
680
       value_64bit );
681
682
      byte_stream_copy_to_uint64_little_endian(
683
       ( (pff_file_header_data_64bit_t *) file_header_data )->total_available_data_size,
684
       value_64bit );
685
      libcnotify_printf(
686
       "%s: total available data size\t\t\t: %" PRIu64 "\n",
687
       function,
688
       value_64bit );
689
690
      byte_stream_copy_to_uint64_little_endian(
691
       ( (pff_file_header_data_64bit_t *) file_header_data )->total_available_page_size,
692
       value_64bit );
693
      libcnotify_printf(
694
       "%s: total available page size\t\t\t: %" PRIu64 "\n",
695
       function,
696
       value_64bit );
697
    }
698
    libcnotify_printf(
699
     "%s: descriptors index back pointer\t\t: %" PRIu64 "\n",
700
     function,
701
     file_header->descriptors_index_root_node_back_pointer );
702
703
    libcnotify_printf(
704
     "%s: descriptors index root node offset\t: %" PRIu64 " (0x%08" PRIx64 ")\n",
705
     function,
706
     safe_descriptors_index_root_node_offset );
707
708
    libcnotify_printf(
709
     "%s: offsets index back pointer\t\t: %" PRIu64 "\n",
710
     function,
711
     file_header->offsets_index_root_node_back_pointer );
712
713
    libcnotify_printf(
714
     "%s: offsets index root node offset\t\t: %" PRIu64 " (0x%08" PRIx64 ")\n",
715
     function,
716
     safe_offsets_index_root_node_offset,
717
     safe_offsets_index_root_node_offset );
718
719
    if( file_header->file_type == LIBPFF_FILE_TYPE_32BIT )
720
    {
721
      libcnotify_printf(
722
       "%s: allocation table validation type\t\t: 0x%02" PRIx8 "\n",
723
       function,
724
       ( (pff_file_header_data_32bit_t *) file_header_data )->allocation_table_validation_type );
725
726
      libcnotify_printf(
727
       "%s: unknown6:\n",
728
       function );
729
      libcnotify_print_data(
730
       ( (pff_file_header_data_32bit_t *) file_header_data )->unknown6,
731
       3,
732
       0 );
733
734
      libcnotify_printf(
735
       "%s: initial data free map:\n",
736
       function );
737
      libcnotify_print_data(
738
       ( (pff_file_header_data_32bit_t *) file_header_data )->initial_data_free_map,
739
       128,
740
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
741
742
      libcnotify_printf(
743
       "%s: initial page free map:\n",
744
       function );
745
      libcnotify_print_data(
746
       ( (pff_file_header_data_32bit_t *) file_header_data )->initial_page_free_map,
747
       128,
748
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
749
    }
750
    else if( ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT )
751
          || ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
752
    {
753
      libcnotify_printf(
754
       "%s: allocation table validation type\t\t: 0x%02" PRIx8 "\n",
755
       function,
756
       ( (pff_file_header_data_64bit_t *) file_header_data )->allocation_table_validation_type );
757
758
      libcnotify_printf(
759
       "%s: unknown6:\n",
760
       function );
761
      libcnotify_print_data(
762
       ( (pff_file_header_data_64bit_t *) file_header_data )->unknown6,
763
       3,
764
       0 );
765
766
      libcnotify_printf(
767
       "%s: unknown7:\n",
768
       function );
769
      libcnotify_print_data(
770
       ( (pff_file_header_data_64bit_t *) file_header_data )->unknown7,
771
       3,
772
       0 );
773
774
      libcnotify_printf(
775
       "%s: initial data free map:\n",
776
       function );
777
      libcnotify_print_data(
778
       ( (pff_file_header_data_64bit_t *) file_header_data )->initial_data_free_map,
779
       128,
780
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
781
782
      libcnotify_printf(
783
       "%s: initial page free map:\n",
784
       function );
785
      libcnotify_print_data(
786
       ( (pff_file_header_data_64bit_t *) file_header_data )->initial_page_free_map,
787
       128,
788
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
789
    }
790
    libcnotify_printf(
791
     "%s: sentinel\t\t\t\t\t: 0x%02" PRIx8 "\n",
792
     function,
793
     sentinel );
794
795
    libcnotify_printf(
796
     "%s: encryption type\t\t\t\t: 0x%02" PRIx8 " (%s)\n",
797
     function,
798
     file_header->encryption_type,
799
     libpff_debug_get_encryption_type(
800
      file_header->encryption_type ) );
801
802
    if( file_header->file_type == LIBPFF_FILE_TYPE_32BIT )
803
    {
804
      libcnotify_printf(
805
       "%s: unknown8:\n",
806
       function );
807
      libcnotify_print_data(
808
       ( (pff_file_header_data_32bit_t *) file_header_data )->unknown8,
809
       2,
810
       0 );
811
812
      libcnotify_printf(
813
       "%s: unknown9:\n",
814
       function );
815
      libcnotify_print_data(
816
       ( (pff_file_header_data_32bit_t *) file_header_data )->unknown9,
817
       8,
818
       0 );
819
820
      libcnotify_printf(
821
       "%s: unknown10:\n",
822
       function );
823
      libcnotify_print_data(
824
       ( (pff_file_header_data_32bit_t *) file_header_data )->unknown10,
825
       4,
826
       0 );
827
828
      libcnotify_printf(
829
       "%s: unknown11:\n",
830
       function );
831
      libcnotify_print_data(
832
       ( (pff_file_header_data_32bit_t *) file_header_data )->unknown11,
833
       3,
834
       0 );
835
836
      libcnotify_printf(
837
       "%s: unknown12:\n",
838
       function );
839
      libcnotify_print_data(
840
       &( ( (pff_file_header_data_32bit_t *) file_header_data )->unknown12 ),
841
       1,
842
       0 );
843
844
      libcnotify_printf(
845
       "%s: unknown13:\n",
846
       function );
847
      libcnotify_print_data(
848
       ( (pff_file_header_data_32bit_t *) file_header_data )->unknown13,
849
       32,
850
       0 );
851
    }
852
    else if( ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT )
853
          || ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
854
    {
855
      libcnotify_printf(
856
       "%s: unknown8:\n",
857
       function );
858
      libcnotify_print_data(
859
       ( (pff_file_header_data_64bit_t *) file_header_data )->unknown8,
860
       2,
861
       0 );
862
863
      byte_stream_copy_to_uint64_little_endian(
864
       ( (pff_file_header_data_64bit_t *) file_header_data )->next_index_pointer,
865
       value_32bit );
866
      libcnotify_printf(
867
       "%s: next index pointer\t\t\t: %" PRIu64 "\n",
868
       function,
869
       value_64bit );
870
871
      libcnotify_printf(
872
       "%s: checksum\t\t\t\t\t: 0x%08" PRIx64 "\n",
873
       function,
874
       stored_checksum );
875
876
      libcnotify_printf(
877
       "%s: unknown11:\n",
878
       function );
879
      libcnotify_print_data(
880
       ( (pff_file_header_data_64bit_t *) file_header_data )->unknown11,
881
       3,
882
       0 );
883
884
      libcnotify_printf(
885
       "%s: unknown12:\n",
886
       function );
887
      libcnotify_print_data(
888
       &( ( (pff_file_header_data_32bit_t *) file_header_data )->unknown12 ),
889
       1,
890
       0 );
891
892
      libcnotify_printf(
893
       "%s: unknown13:\n",
894
       function );
895
      libcnotify_print_data(
896
       ( (pff_file_header_data_64bit_t *) file_header_data )->unknown13,
897
       32,
898
       0 );
899
    }
900
  }
901
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
902
903
9.36k
  if( safe_descriptors_index_root_node_offset > (uint64_t) INT64_MAX )
904
172
  {
905
172
    libcerror_error_set(
906
172
     error,
907
172
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
908
172
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
909
172
     "%s: invalid descriptors index root node offset value out of bounds.",
910
172
     function );
911
912
172
    return( -1 );
913
172
  }
914
9.19k
  if( safe_offsets_index_root_node_offset > (uint64_t) INT64_MAX )
915
172
  {
916
172
    libcerror_error_set(
917
172
     error,
918
172
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
919
172
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
920
172
     "%s: invalid offsets index root node offset value out of bounds.",
921
172
     function );
922
923
172
    return( -1 );
924
172
  }
925
926
9.02k
  file_header->descriptors_index_root_node_offset = (off64_t) safe_descriptors_index_root_node_offset;
927
9.02k
  file_header->offsets_index_root_node_offset     = (off64_t) safe_offsets_index_root_node_offset;
928
929
9.02k
  if( ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT )
930
9.02k
   || ( file_header->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
931
3.85k
  {
932
3.85k
    if( libpff_checksum_calculate_weak_crc32(
933
3.85k
         &calculated_checksum,
934
3.85k
         &( data[ 8 ] ),
935
3.85k
         516,
936
3.85k
         0,
937
3.85k
         error ) != 1 )
938
0
    {
939
0
      libcerror_error_set(
940
0
       error,
941
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
942
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
943
0
       "%s: unable to calculate weak CRC-32.",
944
0
       function );
945
946
0
      return( -1 );
947
0
    }
948
3.85k
    if( stored_checksum != calculated_checksum )
949
122
    {
950
122
      libcerror_error_set(
951
122
       error,
952
122
       LIBCERROR_ERROR_DOMAIN_INPUT,
953
122
       LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
954
122
       "%s: mismatch in file header checksum ( %" PRIu32 " != %" PRIu32 " ).",
955
122
       function,
956
122
       stored_checksum,
957
122
       calculated_checksum );
958
959
122
      return( -1 );
960
122
    }
961
3.85k
  }
962
8.90k
  return( 1 );
963
9.02k
}
964
965
/* Reads the file header
966
 * Returns 1 if successful or -1 on error
967
 */
968
int libpff_file_header_read_file_io_handle(
969
     libpff_file_header_t *file_header,
970
     libbfio_handle_t *file_io_handle,
971
     libcerror_error_t **error )
972
9.87k
{
973
9.87k
  uint8_t file_header_data[ 564 ];
974
975
9.87k
  static char *function = "libpff_file_header_read_file_io_handle";
976
9.87k
  size_t read_size      = 564;
977
9.87k
  ssize_t read_count    = 0;
978
979
9.87k
  if( file_header == NULL )
980
0
  {
981
0
    libcerror_error_set(
982
0
     error,
983
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
984
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
985
0
     "%s: invalid file header.",
986
0
     function );
987
988
0
    return( -1 );
989
0
  }
990
#if defined( HAVE_DEBUG_OUTPUT )
991
  if( libcnotify_verbose != 0 )
992
  {
993
    libcnotify_printf(
994
     "%s: reading file header at offset: 0 (0x00000000)\n",
995
     function );
996
  }
997
#endif
998
9.87k
  read_count = libbfio_handle_read_buffer_at_offset(
999
9.87k
                file_io_handle,
1000
9.87k
                file_header_data,
1001
9.87k
                read_size,
1002
9.87k
                0,
1003
9.87k
                error );
1004
1005
9.87k
  if( read_count != (ssize_t) read_size )
1006
78
  {
1007
78
    libcerror_error_set(
1008
78
     error,
1009
78
     LIBCERROR_ERROR_DOMAIN_IO,
1010
78
     LIBCERROR_IO_ERROR_READ_FAILED,
1011
78
     "%s: unable to read file header data at offset: 0 (0x00000000).",
1012
78
     function );
1013
1014
78
    return( -1 );
1015
78
  }
1016
9.79k
  if( libpff_file_header_read_data(
1017
9.79k
       file_header,
1018
9.79k
       file_header_data,
1019
9.79k
       read_size,
1020
9.79k
       error ) != 1 )
1021
892
  {
1022
892
    libcerror_error_set(
1023
892
     error,
1024
892
     LIBCERROR_ERROR_DOMAIN_IO,
1025
892
     LIBCERROR_IO_ERROR_READ_FAILED,
1026
892
     "%s: unable to read file header.",
1027
892
     function );
1028
1029
892
    return( -1 );
1030
892
  }
1031
8.90k
  return( 1 );
1032
9.79k
}
1033