Coverage Report

Created: 2025-06-13 07:21

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