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.c
Line
Count
Source
1
/*
2
 * Index 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_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
18.5k
{
54
18.5k
  static char *function = "libpff_index_initialize";
55
56
18.5k
  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
18.5k
  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
18.5k
  *index = memory_allocate_structure(
79
18.5k
            libpff_index_t );
80
81
18.5k
  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
18.5k
  if( memory_set(
93
18.5k
       *index,
94
18.5k
       0,
95
18.5k
       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
18.5k
  ( *index )->type                   = index_type;
107
18.5k
  ( *index )->root_node_offset       = root_node_offset;
108
18.5k
  ( *index )->root_node_back_pointer = root_node_back_pointer;
109
110
18.5k
  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
18.5k
}
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
18.5k
{
130
18.5k
  static char *function = "libpff_index_free";
131
132
18.5k
  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
18.5k
  if( *index != NULL )
144
18.5k
  {
145
18.5k
    memory_free(
146
18.5k
     *index );
147
148
18.5k
    *index = NULL;
149
18.5k
  }
150
18.5k
  return( 1 );
151
18.5k
}
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
1.43M
{
163
1.43M
  libpff_block_descriptor_t *existing_block_descriptor = NULL;
164
1.43M
  libpff_block_descriptor_t *new_block_descriptor      = NULL;
165
1.43M
  libpff_block_tree_node_t *leaf_block_tree_node       = NULL;
166
1.43M
  static char *function                                = "libpff_index_check_if_node_block_first_read";
167
1.43M
  int leaf_value_index                                 = 0;
168
1.43M
  int result                                           = 0;
169
170
1.43M
  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
1.43M
  if( libpff_block_descriptor_initialize(
182
1.43M
       &new_block_descriptor,
183
1.43M
       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
1.43M
  new_block_descriptor->identifier = identifier;
195
196
1.43M
  result = libpff_block_tree_insert_block_descriptor_by_offset(
197
1.43M
            node_block_tree,
198
1.43M
            node_offset,
199
1.43M
            new_block_descriptor,
200
1.43M
            &leaf_value_index,
201
1.43M
            &leaf_block_tree_node,
202
1.43M
            &existing_block_descriptor,
203
1.43M
            error );
204
205
1.43M
  if( result == -1 )
206
1.20k
  {
207
1.20k
    libcerror_error_set(
208
1.20k
     error,
209
1.20k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
210
1.20k
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
211
1.20k
     "%s: unable to insert block descriptor for index node at offset: %" PRIi64 " (0x%08" PRIx64 ") in node block tree.",
212
1.20k
     function,
213
1.20k
     node_offset,
214
1.20k
     node_offset );
215
216
1.20k
    goto on_error;
217
1.20k
  }
218
1.43M
  else if( result == 0 )
219
369
  {
220
369
    libcerror_error_set(
221
369
     error,
222
369
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
223
369
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
224
369
     "%s: invalid index node at offset: %" PRIi64 " (0x%08" PRIx64 ") value already exists.",
225
369
     function,
226
369
     node_offset,
227
369
     node_offset );
228
229
369
    goto on_error;
230
369
  }
231
1.43M
  new_block_descriptor = NULL;
232
233
1.43M
  return( 1 );
234
235
1.57k
on_error:
236
1.57k
  if( new_block_descriptor != NULL )
237
1.57k
  {
238
1.57k
    libpff_block_descriptor_free(
239
1.57k
     &new_block_descriptor,
240
1.57k
     NULL );
241
1.57k
  }
242
1.57k
  return( -1 );
243
1.43M
}
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
1.43M
{
260
1.43M
  libpff_index_node_t *index_node = NULL;
261
1.43M
  uint8_t *node_entry_data        = NULL;
262
1.43M
  static char *function           = "libpff_index_get_leaf_node_from_node_by_identifier";
263
1.43M
  uint64_t entry_identifier       = 0;
264
1.43M
  uint64_t sub_node_back_pointer  = 0;
265
1.43M
  uint64_t sub_node_offset        = 0;
266
1.43M
  uint16_t entry_index            = 0;
267
1.43M
  int result                      = 0;
268
269
1.43M
  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
1.43M
  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
1.43M
  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
1.43M
  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
1.43M
  if( libpff_index_check_if_node_block_first_read(
324
1.43M
       index,
325
1.43M
       node_block_tree,
326
1.43M
       node_offset,
327
1.43M
       identifier,
328
1.43M
       error ) != 1 )
329
1.57k
  {
330
1.57k
    libcerror_error_set(
331
1.57k
     error,
332
1.57k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
333
1.57k
     LIBCERROR_RUNTIME_ERROR_GENERIC,
334
1.57k
     "%s: unable to check if first read of index node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
335
1.57k
     function,
336
1.57k
     node_offset,
337
1.57k
     node_offset );
338
339
1.57k
    goto on_error;
340
1.57k
  }
341
1.43M
  if( libpff_index_node_initialize(
342
1.43M
       &index_node,
343
1.43M
       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
1.43M
  if( libpff_index_node_read_file_io_handle(
355
1.43M
       index_node,
356
1.43M
       file_io_handle,
357
1.43M
       node_offset,
358
1.43M
       io_handle->file_type,
359
1.43M
       error ) != 1 )
360
1.70k
  {
361
1.70k
    libcerror_error_set(
362
1.70k
     error,
363
1.70k
     LIBCERROR_ERROR_DOMAIN_IO,
364
1.70k
     LIBCERROR_IO_ERROR_READ_FAILED,
365
1.70k
     "%s: unable to read index node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
366
1.70k
     function,
367
1.70k
     node_offset,
368
1.70k
     node_offset );
369
370
1.70k
    goto on_error;
371
1.70k
  }
372
1.43M
  if( index->type != index_node->type )
373
432
  {
374
432
    libcerror_error_set(
375
432
     error,
376
432
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
377
432
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
378
432
     "%s: index type mismatch (index: 0x%02" PRIx8 ", node: 0x%02" PRIx8 ").",
379
432
     function,
380
432
     index->type,
381
432
     index_node->type );
382
383
    /* TODO error tollerance */
384
385
432
    goto on_error;
386
432
  }
387
1.43M
  if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF )
388
647k
  {
389
647k
    if( index_node->back_pointer != node_back_pointer )
390
797
    {
391
797
      libcerror_error_set(
392
797
       error,
393
797
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
394
797
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
395
797
       "%s: back pointer mismatch (index entry: %" PRIu64 ", node: %" PRIu64 ").",
396
797
       function,
397
797
       node_back_pointer,
398
797
       index_node->back_pointer );
399
400
      /* TODO error tollerance */
401
402
797
      goto on_error;
403
797
    }
404
647k
  }
405
1.42M
  for( entry_index = 0;
406
8.72M
       entry_index < index_node->number_of_entries;
407
7.29M
       entry_index++ )
408
8.41M
  {
409
8.41M
    if( libpff_index_node_get_entry_data(
410
8.41M
         index_node,
411
8.41M
         entry_index,
412
8.41M
         &node_entry_data,
413
8.41M
         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
8.41M
    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
8.41M
    if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
438
6.14M
    {
439
6.14M
      byte_stream_copy_to_uint32_little_endian(
440
6.14M
       ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->identifier,
441
6.14M
       entry_identifier );
442
6.14M
    }
443
2.27M
    else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
444
55.7k
          || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
445
2.27M
    {
446
2.27M
      byte_stream_copy_to_uint64_little_endian(
447
2.27M
       ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->identifier,
448
2.27M
       entry_identifier );
449
2.27M
    }
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
8.41M
    if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
464
5.83M
    {
465
5.83M
      entry_identifier &= 0xffffffffUL;
466
5.83M
    }
467
8.41M
    if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF )
468
4.07M
    {
469
4.07M
      if( ( entry_index == 0 )
470
3.43M
       || ( identifier >= entry_identifier ) )
471
3.77M
      {
472
3.77M
        if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
473
2.87M
        {
474
2.87M
          byte_stream_copy_to_uint32_little_endian(
475
2.87M
           ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->file_offset,
476
2.87M
           sub_node_offset );
477
478
2.87M
          byte_stream_copy_to_uint32_little_endian(
479
2.87M
           ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->back_pointer,
480
2.87M
           sub_node_back_pointer );
481
2.87M
        }
482
902k
        else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
483
9.19k
              || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
484
902k
        {
485
902k
          byte_stream_copy_to_uint64_little_endian(
486
902k
           ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->file_offset,
487
902k
           sub_node_offset );
488
489
902k
          byte_stream_copy_to_uint64_little_endian(
490
902k
           ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->back_pointer,
491
902k
           sub_node_back_pointer );
492
902k
        }
493
3.77M
      }
494
4.07M
    }
495
4.33M
    else if( identifier == entry_identifier )
496
168k
    {
497
168k
      *leaf_node             = index_node;
498
168k
      *leaf_node_entry_index = entry_index;
499
500
168k
      result = 1;
501
168k
    }
502
    /* A branch node contains the identifier of its first sub node
503
     */
504
8.41M
    if( identifier <= entry_identifier )
505
1.11M
    {
506
1.11M
      break;
507
1.11M
    }
508
8.41M
  }
509
1.42M
  if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF )
510
647k
  {
511
647k
    if( sub_node_offset > (uint64_t) INT64_MAX )
512
556
    {
513
556
      libcerror_error_set(
514
556
       error,
515
556
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
516
556
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
517
556
       "%s: invalid sub node offset value out of bounds.",
518
556
       function );
519
520
556
      goto on_error;
521
556
    }
522
646k
    result = libpff_index_get_leaf_node_from_node_by_identifier(
523
646k
        index,
524
646k
        io_handle,
525
646k
        file_io_handle,
526
646k
        node_block_tree,
527
646k
        sub_node_offset,
528
646k
        sub_node_back_pointer,
529
646k
        identifier,
530
646k
        leaf_node,
531
646k
        leaf_node_entry_index,
532
646k
        error );
533
534
646k
    if( result == -1 )
535
3.96k
    {
536
3.96k
      libcerror_error_set(
537
3.96k
       error,
538
3.96k
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
539
3.96k
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
540
3.96k
       "%s: unable to retrieve leaf node by identifier: 0x%08" PRIx64 " (%" PRIu64 ") from node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
541
3.96k
       function,
542
3.96k
       identifier,
543
3.96k
       identifier,
544
3.96k
       node_offset,
545
3.96k
       node_offset );
546
547
3.96k
      goto on_error;
548
3.96k
    }
549
646k
  }
550
1.42M
  if( ( index_node != NULL )
551
1.42M
   && ( index_node != *leaf_node ) )
552
1.25M
  {
553
1.25M
    if( libpff_index_node_free(
554
1.25M
         &index_node,
555
1.25M
         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
1.25M
  }
567
1.42M
  return( result );
568
569
9.03k
on_error:
570
9.03k
  if( index_node != NULL )
571
7.45k
  {
572
7.45k
    libpff_index_node_free(
573
7.45k
     &index_node,
574
7.45k
     NULL );
575
7.45k
  }
576
9.03k
  return( -1 );
577
1.42M
}
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
787k
{
590
787k
  libpff_block_tree_t *node_block_tree   = NULL;
591
787k
  libpff_index_node_t *leaf_node         = NULL;
592
787k
  libpff_index_value_t *safe_index_value = NULL;
593
787k
  uint8_t *node_entry_data               = NULL;
594
787k
  static char *function                  = "libpff_index_get_value_by_identifier";
595
787k
  size_t index_node_size                 = 0;
596
787k
  uint16_t leaf_node_entry_index         = 0;
597
787k
  int result                             = 0;
598
599
787k
  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
787k
  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
787k
  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
787k
  if( ( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
633
160k
   || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) )
634
773k
  {
635
773k
    index_node_size = 512;
636
773k
  }
637
13.2k
  else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
638
13.2k
  {
639
13.2k
    index_node_size = 4096;
640
13.2k
  }
641
787k
  if( libpff_block_tree_initialize(
642
787k
       &node_block_tree,
643
787k
       io_handle->file_size,
644
787k
       index_node_size,
645
787k
       error ) != 1 )
646
40
  {
647
40
    libcerror_error_set(
648
40
     error,
649
40
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
650
40
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
651
40
     "%s: unable to create index node block tree.",
652
40
     function );
653
654
40
    goto on_error;
655
40
  }
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
787k
  result = libpff_index_get_leaf_node_from_node_by_identifier(
667
787k
      index,
668
787k
      io_handle,
669
787k
      file_io_handle,
670
787k
      node_block_tree,
671
787k
      index->root_node_offset,
672
787k
      index->root_node_back_pointer,
673
787k
      identifier,
674
787k
      &leaf_node,
675
787k
      &leaf_node_entry_index,
676
787k
      error );
677
678
787k
  if( result == -1 )
679
5.06k
  {
680
5.06k
    libcerror_error_set(
681
5.06k
     error,
682
5.06k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
683
5.06k
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
684
5.06k
     "%s: unable to retrieve leaf node by identifier: 0x%08" PRIx64 " (%" PRIu64 ") from root node.",
685
5.06k
     function,
686
5.06k
     identifier,
687
5.06k
     identifier );
688
689
5.06k
    goto on_error;
690
5.06k
  }
691
782k
  else if( result != 0 )
692
168k
  {
693
168k
    if( libpff_index_node_get_entry_data(
694
168k
         leaf_node,
695
168k
         leaf_node_entry_index,
696
168k
         &node_entry_data,
697
168k
         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
168k
    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
168k
    if( libpff_index_value_initialize(
722
168k
         &safe_index_value,
723
168k
         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
168k
    if( libpff_index_value_read_data(
735
168k
         safe_index_value,
736
168k
         io_handle,
737
168k
         index->type,
738
168k
         node_entry_data,
739
168k
         (size_t) leaf_node->entry_size,
740
168k
         error ) != 1 )
741
877
    {
742
877
      libcerror_error_set(
743
877
       error,
744
877
       LIBCERROR_ERROR_DOMAIN_IO,
745
877
       LIBCERROR_IO_ERROR_READ_FAILED,
746
877
       "%s: unable to read index value.",
747
877
       function );
748
749
877
      goto on_error;
750
877
    }
751
167k
    if( libpff_index_node_free(
752
167k
         &leaf_node,
753
167k
         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
167k
  }
765
781k
  if( libpff_block_tree_free(
766
781k
       &node_block_tree,
767
781k
       (int (*)(intptr_t **, libcerror_error_t **)) &libpff_block_descriptor_free,
768
781k
       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
781k
  *index_value = safe_index_value;
780
781
781k
  return( result );
782
783
5.98k
on_error:
784
5.98k
  if( safe_index_value != NULL )
785
877
  {
786
877
    libpff_index_value_free(
787
877
     &safe_index_value,
788
877
     NULL );
789
877
  }
790
5.98k
  if( leaf_node != NULL )
791
877
  {
792
877
    libpff_index_node_free(
793
877
     &leaf_node,
794
877
     NULL );
795
877
  }
796
5.98k
  if( node_block_tree != NULL )
797
5.94k
  {
798
5.94k
    libpff_block_tree_free(
799
5.94k
     &node_block_tree,
800
5.94k
     (int (*)(intptr_t **, libcerror_error_t **)) &libpff_block_descriptor_free,
801
     NULL );
802
5.94k
  }
803
5.98k
  return( -1 );
804
781k
}
805