Coverage Report

Created: 2023-06-07 06:53

/src/libpff/libpff/libpff_index.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Index functions
3
 *
4
 * Copyright (C) 2008-2023, 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_block_descriptor.h"
28
#include "libpff_block_tree.h"
29
#include "libpff_block_tree_node.h"
30
#include "libpff_definitions.h"
31
#include "libpff_index.h"
32
#include "libpff_index_node.h"
33
#include "libpff_index_value.h"
34
#include "libpff_libbfio.h"
35
#include "libpff_libcerror.h"
36
#include "libpff_libcnotify.h"
37
#include "libpff_libfdata.h"
38
#include "libpff_libfmapi.h"
39
#include "libpff_unused.h"
40
41
#include "pff_index_node.h"
42
43
/* Creates an index
44
 * Make sure the value index is referencing, is set to NULL
45
 * Returns 1 if successful or -1 on error
46
 */
47
int libpff_index_initialize(
48
     libpff_index_t **index,
49
     uint8_t index_type,
50
     off64_t root_node_offset,
51
     uint64_t root_node_back_pointer,
52
     libcerror_error_t **error )
53
5.46k
{
54
5.46k
  static char *function = "libpff_index_initialize";
55
56
5.46k
  if( index == NULL )
57
0
  {
58
0
    libcerror_error_set(
59
0
     error,
60
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
61
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
62
0
     "%s: invalid index.",
63
0
     function );
64
65
0
    return( -1 );
66
0
  }
67
5.46k
  if( *index != NULL )
68
0
  {
69
0
    libcerror_error_set(
70
0
     error,
71
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
72
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
73
0
     "%s: invalid index value already set.",
74
0
     function );
75
76
0
    return( -1 );
77
0
  }
78
5.46k
  *index = memory_allocate_structure(
79
5.46k
            libpff_index_t );
80
81
5.46k
  if( *index == NULL )
82
0
  {
83
0
    libcerror_error_set(
84
0
     error,
85
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
86
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
87
0
     "%s: unable to create index.",
88
0
     function );
89
90
0
    goto on_error;
91
0
  }
92
5.46k
  if( memory_set(
93
5.46k
       *index,
94
5.46k
       0,
95
5.46k
       sizeof( libpff_index_t ) ) == NULL )
96
0
  {
97
0
    libcerror_error_set(
98
0
     error,
99
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
100
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
101
0
     "%s: unable to clear index.",
102
0
     function );
103
104
0
    goto on_error;
105
0
  }
106
5.46k
  ( *index )->type                   = index_type;
107
5.46k
  ( *index )->root_node_offset       = root_node_offset;
108
5.46k
  ( *index )->root_node_back_pointer = root_node_back_pointer;
109
110
5.46k
  return( 1 );
111
112
0
on_error:
113
0
  if( *index != NULL )
114
0
  {
115
0
    memory_free(
116
0
     *index );
117
118
0
    *index = NULL;
119
0
  }
120
0
  return( -1 );
121
5.46k
}
122
123
/* Frees an index
124
 * Returns 1 if successful or -1 on error
125
 */
126
int libpff_index_free(
127
     libpff_index_t **index,
128
     libcerror_error_t **error )
129
5.46k
{
130
5.46k
  static char *function = "libpff_index_free";
131
132
5.46k
  if( index == NULL )
133
0
  {
134
0
    libcerror_error_set(
135
0
     error,
136
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
137
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
138
0
     "%s: invalid index.",
139
0
     function );
140
141
0
    return( -1 );
142
0
  }
143
5.46k
  if( *index != NULL )
144
5.46k
  {
145
5.46k
    memory_free(
146
5.46k
     *index );
147
148
5.46k
    *index = NULL;
149
5.46k
  }
150
5.46k
  return( 1 );
151
5.46k
}
152
153
/* Checks if this is the first time the index node block is being read
154
 * Returns 1 if successful or -1 on error
155
 */
156
int libpff_index_check_if_node_block_first_read(
157
     libpff_index_t *index,
158
     libpff_block_tree_t *node_block_tree,
159
     off64_t node_offset,
160
     uint64_t identifier,
161
     libcerror_error_t **error )
162
416k
{
163
416k
  libpff_block_descriptor_t *existing_block_descriptor = NULL;
164
416k
  libpff_block_descriptor_t *new_block_descriptor      = NULL;
165
416k
  libpff_block_tree_node_t *leaf_block_tree_node       = NULL;
166
416k
  static char *function                                = "libpff_index_check_if_node_block_first_read";
167
416k
  int leaf_value_index                                 = 0;
168
416k
  int result                                           = 0;
169
170
416k
  if( index == NULL )
171
0
  {
172
0
    libcerror_error_set(
173
0
     error,
174
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
175
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
176
0
     "%s: invalid index.",
177
0
     function );
178
179
0
    return( -1 );
180
0
  }
181
416k
  if( libpff_block_descriptor_initialize(
182
416k
       &new_block_descriptor,
183
416k
       error ) != 1 )
184
0
  {
185
0
    libcerror_error_set(
186
0
     error,
187
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
188
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
189
0
     "%s: unable to create block descriptor.",
190
0
     function );
191
192
0
    goto on_error;
193
0
  }
194
416k
  new_block_descriptor->identifier = identifier;
195
196
416k
  result = libpff_block_tree_insert_block_descriptor_by_offset(
197
416k
            node_block_tree,
198
416k
            node_offset,
199
416k
            new_block_descriptor,
200
416k
            &leaf_value_index,
201
416k
            &leaf_block_tree_node,
202
416k
            &existing_block_descriptor,
203
416k
            error );
204
205
416k
  if( result == -1 )
206
184
  {
207
184
    libcerror_error_set(
208
184
     error,
209
184
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
210
184
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
211
184
     "%s: unable to insert block descriptor for index node at offset: %" PRIi64 " (0x%08" PRIx64 ") in node block tree.",
212
184
     function,
213
184
     node_offset,
214
184
     node_offset );
215
216
184
    goto on_error;
217
184
  }
218
416k
  else if( result == 0 )
219
80
  {
220
80
    libcerror_error_set(
221
80
     error,
222
80
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
223
80
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
224
80
     "%s: invalid index node at offset: %" PRIi64 " (0x%08" PRIx64 ") value already exists.",
225
80
     function,
226
80
     node_offset,
227
80
     node_offset );
228
229
80
    goto on_error;
230
80
  }
231
416k
  new_block_descriptor = NULL;
232
233
416k
  return( 1 );
234
235
264
on_error:
236
264
  if( new_block_descriptor != NULL )
237
264
  {
238
264
    libpff_block_descriptor_free(
239
264
     &new_block_descriptor,
240
264
     NULL );
241
264
  }
242
264
  return( -1 );
243
416k
}
244
245
/* Retrieves the leaf node from an index node for the specific identifier
246
 * Returns 1 if successful, 0 if no leaf node was found or -1 on error
247
 */
248
int libpff_index_get_leaf_node_from_node_by_identifier(
249
     libpff_index_t *index,
250
     libpff_io_handle_t *io_handle,
251
     libbfio_handle_t *file_io_handle,
252
     libpff_block_tree_t *node_block_tree,
253
     off64_t node_offset,
254
     uint64_t node_back_pointer,
255
     uint64_t identifier,
256
     libpff_index_node_t **leaf_node,
257
     uint16_t *leaf_node_entry_index,
258
     libcerror_error_t **error )
259
416k
{
260
416k
  libpff_index_node_t *index_node = NULL;
261
416k
  uint8_t *node_entry_data        = NULL;
262
416k
  static char *function           = "libpff_index_get_leaf_node_from_node_by_identifier";
263
416k
  uint64_t entry_identifier       = 0;
264
416k
  uint64_t sub_node_back_pointer  = 0;
265
416k
  uint64_t sub_node_offset        = 0;
266
416k
  uint16_t entry_index            = 0;
267
416k
  int result                      = 0;
268
269
416k
  if( index == NULL )
270
0
  {
271
0
    libcerror_error_set(
272
0
     error,
273
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
274
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
275
0
     "%s: invalid index.",
276
0
     function );
277
278
0
    return( -1 );
279
0
  }
280
416k
  if( io_handle == NULL )
281
0
  {
282
0
    libcerror_error_set(
283
0
     error,
284
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
285
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
286
0
     "%s: invalid IO handle.",
287
0
     function );
288
289
0
    return( -1 );
290
0
  }
291
416k
  if( leaf_node == NULL )
292
0
  {
293
0
    libcerror_error_set(
294
0
     error,
295
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
296
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
297
0
     "%s: invalid leaf node.",
298
0
     function );
299
300
0
    return( -1 );
301
0
  }
302
416k
  if( leaf_node_entry_index == NULL )
303
0
  {
304
0
    libcerror_error_set(
305
0
     error,
306
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
307
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
308
0
     "%s: invalid leaf node entry index.",
309
0
     function );
310
311
0
    return( -1 );
312
0
  }
313
#if defined( HAVE_DEBUG_OUTPUT )
314
  if( libcnotify_verbose != 0 )
315
  {
316
    libcnotify_printf(
317
     "%s: requested identifier\t: 0x%08" PRIx64 " (%" PRIu64 ").\n",
318
     function,
319
     identifier,
320
     identifier );
321
  }
322
#endif
323
416k
  if( libpff_index_check_if_node_block_first_read(
324
416k
       index,
325
416k
       node_block_tree,
326
416k
       node_offset,
327
416k
       identifier,
328
416k
       error ) != 1 )
329
264
  {
330
264
    libcerror_error_set(
331
264
     error,
332
264
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
333
264
     LIBCERROR_RUNTIME_ERROR_GENERIC,
334
264
     "%s: unable to check if first read of index node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
335
264
     function,
336
264
     node_offset,
337
264
     node_offset );
338
339
264
    goto on_error;
340
264
  }
341
416k
  if( libpff_index_node_initialize(
342
416k
       &index_node,
343
416k
       error ) != 1 )
344
0
  {
345
0
    libcerror_error_set(
346
0
     error,
347
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
348
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
349
0
     "%s: unable to create index node.",
350
0
     function );
351
352
0
    goto on_error;
353
0
  }
354
416k
  if( libpff_index_node_read_file_io_handle(
355
416k
       index_node,
356
416k
       file_io_handle,
357
416k
       node_offset,
358
416k
       io_handle->file_type,
359
416k
       error ) != 1 )
360
258
  {
361
258
    libcerror_error_set(
362
258
     error,
363
258
     LIBCERROR_ERROR_DOMAIN_IO,
364
258
     LIBCERROR_IO_ERROR_READ_FAILED,
365
258
     "%s: unable to read index node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
366
258
     function,
367
258
     node_offset,
368
258
     node_offset );
369
370
258
    goto on_error;
371
258
  }
372
415k
  if( index->type != index_node->type )
373
60
  {
374
60
    libcerror_error_set(
375
60
     error,
376
60
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
377
60
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
378
60
     "%s: index type mismatch (index: 0x%02" PRIx8 ", node: 0x%02" PRIx8 ").",
379
60
     function,
380
60
     index->type,
381
60
     index_node->type );
382
383
    /* TODO error tollerance */
384
385
60
    goto on_error;
386
60
  }
387
415k
  if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF )
388
190k
  {
389
190k
    if( index_node->back_pointer != node_back_pointer )
390
149
    {
391
149
      libcerror_error_set(
392
149
       error,
393
149
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
394
149
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
395
149
       "%s: back pointer mismatch (index entry: %" PRIu64 ", node: %" PRIu64 ").",
396
149
       function,
397
149
       node_back_pointer,
398
149
       index_node->back_pointer );
399
400
      /* TODO error tollerance */
401
402
149
      goto on_error;
403
149
    }
404
190k
  }
405
415k
  for( entry_index = 0;
406
2.10M
       entry_index < index_node->number_of_entries;
407
1.69M
       entry_index++ )
408
2.04M
  {
409
2.04M
    if( libpff_index_node_get_entry_data(
410
2.04M
         index_node,
411
2.04M
         entry_index,
412
2.04M
         &node_entry_data,
413
2.04M
         error ) != 1 )
414
0
    {
415
0
      libcerror_error_set(
416
0
       error,
417
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
418
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
419
0
       "%s: unable to retrieve node entry: %" PRIu16 " data.",
420
0
       function,
421
0
       entry_index );
422
423
0
      goto on_error;
424
0
    }
425
2.04M
    if( node_entry_data == NULL )
426
0
    {
427
0
      libcerror_error_set(
428
0
       error,
429
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
430
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
431
0
       "%s: missing node entry: %" PRIu16 " data.",
432
0
       function,
433
0
       entry_index );
434
435
0
      goto on_error;
436
0
    }
437
2.04M
    if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
438
1.48M
    {
439
1.48M
      byte_stream_copy_to_uint32_little_endian(
440
1.48M
       ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->identifier,
441
1.48M
       entry_identifier );
442
1.48M
    }
443
558k
    else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
444
558k
          || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
445
558k
    {
446
558k
      byte_stream_copy_to_uint64_little_endian(
447
558k
       ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->identifier,
448
558k
       entry_identifier );
449
558k
    }
450
#if defined( HAVE_DEBUG_OUTPUT )
451
    if( libcnotify_verbose != 0 )
452
    {
453
      libcnotify_printf(
454
       "%s: node entry: %" PRIu16 " identifier\t: 0x%08" PRIx64 " (%" PRIu64 ").\n",
455
       function,
456
       entry_index,
457
       entry_identifier,
458
       entry_identifier );
459
    }
460
#endif
461
    /* Ignore the upper 32-bit of descriptor identifiers
462
     */
463
2.04M
    if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
464
1.84M
    {
465
1.84M
      entry_identifier &= 0xffffffffUL;
466
1.84M
    }
467
2.04M
    if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF )
468
1.15M
    {
469
1.15M
      if( ( entry_index == 0 )
470
1.15M
       || ( identifier >= entry_identifier ) )
471
1.05M
      {
472
1.05M
        if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
473
787k
        {
474
787k
          byte_stream_copy_to_uint32_little_endian(
475
787k
           ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->file_offset,
476
787k
           sub_node_offset );
477
478
787k
          byte_stream_copy_to_uint32_little_endian(
479
787k
           ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->back_pointer,
480
787k
           sub_node_back_pointer );
481
787k
        }
482
266k
        else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
483
266k
              || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
484
266k
        {
485
266k
          byte_stream_copy_to_uint64_little_endian(
486
266k
           ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->file_offset,
487
266k
           sub_node_offset );
488
489
266k
          byte_stream_copy_to_uint64_little_endian(
490
266k
           ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->back_pointer,
491
266k
           sub_node_back_pointer );
492
266k
        }
493
1.05M
      }
494
1.15M
    }
495
888k
    else if( identifier == entry_identifier )
496
36.1k
    {
497
36.1k
      *leaf_node             = index_node;
498
36.1k
      *leaf_node_entry_index = entry_index;
499
500
36.1k
      result = 1;
501
36.1k
    }
502
    /* A branch node contains the identifier of its first sub node
503
     */
504
2.04M
    if( identifier <= entry_identifier )
505
347k
    {
506
347k
      break;
507
347k
    }
508
2.04M
  }
509
415k
  if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF )
510
190k
  {
511
190k
    if( sub_node_offset > (uint64_t) INT64_MAX )
512
118
    {
513
118
      libcerror_error_set(
514
118
       error,
515
118
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
516
118
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
517
118
       "%s: invalid sub node offset value out of bounds.",
518
118
       function );
519
520
118
      goto on_error;
521
118
    }
522
190k
    result = libpff_index_get_leaf_node_from_node_by_identifier(
523
190k
        index,
524
190k
        io_handle,
525
190k
        file_io_handle,
526
190k
        node_block_tree,
527
190k
        sub_node_offset,
528
190k
        sub_node_back_pointer,
529
190k
        identifier,
530
190k
        leaf_node,
531
190k
        leaf_node_entry_index,
532
190k
        error );
533
534
190k
    if( result == -1 )
535
570
    {
536
570
      libcerror_error_set(
537
570
       error,
538
570
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
539
570
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
540
570
       "%s: unable to retrieve leaf node by identifier: 0x%08" PRIx64 " (%" PRIu64 ") from node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
541
570
       function,
542
570
       identifier,
543
570
       identifier,
544
570
       node_offset,
545
570
       node_offset );
546
547
570
      goto on_error;
548
570
    }
549
190k
  }
550
415k
  if( ( index_node != NULL )
551
415k
   && ( index_node != *leaf_node ) )
552
378k
  {
553
378k
    if( libpff_index_node_free(
554
378k
         &index_node,
555
378k
         error ) != 1 )
556
0
    {
557
0
      libcerror_error_set(
558
0
       error,
559
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
560
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
561
0
       "%s: unable to free index node.",
562
0
       function );
563
564
0
      goto on_error;
565
0
    }
566
378k
  }
567
415k
  return( result );
568
569
1.41k
on_error:
570
1.41k
  if( index_node != NULL )
571
1.15k
  {
572
1.15k
    libpff_index_node_free(
573
1.15k
     &index_node,
574
1.15k
     NULL );
575
1.15k
  }
576
1.41k
  return( -1 );
577
415k
}
578
579
/* Retrieves the value for the specific identifier
580
 * Returns 1 if successful, 0 if no value was found or -1 on error
581
 */
582
int libpff_index_get_value_by_identifier(
583
     libpff_index_t *index,
584
     libpff_io_handle_t *io_handle,
585
     libbfio_handle_t *file_io_handle,
586
     uint64_t identifier,
587
     libpff_index_value_t **index_value,
588
     libcerror_error_t **error )
589
225k
{
590
225k
  libpff_block_tree_t *node_block_tree   = NULL;
591
225k
  libpff_index_node_t *leaf_node         = NULL;
592
225k
  libpff_index_value_t *safe_index_value = NULL;
593
225k
  uint8_t *node_entry_data               = NULL;
594
225k
  static char *function                  = "libpff_index_get_value_by_identifier";
595
225k
  size_t index_node_size                 = 0;
596
225k
  uint16_t leaf_node_entry_index         = 0;
597
225k
  int result                             = 0;
598
599
225k
  if( index == NULL )
600
0
  {
601
0
    libcerror_error_set(
602
0
     error,
603
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
604
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
605
0
     "%s: invalid index.",
606
0
     function );
607
608
0
    return( -1 );
609
0
  }
610
225k
  if( io_handle == NULL )
611
0
  {
612
0
    libcerror_error_set(
613
0
     error,
614
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
615
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
616
0
     "%s: invalid IO handle.",
617
0
     function );
618
619
0
    return( -1 );
620
0
  }
621
225k
  if( index_value == NULL )
622
0
  {
623
0
    libcerror_error_set(
624
0
     error,
625
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
626
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
627
0
     "%s: invalid index value.",
628
0
     function );
629
630
0
    return( -1 );
631
0
  }
632
225k
  if( ( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
633
225k
   || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) )
634
225k
  {
635
225k
    index_node_size = 512;
636
225k
  }
637
564
  else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
638
564
  {
639
564
    index_node_size = 4096;
640
564
  }
641
225k
  if( libpff_block_tree_initialize(
642
225k
       &node_block_tree,
643
225k
       io_handle->file_size,
644
225k
       index_node_size,
645
225k
       error ) != 1 )
646
2
  {
647
2
    libcerror_error_set(
648
2
     error,
649
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
650
2
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
651
2
     "%s: unable to create index node block tree.",
652
2
     function );
653
654
2
    goto on_error;
655
2
  }
656
#if defined( HAVE_DEBUG_OUTPUT )
657
  if( libcnotify_verbose != 0 )
658
  {
659
    libcnotify_printf(
660
     "%s: requested identifier\t\t: 0x%08" PRIx64 " (%" PRIu64 ").\n",
661
     function,
662
     identifier,
663
     identifier );
664
  }
665
#endif
666
225k
  result = libpff_index_get_leaf_node_from_node_by_identifier(
667
225k
      index,
668
225k
      io_handle,
669
225k
      file_io_handle,
670
225k
      node_block_tree,
671
225k
      index->root_node_offset,
672
225k
      index->root_node_back_pointer,
673
225k
      identifier,
674
225k
      &leaf_node,
675
225k
      &leaf_node_entry_index,
676
225k
      error );
677
678
225k
  if( result == -1 )
679
849
  {
680
849
    libcerror_error_set(
681
849
     error,
682
849
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
683
849
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
684
849
     "%s: unable to retrieve leaf node by identifier: 0x%08" PRIx64 " (%" PRIu64 ") from root node.",
685
849
     function,
686
849
     identifier,
687
849
     identifier );
688
689
849
    goto on_error;
690
849
  }
691
225k
  else if( result != 0 )
692
36.1k
  {
693
36.1k
    if( libpff_index_node_get_entry_data(
694
36.1k
         leaf_node,
695
36.1k
         leaf_node_entry_index,
696
36.1k
         &node_entry_data,
697
36.1k
         error ) != 1 )
698
0
    {
699
0
      libcerror_error_set(
700
0
       error,
701
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
702
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
703
0
       "%s: unable to retrieve node entry: %" PRIu16 " data.",
704
0
       function,
705
0
       leaf_node_entry_index );
706
707
0
      goto on_error;
708
0
    }
709
36.1k
    if( node_entry_data == NULL )
710
0
    {
711
0
      libcerror_error_set(
712
0
       error,
713
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
714
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
715
0
       "%s: missing node entry: %" PRIu16 " data.",
716
0
       function,
717
0
       leaf_node_entry_index );
718
719
0
      goto on_error;
720
0
    }
721
36.1k
    if( libpff_index_value_initialize(
722
36.1k
         &safe_index_value,
723
36.1k
         error ) != 1 )
724
0
    {
725
0
      libcerror_error_set(
726
0
       error,
727
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
728
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
729
0
       "%s: unable to create index value.",
730
0
       function );
731
732
0
      goto on_error;
733
0
    }
734
36.1k
    if( libpff_index_value_read_data(
735
36.1k
         safe_index_value,
736
36.1k
         io_handle,
737
36.1k
         index->type,
738
36.1k
         node_entry_data,
739
36.1k
         (size_t) leaf_node->entry_size,
740
36.1k
         error ) != 1 )
741
140
    {
742
140
      libcerror_error_set(
743
140
       error,
744
140
       LIBCERROR_ERROR_DOMAIN_IO,
745
140
       LIBCERROR_IO_ERROR_READ_FAILED,
746
140
       "%s: unable to read index value.",
747
140
       function );
748
749
140
      goto on_error;
750
140
    }
751
35.9k
    if( libpff_index_node_free(
752
35.9k
         &leaf_node,
753
35.9k
         error ) != 1 )
754
0
    {
755
0
      libcerror_error_set(
756
0
       error,
757
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
758
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
759
0
       "%s: unable to free leaf node.",
760
0
       function );
761
762
0
      goto on_error;
763
0
    }
764
35.9k
  }
765
224k
  if( libpff_block_tree_free(
766
224k
       &node_block_tree,
767
224k
       (int (*)(intptr_t **, libcerror_error_t **)) &libpff_block_descriptor_free,
768
224k
       error ) != 1 )
769
0
  {
770
0
    libcerror_error_set(
771
0
     error,
772
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
773
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
774
0
     "%s: unable to free index node block tree.",
775
0
     function );
776
777
0
    goto on_error;
778
0
  }
779
224k
  *index_value = safe_index_value;
780
781
224k
  return( result );
782
783
991
on_error:
784
991
  if( safe_index_value != NULL )
785
140
  {
786
140
    libpff_index_value_free(
787
140
     &safe_index_value,
788
140
     NULL );
789
140
  }
790
991
  if( leaf_node != NULL )
791
140
  {
792
140
    libpff_index_node_free(
793
140
     &leaf_node,
794
140
     NULL );
795
140
  }
796
991
  if( node_block_tree != NULL )
797
989
  {
798
989
    libpff_block_tree_free(
799
989
     &node_block_tree,
800
989
     (int (*)(intptr_t **, libcerror_error_t **)) &libpff_block_descriptor_free,
801
989
     NULL );
802
989
  }
803
991
  return( -1 );
804
224k
}
805