Coverage Report

Created: 2025-06-24 07:14

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