Coverage Report

Created: 2026-01-20 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libpff/libpff/libpff_index_node.c
Line
Count
Source
1
/*
2
 * Index node functions
3
 *
4
 * Copyright (C) 2008-2025, 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_definitions.h"
29
#include "libpff_index_node.h"
30
#include "libpff_libbfio.h"
31
#include "libpff_libcerror.h"
32
#include "libpff_libcnotify.h"
33
#include "libpff_types.h"
34
35
#include "pff_index_node.h"
36
37
/* Creates an index node
38
 * Make sure the value index_node is referencing, is set to NULL
39
 * Returns 1 if successful or -1 on error
40
 */
41
int libpff_index_node_initialize(
42
     libpff_index_node_t **index_node,
43
     libcerror_error_t **error )
44
1.74M
{
45
1.74M
  static char *function = "libpff_index_node_initialize";
46
47
1.74M
  if( index_node == 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 index node.",
54
0
     function );
55
56
0
    return( -1 );
57
0
  }
58
1.74M
  if( *index_node != 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 index node value already set.",
65
0
     function );
66
67
0
    return( -1 );
68
0
  }
69
1.74M
  *index_node = memory_allocate_structure(
70
1.74M
                 libpff_index_node_t );
71
72
1.74M
  if( *index_node == 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 index node.",
79
0
     function );
80
81
0
    goto on_error;
82
0
  }
83
1.74M
  if( memory_set(
84
1.74M
       *index_node,
85
1.74M
       0,
86
1.74M
       sizeof( libpff_index_node_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 index node.",
93
0
     function );
94
95
0
    goto on_error;
96
0
  }
97
1.74M
  return( 1 );
98
99
0
on_error:
100
0
  if( *index_node != NULL )
101
0
  {
102
0
    memory_free(
103
0
     *index_node );
104
105
0
    *index_node = NULL;
106
0
  }
107
0
  return( -1 );
108
1.74M
}
109
110
/* Frees an index node
111
 * Returns 1 if successful or -1 on error
112
 */
113
int libpff_index_node_free(
114
     libpff_index_node_t **index_node,
115
     libcerror_error_t **error )
116
1.74M
{
117
1.74M
  static char *function = "libpff_index_node_free";
118
119
1.74M
  if( index_node == 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 index node.",
126
0
     function );
127
128
0
    return( -1 );
129
0
  }
130
1.74M
  if( *index_node != NULL )
131
1.74M
  {
132
1.74M
    if( ( *index_node )->data != NULL )
133
1.74M
    {
134
1.74M
      memory_free(
135
1.74M
       ( *index_node )->data );
136
1.74M
    }
137
1.74M
    memory_free(
138
1.74M
     *index_node );
139
140
1.74M
    *index_node = NULL;
141
1.74M
  }
142
1.74M
  return( 1 );
143
1.74M
}
144
145
/* Retrieves the data of a specific entry
146
 * Returns 1 if successful or -1 on error
147
 */
148
int libpff_index_node_get_entry_data(
149
     libpff_index_node_t *index_node,
150
     uint16_t entry_index,
151
     uint8_t **entry_data,
152
     libcerror_error_t **error )
153
9.99M
{
154
9.99M
  static char *function = "libpff_index_node_get_entry_data";
155
9.99M
  size_t entry_offset   = 0;
156
157
9.99M
  if( index_node == NULL )
158
0
  {
159
0
    libcerror_error_set(
160
0
     error,
161
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
162
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
163
0
     "%s: invalid index node.",
164
0
     function );
165
166
0
    return( -1 );
167
0
  }
168
9.99M
  if( index_node->entries_data == NULL )
169
0
  {
170
0
    libcerror_error_set(
171
0
     error,
172
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
173
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
174
0
     "%s: invalid index node - missing entries data.",
175
0
     function );
176
177
0
    return( -1 );
178
0
  }
179
9.99M
  if( entry_data == NULL )
180
0
  {
181
0
    libcerror_error_set(
182
0
     error,
183
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
184
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
185
0
     "%s: invalid entry data.",
186
0
     function );
187
188
0
    return( -1 );
189
0
  }
190
9.99M
  if( entry_index > index_node->maximum_number_of_entries )
191
0
  {
192
0
    libcerror_error_set(
193
0
     error,
194
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
195
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
196
0
     "%s: invalid entry index value out of bounds.",
197
0
     function );
198
199
0
    return( -1 );
200
0
  }
201
9.99M
  entry_offset = (size_t) index_node->entry_size * entry_index;
202
203
9.99M
  if( entry_offset > (size_t) index_node->maximum_entries_data_size )
204
0
  {
205
0
    libcerror_error_set(
206
0
     error,
207
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
208
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
209
0
     "%s: entry index value exceeds maximum.",
210
0
     function );
211
212
0
    return( -1 );
213
0
  }
214
9.99M
  *entry_data = &( index_node->entries_data[ entry_offset ] );
215
216
9.99M
  return( 1 );
217
9.99M
}
218
219
/* Reads an index node
220
 * Returns 1 if successful or -1 on error
221
 */
222
int libpff_index_node_read_data(
223
     libpff_index_node_t *index_node,
224
     const uint8_t *data,
225
     size_t data_size,
226
     uint8_t file_type,
227
     libcerror_error_t **error )
228
1.74M
{
229
1.74M
  static char *function                        = "libpff_index_node_read_data";
230
1.74M
  size_t checksum_data_size                    = 0;
231
1.74M
  size_t index_node_data_size                  = 0;
232
1.74M
  size_t index_node_footer_data_size           = 0;
233
1.74M
  size_t maximum_entries_data_size             = 0;
234
1.74M
  uint32_t calculated_checksum                 = 0;
235
1.74M
  uint8_t calculated_entry_size                = 0;
236
1.74M
  uint8_t calculated_maximum_number_of_entries = 0;
237
238
#if defined( HAVE_DEBUG_OUTPUT )
239
  uint8_t *index_node_entry_data               = NULL;
240
  uint64_t value_64bit                         = 0;
241
  uint32_t value_32bit                         = 0;
242
  uint16_t entry_index                         = 0;
243
  uint16_t index_node_entry_data_size          = 0;
244
  uint16_t value_16bit                         = 0;
245
  int result                                   = 0;
246
#endif
247
248
1.74M
  if( index_node == NULL )
249
0
  {
250
0
    libcerror_error_set(
251
0
     error,
252
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
253
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
254
0
     "%s: invalid index node.",
255
0
     function );
256
257
0
    return( -1 );
258
0
  }
259
1.74M
  if( data == NULL )
260
0
  {
261
0
    libcerror_error_set(
262
0
     error,
263
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
264
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
265
0
     "%s: invalid data.",
266
0
     function );
267
268
0
    return( -1 );
269
0
  }
270
1.74M
  if( data_size > (size_t) SSIZE_MAX )
271
0
  {
272
0
    libcerror_error_set(
273
0
     error,
274
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
275
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
276
0
     "%s: invalid data size value exceeds maximum.",
277
0
     function );
278
279
0
    return( -1 );
280
0
  }
281
1.74M
  if( ( file_type != LIBPFF_FILE_TYPE_32BIT )
282
315k
   && ( file_type != LIBPFF_FILE_TYPE_64BIT )
283
16.0k
   && ( file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
284
0
  {
285
0
    libcerror_error_set(
286
0
     error,
287
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
288
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
289
0
     "%s: unsupported file type.",
290
0
     function );
291
292
0
    return( -1 );
293
0
  }
294
1.74M
  if( file_type == LIBPFF_FILE_TYPE_32BIT )
295
1.43M
  {
296
1.43M
    checksum_data_size          = 500;
297
1.43M
    index_node_data_size        = 512;
298
1.43M
    index_node_footer_data_size = sizeof( pff_index_node_32bit_footer_t );
299
1.43M
  }
300
315k
  else if( file_type == LIBPFF_FILE_TYPE_64BIT )
301
299k
  {
302
299k
    checksum_data_size          = 496;
303
299k
    index_node_data_size        = 512;
304
299k
    index_node_footer_data_size = sizeof( pff_index_node_64bit_footer_t );
305
299k
  }
306
16.0k
  else if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
307
16.0k
  {
308
16.0k
    checksum_data_size          = 4072;
309
16.0k
    index_node_data_size        = 4096;
310
16.0k
    index_node_footer_data_size = sizeof( pff_index_node_64bit_4k_page_footer_t );
311
16.0k
  }
312
1.74M
  maximum_entries_data_size = index_node_data_size - index_node_footer_data_size;
313
314
1.74M
  if( data_size < index_node_data_size )
315
0
  {
316
0
    libcerror_error_set(
317
0
     error,
318
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
319
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
320
0
     "%s: invalid data size value too small.",
321
0
     function );
322
323
0
    return( -1 );
324
0
  }
325
#if defined( HAVE_DEBUG_OUTPUT )
326
  if( libcnotify_verbose != 0 )
327
  {
328
    libcnotify_printf(
329
     "%s: index node data:\n",
330
     function );
331
    libcnotify_print_data(
332
     data,
333
     data_size,
334
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
335
  }
336
#endif
337
1.74M
  if( libpff_index_node_read_footer_data(
338
1.74M
       index_node,
339
1.74M
       &( data[ maximum_entries_data_size ] ),
340
1.74M
       index_node_footer_data_size,
341
1.74M
       file_type,
342
1.74M
       error ) != 1 )
343
909
  {
344
909
    libcerror_error_set(
345
909
     error,
346
909
     LIBCERROR_ERROR_DOMAIN_IO,
347
909
     LIBCERROR_IO_ERROR_READ_FAILED,
348
909
     "%s: unable to read index node footer.",
349
909
     function );
350
351
909
    return( -1 );
352
909
  }
353
1.74M
  if( libpff_checksum_calculate_weak_crc32(
354
1.74M
       &calculated_checksum,
355
1.74M
       data,
356
1.74M
       checksum_data_size,
357
1.74M
       0,
358
1.74M
       error ) != 1 )
359
0
  {
360
0
    libcerror_error_set(
361
0
     error,
362
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
363
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
364
0
     "%s: unable to calculate weak CRC-32.",
365
0
     function );
366
367
0
    return( -1 );
368
0
  }
369
1.74M
  if( index_node->stored_checksum != calculated_checksum )
370
1.72M
  {
371
#if defined( HAVE_DEBUG_OUTPUT )
372
    if( libcnotify_verbose != 0 )
373
    {
374
      libcnotify_printf(
375
       "%s: mismatch in checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n",
376
       function,
377
       index_node->stored_checksum,
378
       calculated_checksum );
379
    }
380
#endif
381
    /* TODO smart error handling */
382
1.72M
  }
383
1.74M
  if( file_type == LIBPFF_FILE_TYPE_32BIT )
384
1.43M
  {
385
1.43M
    if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
386
1.39M
     && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) )
387
864k
    {
388
864k
      calculated_entry_size                = 16;
389
864k
      calculated_maximum_number_of_entries = 496 / 16;
390
864k
    }
391
566k
    else
392
566k
    {
393
566k
      calculated_entry_size                = 12;
394
566k
      calculated_maximum_number_of_entries = 496 / 12;
395
566k
    }
396
1.43M
  }
397
314k
  else if( file_type == LIBPFF_FILE_TYPE_64BIT )
398
298k
  {
399
298k
    if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
400
94.8k
     && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) )
401
54.3k
    {
402
54.3k
      calculated_entry_size                = 32;
403
54.3k
      calculated_maximum_number_of_entries = 488 / 32;
404
54.3k
    }
405
243k
    else
406
243k
    {
407
243k
      calculated_entry_size                = 24;
408
243k
      calculated_maximum_number_of_entries = 488 / 24;
409
243k
    }
410
298k
  }
411
16.0k
  else if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
412
16.0k
  {
413
16.0k
    if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
414
15.0k
     && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) )
415
13.2k
    {
416
13.2k
      calculated_entry_size                = 32;
417
13.2k
      calculated_maximum_number_of_entries = 4056 / 32;
418
13.2k
    }
419
2.76k
    else
420
2.76k
    {
421
2.76k
      calculated_entry_size                = 24;
422
2.76k
      calculated_maximum_number_of_entries = 4056 / 24;
423
2.76k
    }
424
16.0k
  }
425
1.74M
  if( ( index_node->entry_size != 0 )
426
1.57M
   && ( index_node->entry_size != calculated_entry_size ) )
427
1.15M
  {
428
#if defined( HAVE_DEBUG_OUTPUT )
429
    if( libcnotify_verbose != 0 )
430
    {
431
      libcnotify_printf(
432
       "%s: entry size mismatch (calculated: %" PRIu8 ", stored: %" PRIu8 ").\n",
433
       function,
434
       calculated_entry_size,
435
       index_node->entry_size );
436
    }
437
#endif
438
1.15M
    index_node->entry_size = calculated_entry_size;
439
1.15M
  }
440
1.74M
  if( ( index_node->maximum_number_of_entries != 0 )
441
1.60M
   && ( index_node->maximum_number_of_entries != calculated_maximum_number_of_entries ) )
442
1.18M
  {
443
#if defined( HAVE_DEBUG_OUTPUT )
444
    if( libcnotify_verbose != 0 )
445
    {
446
      libcnotify_printf(
447
       "%s: maximum number of entries mismatch (calculated: %" PRIu8 ", stored: %" PRIu8 ").\n",
448
       function,
449
       calculated_maximum_number_of_entries,
450
       index_node->maximum_number_of_entries );
451
    }
452
#endif
453
1.18M
    index_node->maximum_number_of_entries = calculated_maximum_number_of_entries;
454
1.18M
  }
455
1.74M
  if( index_node->number_of_entries > index_node->maximum_number_of_entries )
456
935k
  {
457
#if defined( HAVE_DEBUG_OUTPUT )
458
    if( libcnotify_verbose != 0 )
459
    {
460
      libcnotify_printf(
461
       "%s: number of entries: %" PRIu8 ", exceeds maximum: %" PRIu8 ".",
462
       function,
463
       index_node->number_of_entries,
464
       index_node->maximum_number_of_entries );
465
    }
466
#endif
467
935k
    index_node->number_of_entries = index_node->maximum_number_of_entries;
468
935k
  }
469
1.74M
  if( ( (uint16_t) index_node->number_of_entries * (uint16_t) index_node->entry_size ) > maximum_entries_data_size )
470
0
  {
471
0
    libcerror_error_set(
472
0
     error,
473
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
474
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
475
0
     "%s: size of entries: %" PRIu16 ", exceeds maximum: %" PRIzd ".",
476
0
     function,
477
0
     index_node->number_of_entries * index_node->entry_size,
478
0
     maximum_entries_data_size );
479
480
0
    return( -1 );
481
0
  }
482
#if defined( HAVE_DEBUG_OUTPUT )
483
  if( libcnotify_verbose != 0 )
484
  {
485
    index_node_entry_data      = index_node->data;
486
    index_node_entry_data_size = maximum_entries_data_size;
487
488
    /* Print all the entries
489
     */
490
    for( entry_index = 0;
491
         entry_index < index_node->maximum_number_of_entries;
492
         entry_index++ )
493
    {
494
      if( entry_index == index_node->number_of_entries )
495
      {
496
        result = libpff_index_node_check_for_empty_block(
497
            index_node_entry_data,
498
            index_node_entry_data_size,
499
            error );
500
501
        if( result == -1 )
502
        {
503
          libcerror_error_set(
504
           error,
505
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
506
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
507
           "%s: unable to determine if remaining index nodes are empty.",
508
           function );
509
510
          return( -1 );
511
        }
512
        else if( result != 0 )
513
        {
514
          break;
515
        }
516
        libcnotify_printf(
517
         "\n" );
518
        libcnotify_printf(
519
         "%s: remaining node entries\n",
520
         function );
521
      }
522
      if( file_type == LIBPFF_FILE_TYPE_32BIT )
523
      {
524
        byte_stream_copy_to_uint32_little_endian(
525
         index_node_entry_data,
526
         value_64bit );
527
      }
528
      else if( ( file_type == LIBPFF_FILE_TYPE_64BIT )
529
            || ( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
530
      {
531
        byte_stream_copy_to_uint64_little_endian(
532
         index_node_entry_data,
533
         value_64bit );
534
      }
535
      libcnotify_printf(
536
       "%s: entry: %03" PRIu16 " index node identifier\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
537
       function,
538
       entry_index,
539
       value_64bit,
540
       value_64bit );
541
542
      /* Process descriptor index node leaf nodes
543
       */
544
      if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
545
       && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) )
546
      {
547
        if( file_type == LIBPFF_FILE_TYPE_32BIT )
548
        {
549
          byte_stream_copy_to_uint32_little_endian(
550
           ( (pff_index_node_descriptor_entry_32bit_t *) index_node_entry_data )->data_identifier,
551
           value_64bit );
552
        }
553
        else if( ( file_type == LIBPFF_FILE_TYPE_64BIT )
554
              || ( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
555
        {
556
          byte_stream_copy_to_uint64_little_endian(
557
           ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->data_identifier,
558
           value_64bit );
559
        }
560
        libcnotify_printf(
561
         "%s: entry: %03" PRIu16 " data identifier\t\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
562
         function,
563
         entry_index,
564
         value_64bit,
565
         value_64bit );
566
567
        if( file_type == LIBPFF_FILE_TYPE_32BIT )
568
        {
569
          byte_stream_copy_to_uint32_little_endian(
570
           ( (pff_index_node_descriptor_entry_32bit_t *) index_node_entry_data )->local_descriptors_identifier,
571
           value_64bit );
572
        }
573
        else if( ( file_type == LIBPFF_FILE_TYPE_64BIT )
574
              || ( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
575
        {
576
          byte_stream_copy_to_uint64_little_endian(
577
           ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->local_descriptors_identifier,
578
           value_64bit );
579
        }
580
        libcnotify_printf(
581
         "%s: entry: %03" PRIu16 " local descriptors identifier\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
582
         function,
583
         entry_index,
584
         value_64bit,
585
         value_64bit );
586
587
        if( file_type == LIBPFF_FILE_TYPE_32BIT )
588
        {
589
          byte_stream_copy_to_uint32_little_endian(
590
           ( (pff_index_node_descriptor_entry_32bit_t *) index_node_entry_data )->parent_identifier,
591
           value_32bit );
592
        }
593
        else if( ( file_type == LIBPFF_FILE_TYPE_64BIT )
594
              || ( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
595
        {
596
          byte_stream_copy_to_uint32_little_endian(
597
           ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->parent_identifier,
598
           value_32bit );
599
        }
600
        libcnotify_printf(
601
         "%s: entry: %03" PRIu16 " parent identifier\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n",
602
         function,
603
         entry_index,
604
         value_32bit,
605
         value_32bit );
606
607
        if( ( file_type == LIBPFF_FILE_TYPE_64BIT )
608
         || ( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
609
        {
610
          byte_stream_copy_to_uint32_little_endian(
611
           ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->unknown1,
612
           value_32bit );
613
614
          libcnotify_printf(
615
           "%s: entry: %03" PRIu16 " unknown1\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n",
616
           function,
617
           entry_index,
618
           value_32bit,
619
           value_32bit );
620
        }
621
      }
622
      /* Process offset and descriptor index node branch nodes and offset index node leaf nodes
623
       */
624
      else
625
      {
626
        if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF )
627
        {
628
          if( file_type == LIBPFF_FILE_TYPE_32BIT )
629
          {
630
            byte_stream_copy_to_uint32_little_endian(
631
             ( (pff_index_node_branch_entry_32bit_t *) index_node_entry_data )->back_pointer,
632
             value_64bit );
633
          }
634
          else if( ( file_type == LIBPFF_FILE_TYPE_64BIT )
635
                || ( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
636
          {
637
            byte_stream_copy_to_uint64_little_endian(
638
             ( (pff_index_node_branch_entry_64bit_t *) index_node_entry_data )->back_pointer,
639
             value_64bit );
640
          }
641
          libcnotify_printf(
642
           "%s: entry: %03" PRIu16 " back pointer\t\t\t: 0x%08" PRIx64 "\n",
643
           function,
644
           entry_index,
645
           value_64bit );
646
        }
647
        if( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF )
648
        {
649
          if( file_type == LIBPFF_FILE_TYPE_32BIT )
650
          {
651
            byte_stream_copy_to_uint32_little_endian(
652
             ( (pff_index_node_offset_entry_32bit_t *) index_node_entry_data )->file_offset,
653
             value_64bit );
654
          }
655
          else if( ( file_type == LIBPFF_FILE_TYPE_64BIT )
656
                || ( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
657
          {
658
            byte_stream_copy_to_uint64_little_endian(
659
             ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->file_offset,
660
             value_64bit );
661
          }
662
        }
663
        else
664
        {
665
          if( file_type == LIBPFF_FILE_TYPE_32BIT )
666
          {
667
            byte_stream_copy_to_uint32_little_endian(
668
             ( (pff_index_node_branch_entry_32bit_t *) index_node_entry_data )->file_offset,
669
             value_64bit );
670
          }
671
          else if( ( file_type == LIBPFF_FILE_TYPE_64BIT )
672
                || ( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
673
          {
674
            byte_stream_copy_to_uint64_little_endian(
675
             ( (pff_index_node_branch_entry_64bit_t *) index_node_entry_data )->file_offset,
676
             value_64bit );
677
          }
678
        }
679
        libcnotify_printf(
680
         "%s: entry: %03" PRIu16 " file offset\t\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n",
681
         function,
682
         entry_index,
683
         value_64bit,
684
         value_64bit );
685
686
        if( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF )
687
        {
688
          if( file_type == LIBPFF_FILE_TYPE_32BIT )
689
          {
690
            byte_stream_copy_to_uint16_little_endian(
691
             ( (pff_index_node_offset_entry_32bit_t *) index_node_entry_data )->data_size,
692
             value_16bit );
693
          }
694
          else if( ( file_type == LIBPFF_FILE_TYPE_64BIT )
695
                || ( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
696
          {
697
            byte_stream_copy_to_uint16_little_endian(
698
             ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->data_size,
699
             value_16bit );
700
          }
701
          libcnotify_printf(
702
           "%s: entry: %03" PRIu16 " data size\t\t\t: %" PRIu16 "\n",
703
           function,
704
           entry_index,
705
           value_16bit );
706
707
          if( file_type == LIBPFF_FILE_TYPE_32BIT )
708
          {
709
            byte_stream_copy_to_uint16_little_endian(
710
             ( (pff_index_node_offset_entry_32bit_t *) index_node_entry_data )->reference_count,
711
             value_16bit );
712
          }
713
          else if( ( file_type == LIBPFF_FILE_TYPE_64BIT )
714
                || ( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
715
          {
716
            byte_stream_copy_to_uint16_little_endian(
717
             ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->reference_count,
718
             value_16bit );
719
          }
720
          libcnotify_printf(
721
           "%s: entry: %03" PRIu16 " reference count\t\t\t: %" PRIu16 "\n",
722
           function,
723
           entry_index,
724
           value_16bit );
725
726
          if( ( file_type == LIBPFF_FILE_TYPE_64BIT )
727
           || ( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
728
          {
729
            byte_stream_copy_to_uint32_little_endian(
730
             ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->data_allocation_table_file_offset,
731
             value_32bit );
732
733
            libcnotify_printf(
734
             "%s: entry: %03" PRIu16 " data allocation table offset\t: 0x%08" PRIx32 " (%" PRIu32 ")\n",
735
             function,
736
             entry_index,
737
             value_32bit,
738
             value_32bit );
739
          }
740
        }
741
      }
742
      index_node_entry_data      += index_node->entry_size;
743
      index_node_entry_data_size -= index_node->entry_size;
744
    }
745
    libcnotify_printf(
746
     "\n" );
747
  }
748
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
749
750
1.74M
  index_node->maximum_entries_data_size = (uint16_t) maximum_entries_data_size;
751
752
1.74M
  return( 1 );
753
1.74M
}
754
755
/* Reads an index node footer
756
 * Returns 1 if successful or -1 on error
757
 */
758
int libpff_index_node_read_footer_data(
759
     libpff_index_node_t *index_node,
760
     const uint8_t *data,
761
     size_t data_size,
762
     uint8_t file_type,
763
     libcerror_error_t **error )
764
1.74M
{
765
1.74M
  static char *function              = "libpff_index_node_read_footer_data";
766
1.74M
  size_t index_node_footer_data_size = 0;
767
1.74M
  uint8_t index_node_type_copy       = 0;
768
769
#if defined( HAVE_DEBUG_OUTPUT )
770
  uint64_t value_64bit               = 0;
771
  uint16_t value_16bit               = 0;
772
#endif
773
774
1.74M
  if( index_node == NULL )
775
0
  {
776
0
    libcerror_error_set(
777
0
     error,
778
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
779
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
780
0
     "%s: invalid index node.",
781
0
     function );
782
783
0
    return( -1 );
784
0
  }
785
1.74M
  if( data == NULL )
786
0
  {
787
0
    libcerror_error_set(
788
0
     error,
789
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
790
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
791
0
     "%s: invalid data.",
792
0
     function );
793
794
0
    return( -1 );
795
0
  }
796
1.74M
  if( data_size > (size_t) SSIZE_MAX )
797
0
  {
798
0
    libcerror_error_set(
799
0
     error,
800
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
801
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
802
0
     "%s: invalid data size value exceeds maximum.",
803
0
     function );
804
805
0
    return( -1 );
806
0
  }
807
1.74M
  if( ( file_type != LIBPFF_FILE_TYPE_32BIT )
808
315k
   && ( file_type != LIBPFF_FILE_TYPE_64BIT )
809
16.0k
   && ( file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
810
0
  {
811
0
    libcerror_error_set(
812
0
     error,
813
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
814
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
815
0
     "%s: unsupported file type.",
816
0
     function );
817
818
0
    return( -1 );
819
0
  }
820
1.74M
  if( file_type == LIBPFF_FILE_TYPE_32BIT )
821
1.43M
  {
822
1.43M
    index_node_footer_data_size = sizeof( pff_index_node_32bit_footer_t );;
823
1.43M
  }
824
315k
  else if( file_type == LIBPFF_FILE_TYPE_64BIT )
825
299k
  {
826
299k
    index_node_footer_data_size = sizeof( pff_index_node_64bit_footer_t );;
827
299k
  }
828
16.0k
  else if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
829
16.0k
  {
830
16.0k
    index_node_footer_data_size = sizeof( pff_index_node_64bit_4k_page_footer_t );
831
16.0k
  }
832
1.74M
  if( data_size < index_node_footer_data_size )
833
0
  {
834
0
    libcerror_error_set(
835
0
     error,
836
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
837
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
838
0
     "%s: invalid data size value too small.",
839
0
     function );
840
841
0
    return( -1 );
842
0
  }
843
#if defined( HAVE_DEBUG_OUTPUT )
844
  if( libcnotify_verbose != 0 )
845
  {
846
    libcnotify_printf(
847
     "%s: index node footer data:\n",
848
     function );
849
    libcnotify_print_data(
850
     data,
851
     data_size,
852
     0 );
853
  }
854
#endif
855
1.74M
  if( file_type == LIBPFF_FILE_TYPE_32BIT )
856
1.43M
  {
857
1.43M
    index_node->type     = ( (pff_index_node_32bit_footer_t *) data )->type;
858
1.43M
    index_node_type_copy = ( (pff_index_node_32bit_footer_t *) data )->type_copy;
859
860
1.43M
    byte_stream_copy_to_uint32_little_endian(
861
1.43M
     ( (pff_index_node_32bit_footer_t *) data )->back_pointer,
862
1.43M
     index_node->back_pointer );
863
864
1.43M
    byte_stream_copy_to_uint32_little_endian(
865
1.43M
     ( (pff_index_node_32bit_footer_t *) data )->checksum,
866
1.43M
     index_node->stored_checksum );
867
868
1.43M
    index_node->number_of_entries         = ( (pff_index_node_32bit_footer_t *) data )->number_of_entries;
869
1.43M
    index_node->maximum_number_of_entries = ( (pff_index_node_32bit_footer_t *) data )->maximum_number_of_entries;
870
1.43M
    index_node->entry_size                = ( (pff_index_node_32bit_footer_t *) data )->entry_size;
871
1.43M
    index_node->level                     = ( (pff_index_node_32bit_footer_t *) data )->level;
872
1.43M
  }
873
315k
  else if( file_type == LIBPFF_FILE_TYPE_64BIT )
874
299k
  {
875
299k
    index_node->type     = ( (pff_index_node_64bit_footer_t *) data )->type;
876
299k
    index_node_type_copy = ( (pff_index_node_64bit_footer_t *) data )->type_copy;
877
878
299k
    byte_stream_copy_to_uint32_little_endian(
879
299k
     ( (pff_index_node_64bit_footer_t *) data )->checksum,
880
299k
     index_node->stored_checksum );
881
882
299k
    byte_stream_copy_to_uint64_little_endian(
883
299k
     ( (pff_index_node_64bit_footer_t *) data )->back_pointer,
884
299k
     index_node->back_pointer );
885
886
299k
    index_node->number_of_entries         = ( (pff_index_node_64bit_footer_t *) data )->number_of_entries;
887
299k
    index_node->maximum_number_of_entries = ( (pff_index_node_64bit_footer_t *) data )->maximum_number_of_entries;
888
299k
    index_node->entry_size                = ( (pff_index_node_64bit_footer_t *) data )->entry_size;
889
299k
    index_node->level                     = ( (pff_index_node_64bit_footer_t *) data )->level;
890
299k
  }
891
16.0k
  else if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
892
16.0k
  {
893
16.0k
    index_node->type     = ( (pff_index_node_64bit_4k_page_footer_t *) data )->type;
894
16.0k
    index_node_type_copy = ( (pff_index_node_64bit_4k_page_footer_t *) data )->type_copy;
895
896
16.0k
    byte_stream_copy_to_uint32_little_endian(
897
16.0k
     ( (pff_index_node_64bit_4k_page_footer_t *) data )->checksum,
898
16.0k
     index_node->stored_checksum );
899
900
16.0k
    byte_stream_copy_to_uint64_little_endian(
901
16.0k
     ( (pff_index_node_64bit_4k_page_footer_t *) data )->back_pointer,
902
16.0k
     index_node->back_pointer );
903
904
16.0k
    byte_stream_copy_to_uint16_little_endian(
905
16.0k
     ( (pff_index_node_64bit_4k_page_footer_t *) data )->number_of_entries,
906
16.0k
     index_node->number_of_entries );
907
908
16.0k
    byte_stream_copy_to_uint16_little_endian(
909
16.0k
     ( (pff_index_node_64bit_4k_page_footer_t *) data )->maximum_number_of_entries,
910
16.0k
     index_node->maximum_number_of_entries );
911
912
16.0k
    index_node->entry_size = ( (pff_index_node_64bit_4k_page_footer_t *) data )->entry_size;
913
16.0k
    index_node->level      = ( (pff_index_node_64bit_4k_page_footer_t *) data )->level;
914
16.0k
  }
915
#if defined( HAVE_DEBUG_OUTPUT )
916
  if( libcnotify_verbose != 0 )
917
  {
918
    libcnotify_printf(
919
     "%s: number of entries\t\t\t: %" PRIu16 "\n",
920
     function,
921
     index_node->number_of_entries );
922
923
    libcnotify_printf(
924
     "%s: maximum number of entries\t\t: %" PRIu16 "\n",
925
     function,
926
     index_node->maximum_number_of_entries );
927
928
    libcnotify_printf(
929
     "%s: entry size\t\t\t\t: %" PRIu8 "\n",
930
     function,
931
     index_node->entry_size );
932
933
    libcnotify_printf(
934
     "%s: node level\t\t\t\t: %" PRIu8 "\n",
935
     function,
936
     index_node->level );
937
938
    if( file_type == LIBPFF_FILE_TYPE_64BIT )
939
    {
940
      libcnotify_printf(
941
       "%s: padding:\n",
942
       function );
943
      libcnotify_print_data(
944
       ( (pff_index_node_64bit_footer_t *) data )->padding1,
945
       4,
946
       0 );
947
    }
948
    else if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
949
    {
950
      libcnotify_printf(
951
       "%s: padding:\n",
952
       function );
953
      libcnotify_print_data(
954
       ( (pff_index_node_64bit_4k_page_footer_t *) data )->padding1,
955
       10,
956
       0 );
957
    }
958
    libcnotify_printf(
959
     "%s: index node type\t\t\t: 0x%02" PRIx8 "\n",
960
     function,
961
     index_node->type );
962
    libcnotify_printf(
963
     "%s: index node type copy\t\t: 0x%02" PRIx8 "\n",
964
     function,
965
     index_node_type_copy );
966
967
    if( file_type == LIBPFF_FILE_TYPE_32BIT )
968
    {
969
      byte_stream_copy_to_uint16_little_endian(
970
       ( (pff_index_node_32bit_footer_t *) data )->signature,
971
       value_16bit );
972
      libcnotify_printf(
973
       "%s: signature\t\t\t\t: 0x%04" PRIx16 "\n",
974
       function,
975
       value_16bit );
976
977
      libcnotify_printf(
978
       "%s: back pointer\t\t\t: 0x%08" PRIx64 "\n",
979
       function,
980
       index_node->back_pointer );
981
      libcnotify_printf(
982
       "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n",
983
       function,
984
       index_node->stored_checksum );
985
    }
986
    else if( file_type == LIBPFF_FILE_TYPE_64BIT )
987
    {
988
      byte_stream_copy_to_uint16_little_endian(
989
       ( (pff_index_node_64bit_footer_t *) data )->signature,
990
       value_16bit );
991
      libcnotify_printf(
992
       "%s: signature\t\t\t\t: 0x%04" PRIx16 "\n",
993
       function,
994
       value_16bit );
995
996
      libcnotify_printf(
997
       "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n",
998
       function,
999
       index_node->stored_checksum );
1000
      libcnotify_printf(
1001
       "%s: back pointer\t\t\t: 0x%08" PRIx64 "\n",
1002
       function,
1003
       index_node->back_pointer );
1004
    }
1005
    else if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
1006
    {
1007
      byte_stream_copy_to_uint16_little_endian(
1008
       ( (pff_index_node_64bit_4k_page_footer_t *) data )->signature,
1009
       value_16bit );
1010
      libcnotify_printf(
1011
       "%s: signature\t\t\t\t: 0x%04" PRIx16 "\n",
1012
       function,
1013
       value_16bit );
1014
1015
      libcnotify_printf(
1016
       "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n",
1017
       function,
1018
       index_node->stored_checksum );
1019
      libcnotify_printf(
1020
       "%s: back pointer\t\t\t: 0x%08" PRIx64 "\n",
1021
       function,
1022
       index_node->back_pointer );
1023
1024
      byte_stream_copy_to_uint64_little_endian(
1025
       ( (pff_index_node_64bit_4k_page_footer_t *) data )->unknown1,
1026
       value_64bit );
1027
      libcnotify_printf(
1028
       "%s: unknown1\t\t\t\t: 0x%08" PRIx64 "\n",
1029
       function,
1030
       value_64bit );
1031
    }
1032
    libcnotify_printf(
1033
     "\n" );
1034
  }
1035
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1036
1037
1.74M
  if( index_node->type != index_node_type_copy )
1038
1.45M
  {
1039
#if defined( HAVE_DEBUG_OUTPUT )
1040
    if( libcnotify_verbose != 0 )
1041
    {
1042
      libcnotify_printf(
1043
       "%s: mismatch in index node type (0x%02" PRIx8 " != 0x%02" PRIx8 ").\n",
1044
       function,
1045
       index_node->type,
1046
       index_node_type_copy );
1047
    }
1048
#endif
1049
1.45M
    if( ( index_node->type != LIBPFF_INDEX_TYPE_DESCRIPTOR )
1050
895k
     && ( index_node->type != LIBPFF_INDEX_TYPE_OFFSET )
1051
865k
     && ( ( index_node_type_copy == LIBPFF_INDEX_TYPE_DESCRIPTOR )
1052
33.3k
       || ( index_node_type_copy == LIBPFF_INDEX_TYPE_OFFSET ) ) )
1053
864k
    {
1054
864k
      index_node->type = index_node_type_copy;
1055
864k
    }
1056
1.45M
  }
1057
1.74M
  if( ( index_node->type != LIBPFF_INDEX_TYPE_DESCRIPTOR )
1058
243k
   && ( index_node->type != LIBPFF_INDEX_TYPE_OFFSET ) )
1059
909
  {
1060
909
    libcerror_error_set(
1061
909
     error,
1062
909
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1063
909
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1064
909
     "%s: unsupported index node type: 0x%02" PRIx8 ".",
1065
909
     function,
1066
909
     index_node->type );
1067
1068
909
    return( -1 );
1069
909
  }
1070
1.74M
  return( 1 );
1071
1.74M
}
1072
1073
/* Reads an index node
1074
 * Returns 1 if successful or -1 on error
1075
 */
1076
int libpff_index_node_read_file_io_handle(
1077
     libpff_index_node_t *index_node,
1078
     libbfio_handle_t *file_io_handle,
1079
     off64_t node_offset,
1080
     uint8_t file_type,
1081
     libcerror_error_t **error )
1082
1.74M
{
1083
1.74M
  static char *function = "libpff_index_node_read_file_io_handle";
1084
1.74M
  ssize_t read_count    = 0;
1085
1086
1.74M
  if( index_node == NULL )
1087
0
  {
1088
0
    libcerror_error_set(
1089
0
     error,
1090
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1091
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1092
0
     "%s: invalid index node.",
1093
0
     function );
1094
1095
0
    return( -1 );
1096
0
  }
1097
1.74M
  if( index_node->data != NULL )
1098
0
  {
1099
0
    libcerror_error_set(
1100
0
     error,
1101
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1102
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1103
0
     "%s: invalid index node - data already set.",
1104
0
     function );
1105
1106
0
    return( -1 );
1107
0
  }
1108
1.74M
  if( ( file_type != LIBPFF_FILE_TYPE_32BIT )
1109
316k
   && ( file_type != LIBPFF_FILE_TYPE_64BIT )
1110
16.1k
   && ( file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
1111
0
  {
1112
0
    libcerror_error_set(
1113
0
     error,
1114
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1115
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1116
0
     "%s: unsupported file type.",
1117
0
     function );
1118
1119
0
    return( -1 );
1120
0
  }
1121
1.74M
  if( ( file_type == LIBPFF_FILE_TYPE_32BIT )
1122
316k
   || ( file_type == LIBPFF_FILE_TYPE_64BIT ) )
1123
1.73M
  {
1124
1.73M
    index_node->data_size = 512;
1125
1.73M
  }
1126
16.1k
  else if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
1127
16.1k
  {
1128
16.1k
    index_node->data_size = 4096;
1129
16.1k
  }
1130
1.74M
  index_node->data = (uint8_t *) memory_allocate(
1131
1.74M
                                  sizeof( uint8_t ) * index_node->data_size );
1132
1133
1.74M
  if( index_node->data == NULL )
1134
0
  {
1135
0
    libcerror_error_set(
1136
0
     error,
1137
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1138
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1139
0
     "%s: unable to create index node data.",
1140
0
     function );
1141
1142
0
    goto on_error;
1143
0
  }
1144
#if defined( HAVE_DEBUG_OUTPUT )
1145
  if( libcnotify_verbose != 0 )
1146
  {
1147
    libcnotify_printf(
1148
     "%s: reading index node data at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
1149
     function,
1150
     node_offset,
1151
     node_offset );
1152
  }
1153
#endif
1154
1.74M
  read_count = libbfio_handle_read_buffer_at_offset(
1155
1.74M
                file_io_handle,
1156
1.74M
                index_node->data,
1157
1.74M
                index_node->data_size,
1158
1.74M
                node_offset,
1159
1.74M
                error );
1160
1161
1.74M
  if( read_count != (ssize_t) index_node->data_size )
1162
1.48k
  {
1163
1.48k
    libcerror_error_set(
1164
1.48k
     error,
1165
1.48k
     LIBCERROR_ERROR_DOMAIN_IO,
1166
1.48k
     LIBCERROR_IO_ERROR_READ_FAILED,
1167
1.48k
     "%s: unable to read index node data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1168
1.48k
     function,
1169
1.48k
     node_offset,
1170
1.48k
     node_offset );
1171
1172
1.48k
    goto on_error;
1173
1.48k
  }
1174
1.74M
  if( libpff_index_node_read_data(
1175
1.74M
       index_node,
1176
1.74M
       index_node->data,
1177
1.74M
       index_node->data_size,
1178
1.74M
       file_type,
1179
1.74M
       error ) != 1 )
1180
909
  {
1181
909
    libcerror_error_set(
1182
909
     error,
1183
909
     LIBCERROR_ERROR_DOMAIN_IO,
1184
909
     LIBCERROR_IO_ERROR_READ_FAILED,
1185
909
     "%s: unable to read index node.",
1186
909
     function );
1187
1188
909
    goto on_error;
1189
909
  }
1190
1.74M
  index_node->entries_data = index_node->data;
1191
1192
1.74M
  return( 1 );
1193
1194
2.39k
on_error:
1195
2.39k
  if( index_node->data != NULL )
1196
2.39k
  {
1197
2.39k
    memory_free(
1198
2.39k
     index_node->data );
1199
1200
2.39k
    index_node->data = NULL;
1201
2.39k
  }
1202
2.39k
  return( -1 );
1203
1.74M
}
1204
1205
/* Checks if a buffer containing the chunk data is filled with same value bytes (empty-block)
1206
 * Returns 1 if a pattern was found, 0 if not or -1 on error
1207
 */
1208
int libpff_index_node_check_for_empty_block(
1209
     const uint8_t *data,
1210
     size_t data_size,
1211
     libcerror_error_t **error )
1212
0
{
1213
0
  libpff_aligned_t *aligned_data_index = NULL;
1214
0
  libpff_aligned_t *aligned_data_start = NULL;
1215
0
  uint8_t *data_index                  = NULL;
1216
0
  uint8_t *data_start                  = NULL;
1217
0
  static char *function                = "libpff_index_node_check_for_empty_block";
1218
1219
0
  if( data == NULL )
1220
0
  {
1221
0
    libcerror_error_set(
1222
0
     error,
1223
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1224
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1225
0
     "%s: invalid data.",
1226
0
     function );
1227
1228
0
    return( -1 );
1229
0
  }
1230
0
  if( data_size > (size_t) SSIZE_MAX )
1231
0
  {
1232
0
    libcerror_error_set(
1233
0
     error,
1234
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1235
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1236
0
     "%s: invalid data size value exceeds maximum.",
1237
0
     function );
1238
1239
0
    return( -1 );
1240
0
  }
1241
0
  data_start = (uint8_t *) data;
1242
0
  data_index = (uint8_t *) data + 1;
1243
0
  data_size -= 1;
1244
1245
  /* Only optimize for data larger than the alignment
1246
   */
1247
0
  if( data_size > ( 2 * sizeof( libpff_aligned_t ) ) )
1248
0
  {
1249
    /* Align the data start
1250
     */
1251
0
    while( ( (intptr_t) data_start % sizeof( libpff_aligned_t ) ) != 0 )
1252
0
    {
1253
0
      if( *data_start != *data_index )
1254
0
      {
1255
0
        return( 0 );
1256
0
      }
1257
0
      data_start += 1;
1258
0
      data_index += 1;
1259
0
      data_size  -= 1;
1260
0
    }
1261
    /* Align the data index
1262
     */
1263
0
    while( ( (intptr_t) data_index % sizeof( libpff_aligned_t ) ) != 0 )
1264
0
    {
1265
0
      if( *data_start != *data_index )
1266
0
      {
1267
0
        return( 0 );
1268
0
      }
1269
0
      data_index += 1;
1270
0
      data_size  -= 1;
1271
0
    }
1272
0
    aligned_data_start = (libpff_aligned_t *) data_start;
1273
0
    aligned_data_index = (libpff_aligned_t *) data_index;
1274
1275
0
    while( data_size > sizeof( libpff_aligned_t ) )
1276
0
    {
1277
0
      if( *aligned_data_start != *aligned_data_index )
1278
0
      {
1279
0
        return( 0 );
1280
0
      }
1281
0
      aligned_data_index += 1;
1282
0
      data_size          -= sizeof( libpff_aligned_t );
1283
0
    }
1284
0
    data_index = (uint8_t *) aligned_data_index;
1285
0
  }
1286
0
  while( data_size != 0 )
1287
0
  {
1288
0
    if( *data_start != *data_index )
1289
0
    {
1290
0
      return( 0 );
1291
0
    }
1292
0
    data_index += 1;
1293
0
    data_size  -= 1;
1294
0
  }
1295
0
  return( 1 );
1296
0
}
1297