Coverage Report

Created: 2026-05-30 07:13

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-2026, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <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
19.8k
{
54
19.8k
  static char *function = "libpff_index_initialize";
55
56
19.8k
  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
19.8k
  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
19.8k
  *index = memory_allocate_structure(
79
19.8k
            libpff_index_t );
80
81
19.8k
  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
19.8k
  if( memory_set(
93
19.8k
       *index,
94
19.8k
       0,
95
19.8k
       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
19.8k
  ( *index )->type                   = index_type;
107
19.8k
  ( *index )->root_node_offset       = root_node_offset;
108
19.8k
  ( *index )->root_node_back_pointer = root_node_back_pointer;
109
110
19.8k
  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
19.8k
}
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
19.8k
{
130
19.8k
  static char *function = "libpff_index_free";
131
132
19.8k
  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
19.8k
  if( *index != NULL )
144
19.8k
  {
145
19.8k
    memory_free(
146
19.8k
     *index );
147
148
19.8k
    *index = NULL;
149
19.8k
  }
150
19.8k
  return( 1 );
151
19.8k
}
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.63M
{
163
1.63M
  libpff_block_descriptor_t *existing_block_descriptor = NULL;
164
1.63M
  libpff_block_descriptor_t *new_block_descriptor      = NULL;
165
1.63M
  libpff_block_tree_node_t *leaf_block_tree_node       = NULL;
166
1.63M
  static char *function                                = "libpff_index_check_if_node_block_first_read";
167
1.63M
  int leaf_value_index                                 = 0;
168
1.63M
  int result                                           = 0;
169
170
1.63M
  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.63M
  if( libpff_block_descriptor_initialize(
182
1.63M
       &new_block_descriptor,
183
1.63M
       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.63M
  new_block_descriptor->identifier = identifier;
195
196
1.63M
  result = libpff_block_tree_insert_block_descriptor_by_offset(
197
1.63M
            node_block_tree,
198
1.63M
            node_offset,
199
1.63M
            new_block_descriptor,
200
1.63M
            &leaf_value_index,
201
1.63M
            &leaf_block_tree_node,
202
1.63M
            &existing_block_descriptor,
203
1.63M
            error );
204
205
1.63M
  if( result == -1 )
206
1.27k
  {
207
1.27k
    libcerror_error_set(
208
1.27k
     error,
209
1.27k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
210
1.27k
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
211
1.27k
     "%s: unable to insert block descriptor for index node at offset: %" PRIi64 " (0x%08" PRIx64 ") in node block tree.",
212
1.27k
     function,
213
1.27k
     node_offset,
214
1.27k
     node_offset );
215
216
1.27k
    goto on_error;
217
1.27k
  }
218
1.63M
  else if( result == 0 )
219
393
  {
220
393
    libcerror_error_set(
221
393
     error,
222
393
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
223
393
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
224
393
     "%s: invalid index node at offset: %" PRIi64 " (0x%08" PRIx64 ") value already exists.",
225
393
     function,
226
393
     node_offset,
227
393
     node_offset );
228
229
393
    goto on_error;
230
393
  }
231
1.63M
  new_block_descriptor = NULL;
232
233
1.63M
  return( 1 );
234
235
1.66k
on_error:
236
1.66k
  if( new_block_descriptor != NULL )
237
1.66k
  {
238
1.66k
    libpff_block_descriptor_free(
239
1.66k
     &new_block_descriptor,
240
1.66k
     NULL );
241
1.66k
  }
242
1.66k
  return( -1 );
243
1.63M
}
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.63M
{
260
1.63M
  libpff_index_node_t *index_node = NULL;
261
1.63M
  uint8_t *node_entry_data        = NULL;
262
1.63M
  static char *function           = "libpff_index_get_leaf_node_from_node_by_identifier";
263
1.63M
  uint64_t entry_identifier       = 0;
264
1.63M
  uint64_t sub_node_back_pointer  = 0;
265
1.63M
  uint64_t sub_node_offset        = 0;
266
1.63M
  uint16_t entry_index            = 0;
267
1.63M
  int result                      = 0;
268
269
1.63M
  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.63M
  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.63M
  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.63M
  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.63M
  if( libpff_index_check_if_node_block_first_read(
324
1.63M
       index,
325
1.63M
       node_block_tree,
326
1.63M
       node_offset,
327
1.63M
       identifier,
328
1.63M
       error ) != 1 )
329
1.66k
  {
330
1.66k
    libcerror_error_set(
331
1.66k
     error,
332
1.66k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
333
1.66k
     LIBCERROR_RUNTIME_ERROR_GENERIC,
334
1.66k
     "%s: unable to check if first read of index node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
335
1.66k
     function,
336
1.66k
     node_offset,
337
1.66k
     node_offset );
338
339
1.66k
    goto on_error;
340
1.66k
  }
341
1.63M
  if( libpff_index_node_initialize(
342
1.63M
       &index_node,
343
1.63M
       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.63M
  if( libpff_index_node_read_file_io_handle(
355
1.63M
       index_node,
356
1.63M
       file_io_handle,
357
1.63M
       node_offset,
358
1.63M
       io_handle->file_type,
359
1.63M
       error ) != 1 )
360
1.76k
  {
361
1.76k
    libcerror_error_set(
362
1.76k
     error,
363
1.76k
     LIBCERROR_ERROR_DOMAIN_IO,
364
1.76k
     LIBCERROR_IO_ERROR_READ_FAILED,
365
1.76k
     "%s: unable to read index node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
366
1.76k
     function,
367
1.76k
     node_offset,
368
1.76k
     node_offset );
369
370
1.76k
    goto on_error;
371
1.76k
  }
372
1.63M
  if( index->type != index_node->type )
373
567
  {
374
567
    libcerror_error_set(
375
567
     error,
376
567
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
377
567
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
378
567
     "%s: index type mismatch (index: 0x%02" PRIx8 ", node: 0x%02" PRIx8 ").",
379
567
     function,
380
567
     index->type,
381
567
     index_node->type );
382
383
    /* TODO error tollerance */
384
385
567
    goto on_error;
386
567
  }
387
1.63M
  if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF )
388
742k
  {
389
742k
    if( index_node->back_pointer != node_back_pointer )
390
833
    {
391
833
      libcerror_error_set(
392
833
       error,
393
833
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
394
833
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
395
833
       "%s: back pointer mismatch (index entry: %" PRIu64 ", node: %" PRIu64 ").",
396
833
       function,
397
833
       node_back_pointer,
398
833
       index_node->back_pointer );
399
400
      /* TODO error tollerance */
401
402
833
      goto on_error;
403
833
    }
404
742k
  }
405
1.63M
  for( entry_index = 0;
406
11.1M
       entry_index < index_node->number_of_entries;
407
9.48M
       entry_index++ )
408
10.7M
  {
409
10.7M
    if( libpff_index_node_get_entry_data(
410
10.7M
         index_node,
411
10.7M
         entry_index,
412
10.7M
         &node_entry_data,
413
10.7M
         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
10.7M
    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
10.7M
    if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
438
7.24M
    {
439
7.24M
      byte_stream_copy_to_uint32_little_endian(
440
7.24M
       ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->identifier,
441
7.24M
       entry_identifier );
442
7.24M
    }
443
3.52M
    else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
444
99.5k
          || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
445
3.52M
    {
446
3.52M
      byte_stream_copy_to_uint64_little_endian(
447
3.52M
       ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->identifier,
448
3.52M
       entry_identifier );
449
3.52M
    }
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
10.7M
    if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
464
6.81M
    {
465
6.81M
      entry_identifier &= 0xffffffffUL;
466
6.81M
    }
467
10.7M
    if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF )
468
5.25M
    {
469
5.25M
      if( ( entry_index == 0 )
470
4.51M
       || ( identifier >= entry_identifier ) )
471
4.92M
      {
472
4.92M
        if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
473
3.54M
        {
474
3.54M
          byte_stream_copy_to_uint32_little_endian(
475
3.54M
           ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->file_offset,
476
3.54M
           sub_node_offset );
477
478
3.54M
          byte_stream_copy_to_uint32_little_endian(
479
3.54M
           ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->back_pointer,
480
3.54M
           sub_node_back_pointer );
481
3.54M
        }
482
1.38M
        else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
483
49.6k
              || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
484
1.38M
        {
485
1.38M
          byte_stream_copy_to_uint64_little_endian(
486
1.38M
           ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->file_offset,
487
1.38M
           sub_node_offset );
488
489
1.38M
          byte_stream_copy_to_uint64_little_endian(
490
1.38M
           ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->back_pointer,
491
1.38M
           sub_node_back_pointer );
492
1.38M
        }
493
4.92M
      }
494
5.25M
    }
495
5.51M
    else if( identifier == entry_identifier )
496
240k
    {
497
240k
      *leaf_node             = index_node;
498
240k
      *leaf_node_entry_index = entry_index;
499
500
240k
      result = 1;
501
240k
    }
502
    /* A branch node contains the identifier of its first sub node
503
     */
504
10.7M
    if( identifier <= entry_identifier )
505
1.28M
    {
506
1.28M
      break;
507
1.28M
    }
508
10.7M
  }
509
1.63M
  if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF )
510
741k
  {
511
741k
    if( sub_node_offset > (uint64_t) INT64_MAX )
512
670
    {
513
670
      libcerror_error_set(
514
670
       error,
515
670
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
516
670
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
517
670
       "%s: invalid sub node offset value out of bounds.",
518
670
       function );
519
520
670
      goto on_error;
521
670
    }
522
740k
    result = libpff_index_get_leaf_node_from_node_by_identifier(
523
740k
        index,
524
740k
        io_handle,
525
740k
        file_io_handle,
526
740k
        node_block_tree,
527
740k
        sub_node_offset,
528
740k
        sub_node_back_pointer,
529
740k
        identifier,
530
740k
        leaf_node,
531
740k
        leaf_node_entry_index,
532
740k
        error );
533
534
740k
    if( result == -1 )
535
4.28k
    {
536
4.28k
      libcerror_error_set(
537
4.28k
       error,
538
4.28k
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
539
4.28k
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
540
4.28k
       "%s: unable to retrieve leaf node by identifier: 0x%08" PRIx64 " (%" PRIu64 ") from node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
541
4.28k
       function,
542
4.28k
       identifier,
543
4.28k
       identifier,
544
4.28k
       node_offset,
545
4.28k
       node_offset );
546
547
4.28k
      goto on_error;
548
4.28k
    }
549
740k
  }
550
1.62M
  if( ( index_node != NULL )
551
1.62M
   && ( index_node != *leaf_node ) )
552
1.38M
  {
553
1.38M
    if( libpff_index_node_free(
554
1.38M
         &index_node,
555
1.38M
         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.38M
  }
567
1.62M
  return( result );
568
569
9.77k
on_error:
570
9.77k
  if( index_node != NULL )
571
8.11k
  {
572
8.11k
    libpff_index_node_free(
573
8.11k
     &index_node,
574
8.11k
     NULL );
575
8.11k
  }
576
9.77k
  return( -1 );
577
1.62M
}
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
896k
{
590
896k
  libpff_block_tree_t *node_block_tree   = NULL;
591
896k
  libpff_index_node_t *leaf_node         = NULL;
592
896k
  libpff_index_value_t *safe_index_value = NULL;
593
896k
  uint8_t *node_entry_data               = NULL;
594
896k
  static char *function                  = "libpff_index_get_value_by_identifier";
595
896k
  size_t index_node_size                 = 0;
596
896k
  uint16_t leaf_node_entry_index         = 0;
597
896k
  int result                             = 0;
598
599
896k
  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
896k
  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
896k
  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
896k
  if( ( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
633
226k
   || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) )
634
881k
  {
635
881k
    index_node_size = 512;
636
881k
  }
637
15.4k
  else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
638
15.4k
  {
639
15.4k
    index_node_size = 4096;
640
15.4k
  }
641
896k
  if( libpff_block_tree_initialize(
642
896k
       &node_block_tree,
643
896k
       io_handle->file_size,
644
896k
       index_node_size,
645
896k
       error ) != 1 )
646
43
  {
647
43
    libcerror_error_set(
648
43
     error,
649
43
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
650
43
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
651
43
     "%s: unable to create index node block tree.",
652
43
     function );
653
654
43
    goto on_error;
655
43
  }
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
896k
  result = libpff_index_get_leaf_node_from_node_by_identifier(
667
896k
      index,
668
896k
      io_handle,
669
896k
      file_io_handle,
670
896k
      node_block_tree,
671
896k
      index->root_node_offset,
672
896k
      index->root_node_back_pointer,
673
896k
      identifier,
674
896k
      &leaf_node,
675
896k
      &leaf_node_entry_index,
676
896k
      error );
677
678
896k
  if( result == -1 )
679
5.49k
  {
680
5.49k
    libcerror_error_set(
681
5.49k
     error,
682
5.49k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
683
5.49k
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
684
5.49k
     "%s: unable to retrieve leaf node by identifier: 0x%08" PRIx64 " (%" PRIu64 ") from root node.",
685
5.49k
     function,
686
5.49k
     identifier,
687
5.49k
     identifier );
688
689
5.49k
    goto on_error;
690
5.49k
  }
691
891k
  else if( result != 0 )
692
240k
  {
693
240k
    if( libpff_index_node_get_entry_data(
694
240k
         leaf_node,
695
240k
         leaf_node_entry_index,
696
240k
         &node_entry_data,
697
240k
         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
240k
    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
240k
    if( libpff_index_value_initialize(
722
240k
         &safe_index_value,
723
240k
         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
240k
    if( libpff_index_value_read_data(
735
240k
         safe_index_value,
736
240k
         io_handle,
737
240k
         index->type,
738
240k
         node_entry_data,
739
240k
         (size_t) leaf_node->entry_size,
740
240k
         error ) != 1 )
741
1.04k
    {
742
1.04k
      libcerror_error_set(
743
1.04k
       error,
744
1.04k
       LIBCERROR_ERROR_DOMAIN_IO,
745
1.04k
       LIBCERROR_IO_ERROR_READ_FAILED,
746
1.04k
       "%s: unable to read index value.",
747
1.04k
       function );
748
749
1.04k
      goto on_error;
750
1.04k
    }
751
239k
    if( libpff_index_node_free(
752
239k
         &leaf_node,
753
239k
         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
239k
  }
765
889k
  if( libpff_block_tree_free(
766
889k
       &node_block_tree,
767
889k
       (int (*)(intptr_t **, libcerror_error_t **)) &libpff_block_descriptor_free,
768
889k
       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
889k
  *index_value = safe_index_value;
780
781
889k
  return( result );
782
783
6.58k
on_error:
784
6.58k
  if( safe_index_value != NULL )
785
1.04k
  {
786
1.04k
    libpff_index_value_free(
787
1.04k
     &safe_index_value,
788
1.04k
     NULL );
789
1.04k
  }
790
6.58k
  if( leaf_node != NULL )
791
1.04k
  {
792
1.04k
    libpff_index_node_free(
793
1.04k
     &leaf_node,
794
1.04k
     NULL );
795
1.04k
  }
796
6.58k
  if( node_block_tree != NULL )
797
6.54k
  {
798
6.54k
    libpff_block_tree_free(
799
6.54k
     &node_block_tree,
800
6.54k
     (int (*)(intptr_t **, libcerror_error_t **)) &libpff_block_descriptor_free,
801
     NULL );
802
6.54k
  }
803
6.58k
  return( -1 );
804
889k
}
805