Coverage Report

Created: 2024-02-25 07:20

/src/libesedb/libesedb/libesedb_page_tree.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Page tree functions
3
 *
4
 * Copyright (C) 2009-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 "libesedb_block_descriptor.h"
28
#include "libesedb_block_tree.h"
29
#include "libesedb_block_tree_node.h"
30
#include "libesedb_data_definition.h"
31
#include "libesedb_debug.h"
32
#include "libesedb_definitions.h"
33
#include "libesedb_io_handle.h"
34
#include "libesedb_leaf_page_descriptor.h"
35
#include "libesedb_libbfio.h"
36
#include "libesedb_libcerror.h"
37
#include "libesedb_libcnotify.h"
38
#include "libesedb_libfcache.h"
39
#include "libesedb_libfdata.h"
40
#include "libesedb_page.h"
41
#include "libesedb_page_tree.h"
42
#include "libesedb_page_tree_key.h"
43
#include "libesedb_page_tree_value.h"
44
#include "libesedb_root_page_header.h"
45
#include "libesedb_space_tree.h"
46
#include "libesedb_table_definition.h"
47
#include "libesedb_unused.h"
48
49
#include "esedb_page_values.h"
50
51
/* Creates a page tree
52
 * Make sure the value page_tree is referencing, is set to NULL
53
 * Returns 1 if successful or -1 on error
54
 */
55
int libesedb_page_tree_initialize(
56
     libesedb_page_tree_t **page_tree,
57
     libesedb_io_handle_t *io_handle,
58
     libfdata_vector_t *pages_vector,
59
     libfcache_cache_t *pages_cache,
60
     uint32_t object_identifier,
61
     uint32_t root_page_number,
62
     libesedb_table_definition_t *table_definition,
63
     libesedb_table_definition_t *template_table_definition,
64
     libcerror_error_t **error )
65
9.05k
{
66
9.05k
  static char *function = "libesedb_page_tree_initialize";
67
68
9.05k
  if( page_tree == NULL )
69
0
  {
70
0
    libcerror_error_set(
71
0
     error,
72
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
73
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
74
0
     "%s: invalid page tree.",
75
0
     function );
76
77
0
    return( -1 );
78
0
  }
79
9.05k
  if( *page_tree != NULL )
80
0
  {
81
0
    libcerror_error_set(
82
0
     error,
83
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
84
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
85
0
     "%s: invalid page tree value already set.",
86
0
     function );
87
88
0
    return( -1 );
89
0
  }
90
9.05k
  if( io_handle == NULL )
91
0
  {
92
0
    libcerror_error_set(
93
0
     error,
94
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
95
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
96
0
     "%s: invalid IO handle.",
97
0
     function );
98
99
0
    return( -1 );
100
0
  }
101
9.05k
#if ( SIZEOF_INT <= 4 )
102
9.05k
  if( ( root_page_number < 1 )
103
9.05k
   || ( root_page_number > (uint32_t) INT_MAX ) )
104
#else
105
  if( ( root_page_number < 1 )
106
   || ( (int) root_page_number > INT_MAX ) )
107
#endif
108
103
  {
109
103
    libcerror_error_set(
110
103
     error,
111
103
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
112
103
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
113
103
     "%s: invalid root page number value out of bounds.",
114
103
     function );
115
116
103
    return( -1 );
117
103
  }
118
8.95k
  *page_tree = memory_allocate_structure(
119
8.95k
                libesedb_page_tree_t );
120
121
8.95k
  if( *page_tree == NULL )
122
0
  {
123
0
    libcerror_error_set(
124
0
     error,
125
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
126
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
127
0
     "%s: unable to create page tree.",
128
0
     function );
129
130
0
    goto on_error;
131
0
  }
132
8.95k
  if( memory_set(
133
8.95k
       *page_tree,
134
8.95k
       0,
135
8.95k
       sizeof( libesedb_page_tree_t ) ) == NULL )
136
0
  {
137
0
    libcerror_error_set(
138
0
     error,
139
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
140
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
141
0
     "%s: unable to clear page tree.",
142
0
     function );
143
144
0
    memory_free(
145
0
     *page_tree );
146
147
0
    *page_tree = NULL;
148
149
0
    return( -1 );
150
0
  }
151
8.95k
  if( libesedb_block_tree_initialize(
152
8.95k
       &( ( *page_tree )->page_block_tree ),
153
8.95k
       io_handle->file_size,
154
8.95k
       io_handle->page_size,
155
8.95k
       error ) != 1 )
156
0
  {
157
0
    libcerror_error_set(
158
0
     error,
159
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
160
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
161
0
     "%s: unable to create page block tree.",
162
0
     function );
163
164
0
    goto on_error;
165
0
  }
166
8.95k
  if( libcdata_btree_initialize(
167
8.95k
       &( ( *page_tree )->leaf_page_descriptors_tree ),
168
8.95k
       257,
169
8.95k
       error ) != 1 )
170
0
  {
171
0
    libcerror_error_set(
172
0
     error,
173
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
174
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
175
0
     "%s: unable to create leaf page descriptors B-tree.",
176
0
     function );
177
178
0
    goto on_error;
179
0
  }
180
8.95k
  ( *page_tree )->io_handle                 = io_handle;
181
8.95k
  ( *page_tree )->pages_vector              = pages_vector;
182
8.95k
  ( *page_tree )->pages_cache               = pages_cache;
183
8.95k
  ( *page_tree )->object_identifier         = object_identifier;
184
8.95k
  ( *page_tree )->root_page_number          = root_page_number;
185
8.95k
  ( *page_tree )->table_definition          = table_definition;
186
8.95k
  ( *page_tree )->template_table_definition = template_table_definition;
187
8.95k
  ( *page_tree )->number_of_leaf_values     = -1;
188
189
8.95k
  return( 1 );
190
191
0
on_error:
192
0
  if( *page_tree != NULL )
193
0
  {
194
0
    if( ( *page_tree )->page_block_tree != NULL )
195
0
    {
196
0
      libesedb_block_tree_free(
197
0
       &( ( *page_tree )->page_block_tree ),
198
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_block_descriptor_free,
199
0
       NULL );
200
0
    }
201
0
    memory_free(
202
0
     *page_tree );
203
204
0
    *page_tree = NULL;
205
0
  }
206
0
  return( -1 );
207
8.95k
}
208
209
/* Frees a page tree
210
 * Returns 1 if successful or -1 on error
211
 */
212
int libesedb_page_tree_free(
213
     libesedb_page_tree_t **page_tree,
214
     libcerror_error_t **error )
215
8.95k
{
216
8.95k
  static char *function = "libesedb_page_tree_free";
217
8.95k
  int result            = 1;
218
219
8.95k
  if( page_tree == NULL )
220
0
  {
221
0
    libcerror_error_set(
222
0
     error,
223
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
224
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
225
0
     "%s: invalid page tree.",
226
0
     function );
227
228
0
    return( -1 );
229
0
  }
230
8.95k
  if( *page_tree != NULL )
231
8.95k
  {
232
    /* The io_handle, pages_vector, pages_cache, table_definition and template_table_definition references
233
     * are freed elsewhere
234
     */
235
8.95k
    if( ( *page_tree )->root_page_header != NULL )
236
0
    {
237
0
      if( libesedb_root_page_header_free(
238
0
           &( ( *page_tree )->root_page_header ),
239
0
           error ) != 1 )
240
0
      {
241
0
        libcerror_error_set(
242
0
         error,
243
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
244
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
245
0
         "%s: unable to free root page header.",
246
0
         function );
247
248
0
        result = -1;
249
0
      }
250
0
    }
251
8.95k
    if( libcdata_btree_free(
252
8.95k
         &( ( *page_tree )->leaf_page_descriptors_tree ),
253
8.95k
         (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_leaf_page_descriptor_free,
254
8.95k
         error ) != 1 )
255
0
    {
256
0
      libcerror_error_set(
257
0
       error,
258
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
259
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
260
0
       "%s: unable to free leaf page descriptors B-tree.",
261
0
       function );
262
263
0
      result = -1;
264
0
    }
265
8.95k
    if( libesedb_block_tree_free(
266
8.95k
         &( ( *page_tree )->page_block_tree ),
267
8.95k
         (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_block_descriptor_free,
268
8.95k
         error ) != 1 )
269
0
    {
270
0
      libcerror_error_set(
271
0
       error,
272
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
273
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
274
0
       "%s: unable to free page block tree.",
275
0
       function );
276
277
0
      result = -1;
278
0
    }
279
8.95k
    memory_free(
280
8.95k
     *page_tree );
281
282
8.95k
    *page_tree = NULL;
283
8.95k
  }
284
8.95k
  return( result );
285
8.95k
}
286
287
/* Checks if this is the first time the page block is being read
288
 * Returns 1 if successful or -1 on error
289
 */
290
int libesedb_page_tree_check_if_page_block_first_read(
291
     libesedb_page_tree_t *page_tree,
292
     libesedb_block_tree_t *page_block_tree,
293
     uint32_t page_number,
294
     off64_t page_offset,
295
     libcerror_error_t **error )
296
13.1k
{
297
13.1k
  libesedb_block_descriptor_t *existing_block_descriptor = NULL;
298
13.1k
  libesedb_block_descriptor_t *new_block_descriptor      = NULL;
299
13.1k
  libesedb_block_tree_node_t *leaf_block_tree_node       = NULL;
300
13.1k
  static char *function                                  = "libesedb_page_tree_check_if_page_block_first_read";
301
13.1k
  int leaf_value_index                                   = 0;
302
13.1k
  int result                                             = 0;
303
304
13.1k
  if( page_tree == NULL )
305
0
  {
306
0
    libcerror_error_set(
307
0
     error,
308
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
309
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
310
0
     "%s: invalid page tree.",
311
0
     function );
312
313
0
    return( -1 );
314
0
  }
315
13.1k
  if( libesedb_block_descriptor_initialize(
316
13.1k
       &new_block_descriptor,
317
13.1k
       error ) != 1 )
318
0
  {
319
0
    libcerror_error_set(
320
0
     error,
321
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
322
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
323
0
     "%s: unable to create block descriptor.",
324
0
     function );
325
326
0
    goto on_error;
327
0
  }
328
13.1k
  new_block_descriptor->page_number = page_number;
329
330
13.1k
  result = libesedb_block_tree_insert_block_descriptor_by_offset(
331
13.1k
            page_block_tree,
332
13.1k
            page_offset,
333
13.1k
            new_block_descriptor,
334
13.1k
            &leaf_value_index,
335
13.1k
            &leaf_block_tree_node,
336
13.1k
            &existing_block_descriptor,
337
13.1k
            error );
338
339
13.1k
  if( result == -1 )
340
455
  {
341
455
    libcerror_error_set(
342
455
     error,
343
455
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
344
455
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
345
455
     "%s: unable to insert block descriptor in page block tree.",
346
455
     function );
347
348
455
    goto on_error;
349
455
  }
350
12.7k
  else if( result == 0 )
351
15
  {
352
15
    libcerror_error_set(
353
15
     error,
354
15
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
355
15
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
356
15
     "%s: invalid page number: %" PRIu32 " value already exists.",
357
15
     function,
358
15
     page_number );
359
360
15
    goto on_error;
361
15
  }
362
12.7k
  new_block_descriptor = NULL;
363
364
12.7k
  return( 1 );
365
366
470
on_error:
367
470
  if( new_block_descriptor != NULL )
368
470
  {
369
470
    libesedb_block_descriptor_free(
370
470
     &new_block_descriptor,
371
470
     NULL );
372
470
  }
373
470
  return( -1 );
374
13.1k
}
375
376
/* Reads the root page header
377
 * Returns 1 if successful or -1 on error
378
 */
379
int libesedb_page_tree_read_root_page_header(
380
     libesedb_page_tree_t *page_tree,
381
     libesedb_page_t *root_page,
382
     libcerror_error_t **error )
383
0
{
384
0
  libesedb_page_value_t *page_value = NULL;
385
0
  static char *function             = "libesedb_page_tree_read_root_page_header";
386
0
  uint16_t number_of_page_values    = 0;
387
388
0
  if( page_tree == NULL )
389
0
  {
390
0
    libcerror_error_set(
391
0
     error,
392
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
393
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
394
0
     "%s: invalid page tree.",
395
0
     function );
396
397
0
    return( -1 );
398
0
  }
399
0
  if( libesedb_page_get_number_of_values(
400
0
       root_page,
401
0
       &number_of_page_values,
402
0
       error ) != 1 )
403
0
  {
404
0
    libcerror_error_set(
405
0
     error,
406
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
407
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
408
0
     "%s: unable to retrieve number of page values.",
409
0
     function );
410
411
0
    goto on_error;
412
0
  }
413
0
  if( number_of_page_values > 0 )
414
0
  {
415
0
    if( libesedb_page_get_value_by_index(
416
0
         root_page,
417
0
         0,
418
0
         &page_value,
419
0
         error ) != 1 )
420
0
    {
421
0
      libcerror_error_set(
422
0
       error,
423
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
424
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
425
0
       "%s: unable to retrieve root page value: 0.",
426
0
       function );
427
428
0
      goto on_error;
429
0
    }
430
0
    if( page_value == NULL )
431
0
    {
432
0
      libcerror_error_set(
433
0
       error,
434
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
435
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
436
0
       "%s: missing page value.",
437
0
       function );
438
439
0
      goto on_error;
440
0
    }
441
0
    if( libesedb_root_page_header_initialize(
442
0
         &( page_tree->root_page_header ),
443
0
         error ) != 1 )
444
0
    {
445
0
      libcerror_error_set(
446
0
       error,
447
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
448
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
449
0
       "%s: unable to create root page header.",
450
0
       function );
451
452
0
      goto on_error;
453
0
    }
454
0
    if( libesedb_root_page_header_read_data(
455
0
         page_tree->root_page_header,
456
0
         page_value->data,
457
0
         (size_t) page_value->size,
458
0
         error ) != 1 )
459
0
    {
460
0
      libcerror_error_set(
461
0
       error,
462
0
       LIBCERROR_ERROR_DOMAIN_IO,
463
0
       LIBCERROR_IO_ERROR_READ_FAILED,
464
0
       "%s: unable to read root page header.",
465
0
       function );
466
467
0
      goto on_error;
468
0
    }
469
0
  }
470
0
  return( 1 );
471
472
0
on_error:
473
0
  if( page_tree->root_page_header != NULL )
474
0
  {
475
0
    libesedb_root_page_header_free(
476
0
     &( page_tree->root_page_header ),
477
0
     NULL );
478
0
  }
479
0
  return( -1 );
480
0
}
481
482
/* Reads the space page trees
483
 * Returns 1 if successful or -1 on error
484
 */
485
int libesedb_page_tree_read_space_trees(
486
     libesedb_page_tree_t *page_tree,
487
     libbfio_handle_t *file_io_handle,
488
     libcerror_error_t **error )
489
0
{
490
0
  libesedb_space_tree_t *space_tree = NULL;
491
0
  static char *function             = "libesedb_page_tree_read_space_trees";
492
493
0
  if( page_tree == NULL )
494
0
  {
495
0
    libcerror_error_set(
496
0
     error,
497
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
498
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
499
0
     "%s: invalid page tree.",
500
0
     function );
501
502
0
    return( -1 );
503
0
  }
504
0
  if( page_tree->root_page_header == NULL )
505
0
  {
506
0
    libcerror_error_set(
507
0
     error,
508
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
509
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
510
0
     "%s: invalid page tree - missing root page heder.",
511
0
     function );
512
513
0
    return( -1 );
514
0
  }
515
  /* Read the space tree pages
516
   */
517
0
  if( page_tree->root_page_header->extent_space > 0 )
518
0
  {
519
0
    if( page_tree->root_page_header->space_tree_page_number >= 0xff000000UL )
520
0
    {
521
0
      libcerror_error_set(
522
0
       error,
523
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
524
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
525
0
       "%s: unsupported space tree page number.",
526
0
       function,
527
0
       page_tree->root_page_header->space_tree_page_number );
528
529
0
      goto on_error;
530
0
    }
531
0
    if( page_tree->root_page_header->space_tree_page_number > 0 )
532
0
    {
533
      /* Read the owned pages space tree page
534
       */
535
0
      if( libesedb_space_tree_initialize(
536
0
           &space_tree,
537
0
           page_tree->io_handle,
538
0
           page_tree->object_identifier,
539
0
           page_tree->root_page_header->space_tree_page_number,
540
0
           page_tree->pages_vector,
541
0
           page_tree->pages_cache,
542
0
           error ) != 1 )
543
0
      {
544
0
        libcerror_error_set(
545
0
         error,
546
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
547
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
548
0
         "%s: unable to create owned pages space tree.",
549
0
         function );
550
551
0
        goto on_error;
552
0
      }
553
0
      if( libesedb_space_tree_read_file_io_handle(
554
0
           space_tree,
555
0
           file_io_handle,
556
0
           error ) != 1 )
557
0
      {
558
0
        libcerror_error_set(
559
0
         error,
560
0
         LIBCERROR_ERROR_DOMAIN_IO,
561
0
         LIBCERROR_IO_ERROR_READ_FAILED,
562
0
         "%s: unable to read owned pages space tree.",
563
0
         function );
564
565
0
        goto on_error;
566
0
      }
567
0
      if( libesedb_space_tree_free(
568
0
           &space_tree,
569
0
           error ) != 1 )
570
0
      {
571
0
        libcerror_error_set(
572
0
         error,
573
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
574
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
575
0
         "%s: unable to free space tree.",
576
0
         function );
577
578
0
        goto on_error;
579
0
      }
580
      /* Read the available pages space tree page
581
       */
582
0
      if( libesedb_space_tree_initialize(
583
0
           &space_tree,
584
0
           page_tree->io_handle,
585
0
           page_tree->object_identifier,
586
0
           page_tree->root_page_header->space_tree_page_number + 1,
587
0
           page_tree->pages_vector,
588
0
           page_tree->pages_cache,
589
0
           error ) != 1 )
590
0
      {
591
0
        libcerror_error_set(
592
0
         error,
593
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
594
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
595
0
         "%s: unable to create available pages space tree.",
596
0
         function );
597
598
0
        goto on_error;
599
0
      }
600
0
      if( libesedb_space_tree_read_file_io_handle(
601
0
           space_tree,
602
0
           file_io_handle,
603
0
           error ) != 1 )
604
0
      {
605
0
        libcerror_error_set(
606
0
         error,
607
0
         LIBCERROR_ERROR_DOMAIN_IO,
608
0
         LIBCERROR_IO_ERROR_READ_FAILED,
609
0
         "%s: unable to read available pages space tree.",
610
0
         function );
611
612
0
        goto on_error;
613
0
      }
614
0
      if( libesedb_space_tree_free(
615
0
           &space_tree,
616
0
           error ) != 1 )
617
0
      {
618
0
        libcerror_error_set(
619
0
         error,
620
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
621
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
622
0
         "%s: unable to free space tree.",
623
0
         function );
624
625
0
        goto on_error;
626
0
      }
627
0
    }
628
0
  }
629
0
  return( 1 );
630
631
0
on_error:
632
0
  if( space_tree != NULL )
633
0
  {
634
0
    libesedb_space_tree_free(
635
0
     &space_tree,
636
0
     NULL );
637
0
  }
638
0
  return( -1 );
639
0
}
640
641
/* Retrieves the page tree key of a specific page value
642
 * This function creates a key
643
 * Returns 1 if successful or -1 on error
644
 */
645
int libesedb_page_tree_get_key(
646
     libesedb_page_tree_t *page_tree,
647
     libesedb_page_tree_value_t *page_tree_value,
648
     libesedb_page_t *page,
649
     uint32_t page_flags,
650
     uint16_t page_value_index,
651
     libesedb_page_tree_key_t **key,
652
     libcerror_error_t **error )
653
0
{
654
0
  libesedb_page_tree_key_t *safe_key       = NULL;
655
0
  libesedb_page_value_t *header_page_value = NULL;
656
0
  static char *function                    = "libesedb_page_tree_get_key";
657
658
#if defined( HAVE_DEBUG_OUTPUT )
659
  uint8_t *page_key_data                   = NULL;
660
  size_t page_key_size                     = 0;
661
#endif
662
663
0
  if( page_tree == NULL )
664
0
  {
665
0
    libcerror_error_set(
666
0
     error,
667
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
668
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
669
0
     "%s: invalid page tree.",
670
0
     function );
671
672
0
    return( -1 );
673
0
  }
674
0
  if( page_tree_value == NULL )
675
0
  {
676
0
    libcerror_error_set(
677
0
     error,
678
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
679
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
680
0
     "%s: invalid page tree value.",
681
0
     function );
682
683
0
    return( -1 );
684
0
  }
685
0
  if( key == NULL )
686
0
  {
687
0
    libcerror_error_set(
688
0
     error,
689
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
690
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
691
0
     "%s: invalid key.",
692
0
     function );
693
694
0
    return( -1 );
695
0
  }
696
0
  if( libesedb_page_tree_key_initialize(
697
0
       &safe_key,
698
0
       error ) != 1 )
699
0
  {
700
0
    libcerror_error_set(
701
0
     error,
702
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
703
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
704
0
     "%s: unable to create key.",
705
0
     function );
706
707
0
    goto on_error;
708
0
  }
709
0
  if( page_tree_value->common_key_size > 0 )
710
0
  {
711
0
    if( libesedb_page_get_value_by_index(
712
0
         page,
713
0
         0,
714
0
         &header_page_value,
715
0
         error ) != 1 )
716
0
    {
717
0
      libcerror_error_set(
718
0
       error,
719
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
720
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
721
0
       "%s: unable to retrieve page value: 0.",
722
0
       function );
723
724
0
      goto on_error;
725
0
    }
726
0
    if( header_page_value == NULL )
727
0
    {
728
0
      libcerror_error_set(
729
0
       error,
730
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
731
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
732
0
       "%s: missing page value: 0.",
733
0
       function );
734
735
0
      goto on_error;
736
0
    }
737
#if defined( HAVE_DEBUG_OUTPUT )
738
    if( libcnotify_verbose != 0 )
739
    {
740
      libcnotify_printf(
741
       "%s: page value: 000 page tag flags\t\t: 0x%02" PRIx8 "",
742
       function,
743
       header_page_value->flags );
744
      libesedb_debug_print_page_tag_flags(
745
       header_page_value->flags );
746
      libcnotify_printf(
747
       "\n" );
748
749
      libcnotify_printf(
750
       "%s: page value: 000 data:\n",
751
       function );
752
      libcnotify_print_data(
753
       header_page_value->data,
754
       (size_t) header_page_value->size,
755
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
756
    }
757
#endif
758
0
    if( page_tree_value->common_key_size > header_page_value->size )
759
0
    {
760
0
      libcerror_error_set(
761
0
       error,
762
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
763
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
764
0
       "%s: common key size exceeds header page value size.",
765
0
       function );
766
767
0
      goto on_error;
768
0
    }
769
#if defined( HAVE_DEBUG_OUTPUT )
770
    if( libcnotify_verbose != 0 )
771
    {
772
      libcnotify_printf(
773
       "%s: page value: %03" PRIu16 " common key value\t\t: ",
774
       function,
775
       page_value_index );
776
777
      page_key_data = header_page_value->data;
778
      page_key_size = page_tree_value->common_key_size;
779
780
      while( page_key_size > 0 )
781
      {
782
        if( libcnotify_verbose != 0 )
783
        {
784
          libcnotify_printf(
785
           "%02" PRIx8 " ",
786
           *page_key_data );
787
        }
788
        page_key_data++;
789
        page_key_size--;
790
      }
791
      libcnotify_printf(
792
       "\n" );
793
    }
794
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
795
796
0
    if( libesedb_page_tree_key_set_data(
797
0
         safe_key,
798
0
         header_page_value->data,
799
0
         (size_t) page_tree_value->common_key_size,
800
0
         error ) != 1 )
801
0
    {
802
0
      libcerror_error_set(
803
0
       error,
804
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
805
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
806
0
       "%s: unable to set common key data in key.",
807
0
       function );
808
809
0
      goto on_error;
810
0
    }
811
0
  }
812
0
  if( libesedb_page_tree_key_append_data(
813
0
       safe_key,
814
0
       page_tree_value->local_key,
815
0
       (size_t) page_tree_value->local_key_size,
816
0
       error ) != 1 )
817
0
  {
818
0
    libcerror_error_set(
819
0
     error,
820
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
821
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
822
0
     "%s: unable to append local key data to key.",
823
0
     function );
824
825
0
    goto on_error;
826
0
  }
827
#if defined( HAVE_DEBUG_OUTPUT )
828
  if( libcnotify_verbose != 0 )
829
  {
830
    libcnotify_printf(
831
     "%s: page value: %03" PRIu16 " key value\t\t\t: ",
832
     function,
833
     page_value_index );
834
835
    page_key_data = safe_key->data;
836
    page_key_size = safe_key->data_size;
837
838
    while( page_key_size > 0 )
839
    {
840
      libcnotify_printf(
841
       "%02" PRIx8 " ",
842
       *page_key_data );
843
844
      page_key_data++;
845
      page_key_size--;
846
    }
847
    libcnotify_printf(
848
     "\n\n" );
849
  }
850
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
851
852
0
  if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_LEAF ) != 0 )
853
0
  {
854
0
    safe_key->type = LIBESEDB_KEY_TYPE_LEAF;
855
0
  }
856
0
  else
857
0
  {
858
0
    safe_key->type = LIBESEDB_KEY_TYPE_BRANCH;
859
0
  }
860
0
  *key = safe_key;
861
862
0
  return( 1 );
863
864
0
on_error:
865
0
  if( safe_key != NULL )
866
0
  {
867
0
    libesedb_page_tree_key_free(
868
0
     &safe_key,
869
0
     NULL );
870
0
  }
871
0
  return( -1 );
872
0
}
873
874
/* Determines the first leaf page number from a page
875
 * Returns 1 if successful or -1 on error
876
 */
877
int libesedb_page_tree_get_first_leaf_page_number_from_page(
878
     libesedb_page_tree_t *page_tree,
879
     libbfio_handle_t *file_io_handle,
880
     libesedb_page_t *page,
881
     uint32_t *leaf_page_number,
882
     int recursion_depth,
883
     libcerror_error_t **error )
884
16.6k
{
885
16.6k
  libesedb_page_t *child_page                 = NULL;
886
16.6k
  libesedb_page_tree_value_t *page_tree_value = NULL;
887
16.6k
  libesedb_page_value_t *page_value           = NULL;
888
16.6k
  static char *function                       = "libesedb_page_tree_get_first_leaf_page_number_from_page";
889
16.6k
  uint32_t child_page_number                  = 0;
890
16.6k
  uint32_t page_flags                         = 0;
891
16.6k
  uint16_t number_of_page_values              = 0;
892
16.6k
  uint16_t page_value_index                   = 0;
893
894
#if defined( HAVE_DEBUG_OUTPUT )
895
  libesedb_page_tree_key_t *page_value_key    = NULL;
896
#endif
897
898
16.6k
  if( page_tree == NULL )
899
0
  {
900
0
    libcerror_error_set(
901
0
     error,
902
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
903
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
904
0
     "%s: invalid page tree.",
905
0
     function );
906
907
0
    return( -1 );
908
0
  }
909
16.6k
  if( page_tree->io_handle == NULL )
910
0
  {
911
0
    libcerror_error_set(
912
0
     error,
913
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
914
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
915
0
     "%s: invalid page tree - missing IO handle.",
916
0
     function );
917
918
0
    return( -1 );
919
0
  }
920
16.6k
  if( leaf_page_number == NULL )
921
0
  {
922
0
    libcerror_error_set(
923
0
     error,
924
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
925
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
926
0
     "%s: invalid leaf page number.",
927
0
     function );
928
929
0
    return( -1 );
930
0
  }
931
16.6k
  if( ( recursion_depth < 0 )
932
16.6k
   || ( recursion_depth > LIBESEDB_MAXIMUM_INDEX_NODE_RECURSION_DEPTH ) )
933
29
  {
934
29
    libcerror_error_set(
935
29
     error,
936
29
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
937
29
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
938
29
     "%s: invalid recursion depth value out of bounds.",
939
29
     function );
940
941
29
    return( -1 );
942
29
  }
943
16.5k
  if( libesedb_page_get_flags(
944
16.5k
       page,
945
16.5k
       &page_flags,
946
16.5k
       error ) != 1 )
947
0
  {
948
0
    libcerror_error_set(
949
0
     error,
950
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
951
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
952
0
     "%s: unable to retrieve page flags.",
953
0
     function );
954
955
0
    goto on_error;
956
0
  }
957
16.5k
  if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_LEAF ) != 0 )
958
4.38k
  {
959
4.38k
    *leaf_page_number = page->page_number;
960
961
4.38k
    return( 1 );
962
4.38k
  }
963
12.2k
  if( libesedb_page_get_number_of_values(
964
12.2k
       page,
965
12.2k
       &number_of_page_values,
966
12.2k
       error ) != 1 )
967
0
  {
968
0
    libcerror_error_set(
969
0
     error,
970
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
971
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
972
0
     "%s: unable to retrieve number of page values.",
973
0
     function );
974
975
0
    goto on_error;
976
0
  }
977
12.2k
  for( page_value_index = 1;
978
20.2k
       page_value_index < number_of_page_values;
979
12.2k
       page_value_index++ )
980
17.7k
  {
981
17.7k
    if( libesedb_page_get_value_by_index(
982
17.7k
         page,
983
17.7k
         page_value_index,
984
17.7k
         &page_value,
985
17.7k
         error ) != 1 )
986
0
    {
987
0
      libcerror_error_set(
988
0
       error,
989
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
990
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
991
0
       "%s: unable to retrieve page value: %" PRIu16 ".",
992
0
       function,
993
0
       page_value_index );
994
995
0
      goto on_error;
996
0
    }
997
17.7k
    if( page_value == NULL )
998
0
    {
999
0
      libcerror_error_set(
1000
0
       error,
1001
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1002
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1003
0
       "%s: missing page value: %" PRIu16 ".",
1004
0
       function,
1005
0
       page_value_index );
1006
1007
0
      goto on_error;
1008
0
    }
1009
#if defined( HAVE_DEBUG_OUTPUT )
1010
    if( libcnotify_verbose != 0 )
1011
    {
1012
      libcnotify_printf(
1013
       "%s: page value: %03" PRIu16 " page tag flags\t\t: 0x%02" PRIx8 "",
1014
       function,
1015
       page_value_index,
1016
       page_value->flags );
1017
      libesedb_debug_print_page_tag_flags(
1018
       page_value->flags );
1019
      libcnotify_printf(
1020
       "\n" );
1021
    }
1022
#endif
1023
17.7k
    if( ( page_value->flags & LIBESEDB_PAGE_TAG_FLAG_IS_DEFUNCT ) != 0 )
1024
8.03k
    {
1025
/* TODO are defunct data definition of any value recovering */
1026
#if defined( HAVE_DEBUG_OUTPUT )
1027
      if( libcnotify_verbose != 0 )
1028
      {
1029
        libcnotify_printf(
1030
         "%s: page value: %03" PRIu16 " data:\n",
1031
         function,
1032
         page_value_index );
1033
        libcnotify_print_data(
1034
         page_value->data,
1035
         (size_t) page_value->size,
1036
         LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1037
      }
1038
#endif
1039
8.03k
      continue;
1040
8.03k
    }
1041
9.71k
    if( libesedb_page_tree_value_initialize(
1042
9.71k
         &page_tree_value,
1043
9.71k
         error ) != 1 )
1044
0
    {
1045
0
      libcerror_error_set(
1046
0
       error,
1047
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1048
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1049
0
       "%s: unable to create page tree value.",
1050
0
       function );
1051
1052
0
      goto on_error;
1053
0
    }
1054
9.71k
    if( libesedb_page_tree_value_read_data(
1055
9.71k
         page_tree_value,
1056
9.71k
         page_value->data,
1057
9.71k
         (size_t) page_value->size,
1058
9.71k
         page_value->flags,
1059
9.71k
         error ) != 1 )
1060
79
    {
1061
79
      libcerror_error_set(
1062
79
       error,
1063
79
       LIBCERROR_ERROR_DOMAIN_IO,
1064
79
       LIBCERROR_IO_ERROR_READ_FAILED,
1065
79
       "%s: unable to read page tree value: %" PRIu16 ".",
1066
79
       function,
1067
79
       page_value_index );
1068
1069
79
      goto on_error;
1070
79
    }
1071
#if defined( HAVE_DEBUG_OUTPUT )
1072
    if( libesedb_page_tree_get_key(
1073
         page_tree,
1074
         page_tree_value,
1075
         page,
1076
         page_flags,
1077
         page_value_index,
1078
         &page_value_key,
1079
         error ) != 1 )
1080
    {
1081
      libcerror_error_set(
1082
       error,
1083
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1084
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1085
       "%s: unable to retrieve key of page value: %" PRIu16 ".",
1086
       function,
1087
       page_value_index );
1088
1089
      goto on_error;
1090
    }
1091
    if( libesedb_page_tree_key_free(
1092
         &page_value_key,
1093
         error ) != 1 )
1094
    {
1095
      libcerror_error_set(
1096
       error,
1097
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1098
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1099
       "%s: unable to free page value key.",
1100
       function );
1101
1102
      goto on_error;
1103
    }
1104
#endif
1105
9.63k
    if( page_tree_value->data_size < 4 )
1106
7
    {
1107
7
      libcerror_error_set(
1108
7
       error,
1109
7
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1110
7
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1111
7
       "%s: invalid page tree value: %" PRIu16 " data size value out of bounds.",
1112
7
       function,
1113
7
       page_value_index );
1114
1115
7
      goto on_error;
1116
7
    }
1117
9.62k
    byte_stream_copy_to_uint32_little_endian(
1118
9.62k
     page_tree_value->data,
1119
9.62k
     child_page_number );
1120
1121
#if defined( HAVE_DEBUG_OUTPUT )
1122
    if( libcnotify_verbose != 0 )
1123
    {
1124
      libcnotify_printf(
1125
       "%s: page value: %03" PRIu16 " child page number\t: %" PRIu32 "",
1126
       function,
1127
       page_value_index,
1128
       child_page_number );
1129
1130
      if( child_page_number == 0 )
1131
      {
1132
        libcnotify_printf(
1133
         " (invalid page number)\n" );
1134
      }
1135
      else if( child_page_number > page_tree->io_handle->last_page_number )
1136
      {
1137
        libcnotify_printf(
1138
         " (exceeds last page number: %" PRIu32 ")\n",
1139
         page_tree->io_handle->last_page_number );
1140
      }
1141
      libcnotify_printf(
1142
       "\n" );
1143
      libcnotify_printf(
1144
       "\n" );
1145
    }
1146
#endif
1147
9.62k
#if ( SIZEOF_INT <= 4 )
1148
9.62k
    if( ( child_page_number < 1 )
1149
9.62k
     || ( child_page_number > (uint32_t) INT_MAX ) )
1150
#else
1151
    if( ( child_page_number < 1 )
1152
     || ( (int) child_page_number > INT_MAX ) )
1153
#endif
1154
149
    {
1155
149
      libcerror_error_set(
1156
149
       error,
1157
149
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1158
149
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1159
149
       "%s: invalid child page number value out of bounds.",
1160
149
       function );
1161
1162
149
      goto on_error;
1163
149
    }
1164
#if defined( HAVE_DEBUG_OUTPUT )
1165
    if( libcnotify_verbose != 0 )
1166
    {
1167
      if( page_tree_value->data_size > 4 )
1168
      {
1169
        libcnotify_printf(
1170
         "%s: page value: %03" PRIu16 " trailing data:\n",
1171
         function,
1172
         page_value_index );
1173
        libcnotify_print_data(
1174
         &( page_tree_value->data[ 4 ] ),
1175
         page_tree_value->data_size - 4,
1176
         LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1177
      }
1178
    }
1179
#endif
1180
9.48k
    if( ( child_page_number > 0 )
1181
9.48k
     && ( child_page_number <= page_tree->io_handle->last_page_number ) )
1182
9.18k
    {
1183
9.18k
      if( libfdata_vector_get_element_value_by_index(
1184
9.18k
           page_tree->pages_vector,
1185
9.18k
           (intptr_t *) file_io_handle,
1186
9.18k
           (libfdata_cache_t *) page_tree->pages_cache,
1187
9.18k
           (int) child_page_number - 1,
1188
9.18k
           (intptr_t **) &child_page,
1189
9.18k
           0,
1190
9.18k
           error ) != 1 )
1191
17
      {
1192
17
        libcerror_error_set(
1193
17
         error,
1194
17
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1195
17
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1196
17
         "%s: unable to retrieve page: %" PRIu32 ".",
1197
17
         function,
1198
17
         child_page_number );
1199
1200
17
        goto on_error;
1201
17
      }
1202
9.16k
      if( libesedb_page_validate_page(
1203
9.16k
           child_page,
1204
9.16k
           error ) != 1 )
1205
419
      {
1206
419
        libcerror_error_set(
1207
419
         error,
1208
419
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1209
419
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1210
419
         "%s: unsupported page.",
1211
419
         function );
1212
1213
419
        goto on_error;
1214
419
      }
1215
8.74k
      if( libesedb_page_tree_get_first_leaf_page_number_from_page(
1216
8.74k
           page_tree,
1217
8.74k
           file_io_handle,
1218
8.74k
           child_page,
1219
8.74k
           leaf_page_number,
1220
8.74k
           recursion_depth + 1,
1221
8.74k
           error ) != 1 )
1222
7.58k
      {
1223
7.58k
        libcerror_error_set(
1224
7.58k
         error,
1225
7.58k
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1226
7.58k
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1227
7.58k
         "%s: unable to retrieve first leaf page number from page: %" PRIu32 ".",
1228
7.58k
         function,
1229
7.58k
         child_page_number );
1230
1231
7.58k
        goto on_error;
1232
7.58k
      }
1233
8.74k
    }
1234
1.45k
    if( libesedb_page_tree_value_free(
1235
1.45k
         &page_tree_value,
1236
1.45k
         error ) != 1 )
1237
0
    {
1238
0
      libcerror_error_set(
1239
0
       error,
1240
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1241
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1242
0
       "%s: unable to free page tree value.",
1243
0
       function );
1244
1245
0
      goto on_error;
1246
0
    }
1247
1.45k
    break;
1248
1.45k
  }
1249
3.95k
  return( 1 );
1250
1251
8.25k
on_error:
1252
#if defined( HAVE_DEBUG_OUTPUT )
1253
  if( page_value_key != NULL )
1254
  {
1255
    libesedb_page_tree_key_free(
1256
     &page_value_key,
1257
     NULL );
1258
  }
1259
#endif
1260
8.25k
  if( page_tree_value != NULL )
1261
8.25k
  {
1262
8.25k
    libesedb_page_tree_value_free(
1263
8.25k
     &page_tree_value,
1264
8.25k
     NULL );
1265
8.25k
  }
1266
8.25k
  return( -1 );
1267
12.2k
}
1268
1269
/* Determines the first leaf page number
1270
 * Returns 1 if successful or -1 on error
1271
 */
1272
int libesedb_page_tree_get_get_first_leaf_page_number(
1273
     libesedb_page_tree_t *page_tree,
1274
     libbfio_handle_t *file_io_handle,
1275
     uint32_t *leaf_page_number,
1276
     libcerror_error_t **error )
1277
8.88k
{
1278
8.88k
  libesedb_page_t *page          = NULL;
1279
8.88k
  static char *function          = "libesedb_page_tree_get_get_first_leaf_page_number";
1280
8.88k
  off64_t page_offset            = 0;
1281
8.88k
  uint32_t last_leaf_page_number = 0;
1282
8.88k
  uint32_t page_flags            = 0;
1283
8.88k
  uint32_t safe_leaf_page_number = 0;
1284
1285
8.88k
  if( page_tree == NULL )
1286
0
  {
1287
0
    libcerror_error_set(
1288
0
     error,
1289
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1290
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1291
0
     "%s: invalid page tree.",
1292
0
     function );
1293
1294
0
    return( -1 );
1295
0
  }
1296
8.88k
  if( page_tree->io_handle == NULL )
1297
0
  {
1298
0
    libcerror_error_set(
1299
0
     error,
1300
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1301
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1302
0
     "%s: invalid page tree - missing IO handle.",
1303
0
     function );
1304
1305
0
    return( -1 );
1306
0
  }
1307
8.88k
  if( leaf_page_number == NULL )
1308
0
  {
1309
0
    libcerror_error_set(
1310
0
     error,
1311
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1312
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1313
0
     "%s: invalid leaf page number.",
1314
0
     function );
1315
1316
0
    return( -1 );
1317
0
  }
1318
8.88k
  if( libfdata_vector_get_element_value_by_index(
1319
8.88k
       page_tree->pages_vector,
1320
8.88k
       (intptr_t *) file_io_handle,
1321
8.88k
       (libfdata_cache_t *) page_tree->pages_cache,
1322
8.88k
       (int) page_tree->root_page_number - 1,
1323
8.88k
       (intptr_t **) &page,
1324
8.88k
       0,
1325
8.88k
       error ) != 1 )
1326
922
  {
1327
922
    libcerror_error_set(
1328
922
     error,
1329
922
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1330
922
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1331
922
     "%s: unable to retrieve page: %" PRIu32 ".",
1332
922
     function,
1333
922
     page_tree->root_page_number );
1334
1335
922
    return( -1 );
1336
922
  }
1337
7.95k
  if( libesedb_page_get_flags(
1338
7.95k
       page,
1339
7.95k
       &page_flags,
1340
7.95k
       error ) != 1 )
1341
0
  {
1342
0
    libcerror_error_set(
1343
0
     error,
1344
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1345
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1346
0
     "%s: unable to retrieve page flags.",
1347
0
     function );
1348
1349
0
    return( -1 );
1350
0
  }
1351
  /* Seen in temp.edb where is root flag is not set
1352
   */
1353
7.95k
  if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_ROOT ) != 0 )
1354
3.07k
  {
1355
3.07k
    if( libesedb_page_validate_root_page(
1356
3.07k
         page,
1357
3.07k
         error ) != 1 )
1358
88
    {
1359
88
      libcerror_error_set(
1360
88
       error,
1361
88
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1362
88
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1363
88
       "%s: unsupported root page.",
1364
88
       function );
1365
1366
88
      return( -1 );
1367
88
    }
1368
3.07k
  }
1369
#if defined( HAVE_DEBUG_OUTPUT ) && defined( TODO )
1370
  if( page_tree->root_page_header == NULL )
1371
  {
1372
    if( libesedb_page_tree_read_root_page_header(
1373
         page_tree,
1374
         page,
1375
         error ) != 1 )
1376
    {
1377
      libcerror_error_set(
1378
       error,
1379
       LIBCERROR_ERROR_DOMAIN_IO,
1380
       LIBCERROR_IO_ERROR_READ_FAILED,
1381
       "%s: unable to read root page header.",
1382
       function );
1383
1384
      return( -1 );
1385
    }
1386
    if( libesedb_page_tree_read_space_trees(
1387
         page_tree,
1388
         file_io_handle,
1389
         error ) != 1 )
1390
    {
1391
      libcerror_error_set(
1392
       error,
1393
       LIBCERROR_ERROR_DOMAIN_IO,
1394
       LIBCERROR_IO_ERROR_READ_FAILED,
1395
       "%s: unable to read space trees.",
1396
       function );
1397
1398
      return( -1 );
1399
    }
1400
  }
1401
#endif
1402
7.87k
  if( libesedb_page_tree_get_first_leaf_page_number_from_page(
1403
7.87k
       page_tree,
1404
7.87k
       file_io_handle,
1405
7.87k
       page,
1406
7.87k
       &safe_leaf_page_number,
1407
7.87k
       0,
1408
7.87k
       error ) != 1 )
1409
700
  {
1410
700
    libcerror_error_set(
1411
700
     error,
1412
700
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1413
700
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1414
700
     "%s: unable to retrieve first leaf page number from page: %" PRIu32 ".",
1415
700
     function,
1416
700
     page_tree->root_page_number );
1417
1418
700
    return( -1 );
1419
700
  }
1420
14.0k
  while( safe_leaf_page_number != 0 )
1421
7.53k
  {
1422
7.53k
    page_offset = ( safe_leaf_page_number + 1 ) * page_tree->io_handle->page_size;
1423
1424
7.53k
    if( libesedb_page_tree_check_if_page_block_first_read(
1425
7.53k
         page_tree,
1426
7.53k
         page_tree->page_block_tree,
1427
7.53k
         safe_leaf_page_number,
1428
7.53k
         page_offset,
1429
7.53k
         error ) != 1 )
1430
191
    {
1431
191
      libcerror_error_set(
1432
191
       error,
1433
191
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1434
191
       LIBCERROR_RUNTIME_ERROR_GENERIC,
1435
191
       "%s: unable to check if first read of page number: %" PRIu32 ".",
1436
191
       function,
1437
191
       safe_leaf_page_number );
1438
1439
191
      return( -1 );
1440
191
    }
1441
7.34k
#if ( SIZEOF_INT <= 4 )
1442
7.34k
    if( safe_leaf_page_number > (uint32_t) INT_MAX )
1443
#else
1444
    if( safe_leaf_page_number > (unsigned int) INT_MAX )
1445
#endif
1446
120
    {
1447
120
      libcerror_error_set(
1448
120
       error,
1449
120
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1450
120
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1451
120
       "%s: invalid leaf page number value out of bounds.",
1452
120
       function );
1453
1454
120
      return( -1 );
1455
120
    }
1456
7.22k
    last_leaf_page_number = safe_leaf_page_number;
1457
1458
7.22k
    if( libfdata_vector_get_element_value_by_index(
1459
7.22k
         page_tree->pages_vector,
1460
7.22k
         (intptr_t *) file_io_handle,
1461
7.22k
         (libfdata_cache_t *) page_tree->pages_cache,
1462
7.22k
         (int) safe_leaf_page_number - 1,
1463
7.22k
         (intptr_t **) &page,
1464
7.22k
         0,
1465
7.22k
         error ) != 1 )
1466
382
    {
1467
382
      libcerror_error_set(
1468
382
       error,
1469
382
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1470
382
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1471
382
       "%s: unable to retrieve page: %" PRIu32 ".",
1472
382
       function,
1473
382
       safe_leaf_page_number );
1474
1475
382
      return( -1 );
1476
382
    }
1477
6.84k
    if( libesedb_page_get_previous_page_number(
1478
6.84k
         page,
1479
6.84k
         &safe_leaf_page_number,
1480
6.84k
         error ) != 1 )
1481
0
    {
1482
0
      libcerror_error_set(
1483
0
       error,
1484
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1485
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1486
0
       "%s: unable to retrieve previous page number from page: %" PRIu32 ".",
1487
0
       function,
1488
0
       safe_leaf_page_number );
1489
1490
0
      return( -1 );
1491
0
    }
1492
6.84k
  }
1493
6.47k
  *leaf_page_number = last_leaf_page_number;
1494
1495
6.47k
  return( 1 );
1496
7.17k
}
1497
1498
/* Determines the number of leaf values from a page
1499
 * Returns 1 if successful or -1 on error
1500
 */
1501
int libesedb_page_tree_get_number_of_leaf_values_from_leaf_page(
1502
     libesedb_page_tree_t *page_tree,
1503
     libesedb_page_t *page,
1504
     int *number_of_leaf_values,
1505
     libcerror_error_t **error )
1506
88.6k
{
1507
88.6k
  libesedb_page_value_t *page_value = NULL;
1508
88.6k
  static char *function             = "libesedb_page_tree_get_number_of_leaf_values_from_leaf_page";
1509
88.6k
  uint32_t page_flags               = 0;
1510
88.6k
  uint16_t number_of_page_values    = 0;
1511
88.6k
  uint16_t page_value_index         = 0;
1512
88.6k
  int safe_number_of_leaf_values    = 0;
1513
1514
88.6k
  if( page_tree == NULL )
1515
0
  {
1516
0
    libcerror_error_set(
1517
0
     error,
1518
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1519
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1520
0
     "%s: invalid page tree.",
1521
0
     function );
1522
1523
0
    return( -1 );
1524
0
  }
1525
88.6k
  if( number_of_leaf_values == NULL )
1526
0
  {
1527
0
    libcerror_error_set(
1528
0
     error,
1529
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1530
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1531
0
     "%s: invalid number of leaf values.",
1532
0
     function );
1533
1534
0
    return( -1 );
1535
0
  }
1536
88.6k
  if( libesedb_page_get_flags(
1537
88.6k
       page,
1538
88.6k
       &page_flags,
1539
88.6k
       error ) != 1 )
1540
0
  {
1541
0
    libcerror_error_set(
1542
0
     error,
1543
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1544
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1545
0
     "%s: unable to retrieve page flags.",
1546
0
     function );
1547
1548
0
    return( -1 );
1549
0
  }
1550
88.6k
  if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_LEAF ) == 0 )
1551
1
  {
1552
1
    libcerror_error_set(
1553
1
     error,
1554
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1555
1
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1556
1
     "%s: unsupported page - not a leaf page.",
1557
1
     function );
1558
1559
1
    return( -1 );
1560
1
  }
1561
88.6k
  if( libesedb_page_get_number_of_values(
1562
88.6k
       page,
1563
88.6k
       &number_of_page_values,
1564
88.6k
       error ) != 1 )
1565
0
  {
1566
0
    libcerror_error_set(
1567
0
     error,
1568
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1569
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1570
0
     "%s: unable to retrieve number of page values.",
1571
0
     function );
1572
1573
0
    return( -1 );
1574
0
  }
1575
88.6k
  safe_number_of_leaf_values = *number_of_leaf_values;
1576
1577
88.6k
  for( page_value_index = 1;
1578
57.6M
       page_value_index < number_of_page_values;
1579
57.5M
       page_value_index++ )
1580
57.5M
  {
1581
57.5M
    if( libesedb_page_get_value_by_index(
1582
57.5M
         page,
1583
57.5M
         page_value_index,
1584
57.5M
         &page_value,
1585
57.5M
         error ) != 1 )
1586
0
    {
1587
0
      libcerror_error_set(
1588
0
       error,
1589
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1590
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1591
0
       "%s: unable to retrieve page value: %" PRIu16 ".",
1592
0
       function,
1593
0
       page_value_index );
1594
1595
0
      return( -1 );
1596
0
    }
1597
57.5M
    if( page_value == NULL )
1598
0
    {
1599
0
      libcerror_error_set(
1600
0
       error,
1601
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1602
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1603
0
       "%s: missing page value: %" PRIu16 ".",
1604
0
       function,
1605
0
       page_value_index );
1606
1607
0
      return( -1 );
1608
0
    }
1609
#if defined( HAVE_DEBUG_OUTPUT )
1610
    if( libcnotify_verbose != 0 )
1611
    {
1612
      libcnotify_printf(
1613
       "%s: page value: %03" PRIu16 " page tag flags\t\t: 0x%02" PRIx8 "",
1614
       function,
1615
       page_value_index,
1616
       page_value->flags );
1617
      libesedb_debug_print_page_tag_flags(
1618
       page_value->flags );
1619
      libcnotify_printf(
1620
       "\n" );
1621
    }
1622
#endif
1623
57.5M
    if( ( page_value->flags & LIBESEDB_PAGE_TAG_FLAG_IS_DEFUNCT ) != 0 )
1624
19.4k
    {
1625
/* TODO are defunct data definition of any value recovering */
1626
#if defined( HAVE_DEBUG_OUTPUT )
1627
      if( libcnotify_verbose != 0 )
1628
      {
1629
        libcnotify_printf(
1630
         "%s: page value: %03" PRIu16 " data:\n",
1631
         function,
1632
         page_value_index );
1633
        libcnotify_print_data(
1634
         page_value->data,
1635
         (size_t) page_value->size,
1636
         LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1637
      }
1638
#endif
1639
19.4k
      continue;
1640
19.4k
    }
1641
57.4M
    if( safe_number_of_leaf_values == INT_MAX )
1642
0
    {
1643
0
      libcerror_error_set(
1644
0
       error,
1645
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1646
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1647
0
       "%s: invalid number of leaf values value out of bounds.",
1648
0
       function );
1649
1650
0
      return( -1 );
1651
0
    }
1652
57.4M
    safe_number_of_leaf_values++;
1653
57.4M
  }
1654
88.6k
  *number_of_leaf_values = safe_number_of_leaf_values;
1655
1656
88.6k
  return( 1 );
1657
88.6k
}
1658
1659
/* Determines the number of leaf values
1660
 * Returns 1 if successful or -1 on error
1661
 */
1662
int libesedb_page_tree_get_number_of_leaf_values(
1663
     libesedb_page_tree_t *page_tree,
1664
     libbfio_handle_t *file_io_handle,
1665
     int *number_of_leaf_values,
1666
     libcerror_error_t **error )
1667
492
{
1668
492
  libcdata_tree_node_t *upper_node                               = NULL;
1669
492
  libesedb_leaf_page_descriptor_t *existing_leaf_page_descriptor = NULL;
1670
492
  libesedb_leaf_page_descriptor_t *leaf_page_descriptor          = NULL;
1671
492
  libesedb_page_t *page                                          = NULL;
1672
492
  static char *function                                          = "libesedb_page_tree_get_number_of_leaf_values";
1673
492
  uint32_t leaf_page_number                                      = 0;
1674
492
  int number_of_leaf_pages                                       = 0;
1675
492
  int safe_number_of_leaf_values                                 = 0;
1676
492
  int value_index                                                = 0;
1677
1678
492
  if( page_tree == NULL )
1679
0
  {
1680
0
    libcerror_error_set(
1681
0
     error,
1682
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1683
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1684
0
     "%s: invalid page tree.",
1685
0
     function );
1686
1687
0
    return( -1 );
1688
0
  }
1689
492
  if( number_of_leaf_values == NULL )
1690
0
  {
1691
0
    libcerror_error_set(
1692
0
     error,
1693
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1694
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1695
0
     "%s: invalid number of leaf values.",
1696
0
     function );
1697
1698
0
    return( -1 );
1699
0
  }
1700
492
  if( page_tree->number_of_leaf_values == -1 )
1701
492
  {
1702
492
    page_tree->number_of_leaf_values = 0;
1703
1704
492
    if( libesedb_page_tree_get_get_first_leaf_page_number(
1705
492
         page_tree,
1706
492
         file_io_handle,
1707
492
         &leaf_page_number,
1708
492
         error ) != 1 )
1709
18
    {
1710
18
      libcerror_error_set(
1711
18
       error,
1712
18
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1713
18
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1714
18
       "%s: unable to retrieve first leaf page number from page tree.",
1715
18
       function );
1716
1717
18
      goto on_error;
1718
18
    }
1719
89.0k
    while( leaf_page_number != 0 )
1720
88.6k
    {
1721
88.6k
      if( number_of_leaf_pages > LIBESEDB_MAXIMUM_NUMBER_OF_LEAF_PAGES )
1722
5
      {
1723
5
        libcerror_error_set(
1724
5
         error,
1725
5
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1726
5
         LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
1727
5
         "%s: invalid number of leaf pages value exceeds maximum.",
1728
5
         function );
1729
1730
5
        goto on_error;
1731
5
      }
1732
88.6k
#if ( SIZEOF_INT <= 4 )
1733
88.6k
      if( leaf_page_number > (uint32_t) INT_MAX )
1734
#else
1735
      if( leaf_page_number > (unsigned int) INT_MAX )
1736
#endif
1737
36
      {
1738
36
        libcerror_error_set(
1739
36
         error,
1740
36
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1741
36
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1742
36
         "%s: invalid leaf page number value out of bounds.",
1743
36
         function );
1744
1745
36
        goto on_error;
1746
36
      }
1747
88.6k
      if( libfdata_vector_get_element_value_by_index(
1748
88.6k
           page_tree->pages_vector,
1749
88.6k
           (intptr_t *) file_io_handle,
1750
88.6k
           (libfdata_cache_t *) page_tree->pages_cache,
1751
88.6k
           (int) leaf_page_number - 1,
1752
88.6k
           (intptr_t **) &page,
1753
88.6k
           0,
1754
88.6k
           error ) != 1 )
1755
20
      {
1756
20
        libcerror_error_set(
1757
20
         error,
1758
20
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1759
20
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1760
20
         "%s: unable to retrieve page: %" PRIu32 ".",
1761
20
         function,
1762
20
         leaf_page_number );
1763
1764
20
        goto on_error;
1765
20
      }
1766
88.6k
      if( libesedb_page_tree_get_number_of_leaf_values_from_leaf_page(
1767
88.6k
           page_tree,
1768
88.6k
           page,
1769
88.6k
           &safe_number_of_leaf_values,
1770
88.6k
           error ) != 1 )
1771
1
      {
1772
1
        libcerror_error_set(
1773
1
         error,
1774
1
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1775
1
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1776
1
         "%s: unable to determine number of leaf values from page: %" PRIu32 ".",
1777
1
         function,
1778
1
         leaf_page_number );
1779
1780
1
        goto on_error;
1781
1
      }
1782
88.6k
      if( libesedb_leaf_page_descriptor_initialize(
1783
88.6k
           &leaf_page_descriptor,
1784
88.6k
           error ) != 1 )
1785
0
      {
1786
0
        libcerror_error_set(
1787
0
         error,
1788
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1789
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1790
0
         "%s: unable to create leaf page descriptor.",
1791
0
         function );
1792
1793
0
        goto on_error;
1794
0
      }
1795
88.6k
      leaf_page_descriptor->page_number            = page->page_number;
1796
88.6k
      leaf_page_descriptor->first_leaf_value_index = page_tree->number_of_leaf_values;
1797
88.6k
      leaf_page_descriptor->last_leaf_value_index  = safe_number_of_leaf_values - 1;
1798
1799
88.6k
      if( libcdata_btree_insert_value(
1800
88.6k
           page_tree->leaf_page_descriptors_tree,
1801
88.6k
           &value_index,
1802
88.6k
           (intptr_t *) leaf_page_descriptor,
1803
88.6k
           (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libesedb_leaf_page_descriptor_compare,
1804
88.6k
           &upper_node,
1805
88.6k
           (intptr_t **) &existing_leaf_page_descriptor,
1806
88.6k
           error ) != 1 )
1807
12
      {
1808
12
        libcerror_error_set(
1809
12
         error,
1810
12
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1811
12
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1812
12
         "%s: unable insert leaf page descriptor into tree.",
1813
12
         function );
1814
1815
12
        goto on_error;
1816
12
      }
1817
88.5k
      leaf_page_descriptor = NULL;
1818
1819
88.5k
      if( libesedb_page_get_next_page_number(
1820
88.5k
           page,
1821
88.5k
           &leaf_page_number,
1822
88.5k
           error ) != 1 )
1823
0
      {
1824
0
        libcerror_error_set(
1825
0
         error,
1826
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1827
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1828
0
         "%s: unable to retrieve next page number from page: %" PRIu32 ".",
1829
0
         function,
1830
0
         leaf_page_number );
1831
1832
0
        goto on_error;
1833
0
      }
1834
88.5k
      page_tree->number_of_leaf_values = safe_number_of_leaf_values;
1835
1836
88.5k
      number_of_leaf_pages++;
1837
88.5k
    }
1838
474
  }
1839
400
  *number_of_leaf_values = page_tree->number_of_leaf_values;
1840
1841
400
  return( 1 );
1842
1843
92
on_error:
1844
92
  if( leaf_page_descriptor != NULL )
1845
12
  {
1846
12
    libesedb_leaf_page_descriptor_free(
1847
12
     &leaf_page_descriptor,
1848
12
     NULL );
1849
12
  }
1850
92
  return( -1 );
1851
492
}
1852
1853
/* Retrieves a specific leaf value
1854
 * This function creates a new data definition
1855
 * Returns 1 if successful or -1 on error
1856
 */
1857
int libesedb_page_tree_get_leaf_value_by_index_from_page(
1858
     libesedb_page_tree_t *page_tree,
1859
     libbfio_handle_t *file_io_handle,
1860
     libesedb_page_t *page,
1861
     int leaf_value_index,
1862
     libesedb_data_definition_t **data_definition,
1863
     int *current_leaf_value_index,
1864
     int recursion_depth,
1865
     libcerror_error_t **error )
1866
397
{
1867
397
  libesedb_page_t *child_page                 = NULL;
1868
397
  libesedb_page_tree_value_t *page_tree_value = NULL;
1869
397
  libesedb_page_value_t *page_value           = NULL;
1870
397
  libfcache_cache_t *child_page_cache         = NULL;
1871
397
  static char *function                       = "libesedb_page_tree_get_leaf_value_by_index_from_page";
1872
397
  uint32_t child_page_number                  = 0;
1873
397
  uint32_t page_flags                         = 0;
1874
397
  uint16_t data_offset                        = 0;
1875
397
  uint16_t number_of_page_values              = 0;
1876
397
  uint16_t page_value_index                   = 0;
1877
1878
397
  if( page_tree == NULL )
1879
0
  {
1880
0
    libcerror_error_set(
1881
0
     error,
1882
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1883
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1884
0
     "%s: invalid page tree.",
1885
0
     function );
1886
1887
0
    return( -1 );
1888
0
  }
1889
397
  if( page_tree->io_handle == NULL )
1890
0
  {
1891
0
    libcerror_error_set(
1892
0
     error,
1893
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1894
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1895
0
     "%s: invalid page tree - missing IO handle.",
1896
0
     function );
1897
1898
0
    return( -1 );
1899
0
  }
1900
397
  if( data_definition == NULL )
1901
0
  {
1902
0
    libcerror_error_set(
1903
0
     error,
1904
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1905
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1906
0
     "%s: invalid data definition.",
1907
0
     function );
1908
1909
0
    return( -1 );
1910
0
  }
1911
397
  if( current_leaf_value_index == NULL )
1912
0
  {
1913
0
    libcerror_error_set(
1914
0
     error,
1915
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1916
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1917
0
     "%s: invalid current leaf value index.",
1918
0
     function );
1919
1920
0
    return( -1 );
1921
0
  }
1922
397
  if( ( recursion_depth < 0 )
1923
397
   || ( recursion_depth > LIBESEDB_MAXIMUM_INDEX_NODE_RECURSION_DEPTH ) )
1924
0
  {
1925
0
    libcerror_error_set(
1926
0
     error,
1927
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1928
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1929
0
     "%s: invalid recursion depth value out of bounds.",
1930
0
     function );
1931
1932
0
    return( -1 );
1933
0
  }
1934
397
  if( libesedb_page_get_number_of_values(
1935
397
       page,
1936
397
       &number_of_page_values,
1937
397
       error ) != 1 )
1938
0
  {
1939
0
    libcerror_error_set(
1940
0
     error,
1941
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1942
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1943
0
     "%s: unable to retrieve number of page values.",
1944
0
     function );
1945
1946
0
    goto on_error;
1947
0
  }
1948
397
  if( number_of_page_values == 0 )
1949
0
  {
1950
0
    return( 1 );
1951
0
  }
1952
397
  if( libesedb_page_get_flags(
1953
397
       page,
1954
397
       &page_flags,
1955
397
       error ) != 1 )
1956
0
  {
1957
0
    libcerror_error_set(
1958
0
     error,
1959
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1960
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1961
0
     "%s: unable to retrieve page flags.",
1962
0
     function );
1963
1964
0
    goto on_error;
1965
0
  }
1966
        /* Use a local cache to prevent cache invalidation of the page
1967
         * when reading child pages.
1968
         */
1969
397
  if( libfcache_cache_initialize(
1970
397
       &child_page_cache,
1971
397
       1,
1972
397
       error ) != 1 )
1973
0
  {
1974
0
    libcerror_error_set(
1975
0
     error,
1976
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1977
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1978
0
     "%s: unable to create child page cache.",
1979
0
     function );
1980
1981
0
    goto on_error;
1982
0
  }
1983
397
  for( page_value_index = 1;
1984
711
       page_value_index < number_of_page_values;
1985
397
       page_value_index++ )
1986
711
  {
1987
711
    if( libesedb_page_get_value_by_index(
1988
711
         page,
1989
711
         page_value_index,
1990
711
         &page_value,
1991
711
         error ) != 1 )
1992
0
    {
1993
0
      libcerror_error_set(
1994
0
       error,
1995
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1996
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1997
0
       "%s: unable to retrieve page value: %" PRIu16 ".",
1998
0
       function,
1999
0
       page_value_index );
2000
2001
0
      goto on_error;
2002
0
    }
2003
711
    if( page_value == NULL )
2004
0
    {
2005
0
      libcerror_error_set(
2006
0
       error,
2007
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2008
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2009
0
       "%s: missing page value: %" PRIu16 ".",
2010
0
       function,
2011
0
       page_value_index );
2012
2013
0
      goto on_error;
2014
0
    }
2015
#if defined( HAVE_DEBUG_OUTPUT )
2016
    if( libcnotify_verbose != 0 )
2017
    {
2018
      libcnotify_printf(
2019
       "%s: page value: %03" PRIu16 " page tag flags\t\t: 0x%02" PRIx8 "",
2020
       function,
2021
       page_value_index,
2022
       page_value->flags );
2023
      libesedb_debug_print_page_tag_flags(
2024
       page_value->flags );
2025
      libcnotify_printf(
2026
       "\n" );
2027
    }
2028
#endif
2029
711
    if( ( page_value->flags & LIBESEDB_PAGE_TAG_FLAG_IS_DEFUNCT ) != 0 )
2030
314
    {
2031
314
      continue;
2032
314
    }
2033
397
    if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_LEAF ) != 0 )
2034
397
    {
2035
397
      if( *current_leaf_value_index == INT_MAX )
2036
0
      {
2037
0
        libcerror_error_set(
2038
0
         error,
2039
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2040
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2041
0
         "%s: invalid current leaf value index value out of bounds.",
2042
0
         function );
2043
2044
0
        goto on_error;
2045
0
      }
2046
397
      if( *current_leaf_value_index < leaf_value_index )
2047
0
      {
2048
0
        *current_leaf_value_index += 1;
2049
2050
0
        continue;
2051
0
      }
2052
397
    }
2053
397
    if( libesedb_page_tree_value_initialize(
2054
397
         &page_tree_value,
2055
397
         error ) != 1 )
2056
0
    {
2057
0
      libcerror_error_set(
2058
0
       error,
2059
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2060
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2061
0
       "%s: unable to create page tree value.",
2062
0
       function );
2063
2064
0
      goto on_error;
2065
0
    }
2066
397
    if( libesedb_page_tree_value_read_data(
2067
397
         page_tree_value,
2068
397
         page_value->data,
2069
397
         (size_t) page_value->size,
2070
397
         page_value->flags,
2071
397
         error ) != 1 )
2072
19
    {
2073
19
      libcerror_error_set(
2074
19
       error,
2075
19
       LIBCERROR_ERROR_DOMAIN_IO,
2076
19
       LIBCERROR_IO_ERROR_READ_FAILED,
2077
19
       "%s: unable to read page tree value: %" PRIu16 ".",
2078
19
       function,
2079
19
       page_value_index );
2080
2081
19
      goto on_error;
2082
19
    }
2083
378
    if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_LEAF ) != 0 )
2084
378
    {
2085
378
      if( libesedb_data_definition_initialize(
2086
378
           data_definition,
2087
378
           error ) != 1 )
2088
0
      {
2089
0
        libcerror_error_set(
2090
0
         error,
2091
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2092
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2093
0
         "%s: unable to create data definition.",
2094
0
         function );
2095
2096
0
        goto on_error;
2097
0
      }
2098
378
      data_offset = page_value->offset + 2 + page_tree_value->local_key_size;
2099
2100
378
      if( ( page_value->flags & LIBESEDB_PAGE_TAG_FLAG_HAS_COMMON_KEY_SIZE ) != 0 )
2101
220
      {
2102
220
        data_offset += 2;
2103
220
      }
2104
378
      ( *data_definition )->page_value_index = page_value_index;
2105
378
      ( *data_definition )->page_offset      = page->offset - ( 2 * page_tree->io_handle->page_size );
2106
378
      ( *data_definition )->page_number      = page->page_number;
2107
378
      ( *data_definition )->data_offset      = data_offset;
2108
378
      ( *data_definition )->data_size        = page_tree_value->data_size;
2109
2110
378
      *current_leaf_value_index += 1;
2111
378
    }
2112
0
    else
2113
0
    {
2114
0
      if( page_tree_value->data_size < 4 )
2115
0
      {
2116
0
        libcerror_error_set(
2117
0
         error,
2118
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2119
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2120
0
         "%s: invalid page tree value: %" PRIu16 " data size value out of bounds.",
2121
0
         function,
2122
0
         page_value_index );
2123
2124
0
        goto on_error;
2125
0
      }
2126
0
      byte_stream_copy_to_uint32_little_endian(
2127
0
       page_tree_value->data,
2128
0
       child_page_number );
2129
2130
#if defined( HAVE_DEBUG_OUTPUT )
2131
      if( libcnotify_verbose != 0 )
2132
      {
2133
        libcnotify_printf(
2134
         "%s: page value: %03" PRIu16 " child page number\t: %" PRIu32 "",
2135
         function,
2136
         page_value_index,
2137
         child_page_number );
2138
2139
        if( child_page_number == 0 )
2140
        {
2141
          libcnotify_printf(
2142
           " (invalid page number)\n" );
2143
        }
2144
        else if( child_page_number > page_tree->io_handle->last_page_number )
2145
        {
2146
          libcnotify_printf(
2147
           " (exceeds last page number: %" PRIu32 ")\n",
2148
           page_tree->io_handle->last_page_number );
2149
        }
2150
        libcnotify_printf(
2151
         "\n" );
2152
        libcnotify_printf(
2153
         "\n" );
2154
      }
2155
#endif
2156
0
#if ( SIZEOF_INT <= 4 )
2157
0
      if( ( child_page_number < 1 )
2158
0
       || ( child_page_number > (uint32_t) INT_MAX ) )
2159
#else
2160
      if( ( child_page_number < 1 )
2161
       || ( (int) child_page_number > INT_MAX ) )
2162
#endif
2163
0
      {
2164
0
        libcerror_error_set(
2165
0
         error,
2166
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2167
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2168
0
         "%s: invalid child page number value out of bounds.",
2169
0
         function );
2170
2171
0
        goto on_error;
2172
0
      }
2173
#if defined( HAVE_DEBUG_OUTPUT )
2174
      if( libcnotify_verbose != 0 )
2175
      {
2176
        if( page_tree_value->data_size > 4 )
2177
        {
2178
          libcnotify_printf(
2179
           "%s: page value: %03" PRIu16 " trailing data:\n",
2180
           function,
2181
           page_value_index );
2182
          libcnotify_print_data(
2183
           &( page_tree_value->data[ 4 ] ),
2184
           page_tree_value->data_size - 4,
2185
           LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
2186
        }
2187
      }
2188
#endif
2189
0
      if( ( child_page_number > 0 )
2190
0
       && ( child_page_number <= page_tree->io_handle->last_page_number ) )
2191
0
      {
2192
0
        if( libfdata_vector_get_element_value_by_index(
2193
0
             page_tree->pages_vector,
2194
0
             (intptr_t *) file_io_handle,
2195
0
             (libfdata_cache_t *) child_page_cache,
2196
0
             (int) child_page_number - 1,
2197
0
             (intptr_t **) &child_page,
2198
0
             0,
2199
0
             error ) != 1 )
2200
0
        {
2201
0
          libcerror_error_set(
2202
0
           error,
2203
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2204
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2205
0
           "%s: unable to retrieve page: %" PRIu32 ".",
2206
0
           function,
2207
0
           child_page_number );
2208
2209
0
          goto on_error;
2210
0
        }
2211
0
        if( libesedb_page_validate_page(
2212
0
             child_page,
2213
0
             error ) != 1 )
2214
0
        {
2215
0
          libcerror_error_set(
2216
0
           error,
2217
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2218
0
           LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2219
0
           "%s: unsupported page.",
2220
0
           function );
2221
2222
0
          goto on_error;
2223
0
        }
2224
0
        if( libesedb_page_tree_get_leaf_value_by_index_from_page(
2225
0
             page_tree,
2226
0
             file_io_handle,
2227
0
             child_page,
2228
0
             leaf_value_index,
2229
0
             data_definition,
2230
0
             current_leaf_value_index,
2231
0
             recursion_depth + 1,
2232
0
             error ) != 1 )
2233
0
        {
2234
0
          libcerror_error_set(
2235
0
           error,
2236
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2237
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2238
0
           "%s: unable to retrieve leaf value: %d from page: %" PRIu32 ".",
2239
0
           function,
2240
0
           leaf_value_index,
2241
0
           child_page_number );
2242
2243
0
          goto on_error;
2244
0
        }
2245
0
      }
2246
0
    }
2247
378
    if( libesedb_page_tree_value_free(
2248
378
         &page_tree_value,
2249
378
         error ) != 1 )
2250
0
    {
2251
0
      libcerror_error_set(
2252
0
       error,
2253
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2254
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2255
0
       "%s: unable to free page tree value.",
2256
0
       function );
2257
2258
0
      goto on_error;
2259
0
    }
2260
378
    if( *current_leaf_value_index > leaf_value_index )
2261
378
    {
2262
378
      break;
2263
378
    }
2264
378
  }
2265
378
  if( libfcache_cache_free(
2266
378
       &child_page_cache,
2267
378
       error ) != 1 )
2268
0
  {
2269
0
    libcerror_error_set(
2270
0
     error,
2271
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2272
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2273
0
     "%s: unable to free child page cache.",
2274
0
     function );
2275
2276
0
    goto on_error;
2277
0
  }
2278
378
  return( 1 );
2279
2280
19
on_error:
2281
19
  if( *data_definition != NULL )
2282
0
  {
2283
0
    libesedb_data_definition_free(
2284
0
     data_definition,
2285
0
     NULL );
2286
0
  }
2287
19
  if( page_tree_value != NULL )
2288
19
  {
2289
19
    libesedb_page_tree_value_free(
2290
19
     &page_tree_value,
2291
19
     NULL );
2292
19
  }
2293
19
  if( child_page_cache != NULL )
2294
19
  {
2295
19
    libfcache_cache_free(
2296
19
     &child_page_cache,
2297
19
     NULL );
2298
19
  }
2299
19
  return( -1 );
2300
378
}
2301
2302
/* Retrieves a specific leaf value
2303
 * This function creates a new data definition
2304
 * Returns 1 if successful or -1 on error
2305
 */
2306
int libesedb_page_tree_get_leaf_value_by_index(
2307
     libesedb_page_tree_t *page_tree,
2308
     libbfio_handle_t *file_io_handle,
2309
     int leaf_value_index,
2310
     libesedb_data_definition_t **data_definition,
2311
     libcerror_error_t **error )
2312
399
{
2313
399
  libcdata_tree_node_t *upper_node                               = NULL;
2314
399
  libesedb_leaf_page_descriptor_t *existing_leaf_page_descriptor = NULL;
2315
399
  libesedb_leaf_page_descriptor_t *leaf_page_descriptor          = NULL;
2316
399
  libesedb_page_t *base_page                                     = NULL;
2317
399
  libfcache_cache_t *base_page_cache                             = NULL;
2318
399
  static char *function                                          = "libesedb_page_tree_get_leaf_value_by_index";
2319
399
  uint32_t base_page_number                                      = 0;
2320
399
  int current_leaf_value_index                                   = 0;
2321
399
  int number_of_leaf_values                                      = 0;
2322
399
  int result                                                     = 0;
2323
2324
399
  if( page_tree == NULL )
2325
0
  {
2326
0
    libcerror_error_set(
2327
0
     error,
2328
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2329
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2330
0
     "%s: invalid page tree.",
2331
0
     function );
2332
2333
0
    return( -1 );
2334
0
  }
2335
399
  if( leaf_value_index < 0 )
2336
0
  {
2337
0
    libcerror_error_set(
2338
0
     error,
2339
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2340
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2341
0
     "%s: invalid leaf value index value out of bounds.",
2342
0
     function );
2343
2344
0
    goto on_error;
2345
0
  }
2346
399
  if( data_definition == NULL )
2347
0
  {
2348
0
    libcerror_error_set(
2349
0
     error,
2350
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2351
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2352
0
     "%s: invalid data definition.",
2353
0
     function );
2354
2355
0
    return( -1 );
2356
0
  }
2357
399
  if( page_tree->number_of_leaf_values == -1 )
2358
0
  {
2359
    /* libesedb_page_tree_get_number_of_leaf_values is called to build the leaf_page_descriptors_tree
2360
     */
2361
0
    if( libesedb_page_tree_get_number_of_leaf_values(
2362
0
         page_tree,
2363
0
         file_io_handle,
2364
0
         &number_of_leaf_values,
2365
0
         error ) != 1 )
2366
0
    {
2367
0
      libcerror_error_set(
2368
0
       error,
2369
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2370
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2371
0
       "%s: unable to retrieve number of leaf values from page: %" PRIu32 ".",
2372
0
       function,
2373
0
       page_tree->root_page_number );
2374
2375
0
      goto on_error;
2376
0
    }
2377
0
  }
2378
399
  base_page_number = page_tree->root_page_number;
2379
2380
399
  if( libesedb_leaf_page_descriptor_initialize(
2381
399
       &leaf_page_descriptor,
2382
399
       error ) != 1 )
2383
0
  {
2384
0
    libcerror_error_set(
2385
0
     error,
2386
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2387
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2388
0
     "%s: unable to create leaf page descriptor.",
2389
0
     function );
2390
2391
0
    goto on_error;
2392
0
  }
2393
399
  leaf_page_descriptor->first_leaf_value_index = leaf_value_index;
2394
399
  leaf_page_descriptor->last_leaf_value_index  = leaf_value_index;
2395
2396
399
  result = libcdata_btree_get_value_by_value(
2397
399
            page_tree->leaf_page_descriptors_tree,
2398
399
            (intptr_t *) leaf_page_descriptor,
2399
399
            (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libesedb_leaf_page_descriptor_compare,
2400
399
            &upper_node,
2401
399
            (intptr_t **) &existing_leaf_page_descriptor,
2402
399
            error );
2403
2404
399
  if( result == -1 )
2405
0
  {
2406
0
    libcerror_error_set(
2407
0
     error,
2408
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2409
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2410
0
     "%s: unable to retrieve leaf page descriptor from tree.",
2411
0
     function );
2412
2413
0
    goto on_error;
2414
0
  }
2415
399
  else if( result != 0 )
2416
399
  {
2417
399
    if( existing_leaf_page_descriptor == NULL )
2418
0
    {
2419
0
      libcerror_error_set(
2420
0
       error,
2421
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2422
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2423
0
       "%s: missing existing leaf page descriptor.",
2424
0
       function );
2425
2426
0
      goto on_error;
2427
0
    }
2428
399
    current_leaf_value_index = existing_leaf_page_descriptor->first_leaf_value_index;
2429
399
    base_page_number         = existing_leaf_page_descriptor->page_number;
2430
399
  }
2431
399
  if( libesedb_leaf_page_descriptor_free(
2432
399
       &leaf_page_descriptor,
2433
399
       error ) != 1 )
2434
0
  {
2435
0
    libcerror_error_set(
2436
0
     error,
2437
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2438
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2439
0
     "%s: unable to free leaf page descriptor.",
2440
0
     function );
2441
2442
0
    goto on_error;
2443
0
  }
2444
        /* Use a local cache to prevent cache invalidation of the root page
2445
         * when reading child pages.
2446
         */
2447
399
  if( libfcache_cache_initialize(
2448
399
       &base_page_cache,
2449
399
       1,
2450
399
       error ) != 1 )
2451
0
  {
2452
0
    libcerror_error_set(
2453
0
     error,
2454
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2455
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2456
0
     "%s: unable to create base page cache.",
2457
0
     function );
2458
2459
0
    goto on_error;
2460
0
  }
2461
399
  if( libfdata_vector_get_element_value_by_index(
2462
399
       page_tree->pages_vector,
2463
399
       (intptr_t *) file_io_handle,
2464
399
       (libfdata_cache_t *) base_page_cache,
2465
399
       (int) base_page_number - 1,
2466
399
       (intptr_t **) &base_page,
2467
399
       0,
2468
399
       error ) != 1 )
2469
0
  {
2470
0
    libcerror_error_set(
2471
0
     error,
2472
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2473
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2474
0
     "%s: unable to retrieve page: %" PRIu32 ".",
2475
0
     function,
2476
0
     base_page_number );
2477
2478
0
    goto on_error;
2479
0
  }
2480
399
  if( base_page_number == page_tree->root_page_number )
2481
226
  {
2482
226
    if( libesedb_page_validate_root_page(
2483
226
         base_page,
2484
226
         error ) != 1 )
2485
2
    {
2486
2
      libcerror_error_set(
2487
2
       error,
2488
2
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2489
2
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2490
2
       "%s: unsupported root page.",
2491
2
       function );
2492
2493
2
      goto on_error;
2494
2
    }
2495
226
  }
2496
397
  if( libesedb_page_tree_get_leaf_value_by_index_from_page(
2497
397
       page_tree,
2498
397
       file_io_handle,
2499
397
       base_page,
2500
397
       leaf_value_index,
2501
397
       data_definition,
2502
397
       &current_leaf_value_index,
2503
397
       0,
2504
397
       error ) != 1 )
2505
19
  {
2506
19
    libcerror_error_set(
2507
19
     error,
2508
19
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2509
19
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2510
19
     "%s: unable to retrieve leaf value: %d from page: %" PRIu32 ".",
2511
19
     function,
2512
19
     leaf_value_index,
2513
19
     base_page_number );
2514
2515
19
    goto on_error;
2516
19
  }
2517
378
  if( current_leaf_value_index != ( leaf_value_index + 1 ) )
2518
0
  {
2519
0
    libcerror_error_set(
2520
0
     error,
2521
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2522
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2523
0
     "%s: invalid current leaf value index value out of bounds.",
2524
0
     function );
2525
2526
0
    goto on_error;
2527
0
  }
2528
378
  if( libfcache_cache_free(
2529
378
       &base_page_cache,
2530
378
       error ) != 1 )
2531
0
  {
2532
0
    libcerror_error_set(
2533
0
     error,
2534
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2535
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2536
0
     "%s: unable to free base page cache.",
2537
0
     function );
2538
2539
0
    goto on_error;
2540
0
  }
2541
378
  return( 1 );
2542
2543
21
on_error:
2544
21
  if( *data_definition != NULL )
2545
0
  {
2546
0
    libesedb_data_definition_free(
2547
0
     data_definition,
2548
0
     NULL );
2549
0
  }
2550
21
  if( leaf_page_descriptor != NULL )
2551
0
  {
2552
0
    libesedb_leaf_page_descriptor_free(
2553
0
     &leaf_page_descriptor,
2554
0
     NULL );
2555
0
  }
2556
21
  if( base_page_cache != NULL )
2557
21
  {
2558
21
    libfcache_cache_free(
2559
21
     &base_page_cache,
2560
21
     NULL );
2561
21
  }
2562
21
  return( -1 );
2563
378
}
2564
2565
/* Retrieves a specific leaf value
2566
 * This function creates a new data definition
2567
 * Returns 1 if successful, 0 if no such value or -1 on error
2568
 */
2569
int libesedb_page_tree_get_leaf_value_by_key_from_page(
2570
     libesedb_page_tree_t *page_tree,
2571
     libbfio_handle_t *file_io_handle,
2572
     libesedb_page_t *page,
2573
     libesedb_page_tree_key_t *leaf_value_key,
2574
     libesedb_data_definition_t **data_definition,
2575
     int recursion_depth,
2576
     libcerror_error_t **error )
2577
0
{
2578
0
  libesedb_page_tree_key_t *page_value_key    = NULL;
2579
0
  libesedb_page_t *child_page                 = NULL;
2580
0
  libesedb_page_tree_value_t *page_tree_value = NULL;
2581
0
  libesedb_page_value_t *page_value           = NULL;
2582
0
  libfcache_cache_t *child_page_cache         = NULL;
2583
0
  static char *function                       = "libesedb_page_tree_get_leaf_value_by_key_from_page";
2584
0
  uint32_t child_page_number                  = 0;
2585
0
  uint32_t page_flags                         = 0;
2586
0
  uint16_t data_offset                        = 0;
2587
0
  uint16_t number_of_page_values              = 0;
2588
0
  uint16_t page_value_index                   = 0;
2589
0
  int compare_result                          = 0;
2590
0
  int result                                  = 0;
2591
2592
0
  if( page_tree == NULL )
2593
0
  {
2594
0
    libcerror_error_set(
2595
0
     error,
2596
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2597
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2598
0
     "%s: invalid page tree.",
2599
0
     function );
2600
2601
0
    return( -1 );
2602
0
  }
2603
0
  if( page_tree->io_handle == NULL )
2604
0
  {
2605
0
    libcerror_error_set(
2606
0
     error,
2607
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2608
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2609
0
     "%s: invalid page tree - missing IO handle.",
2610
0
     function );
2611
2612
0
    return( -1 );
2613
0
  }
2614
0
  if( data_definition == NULL )
2615
0
  {
2616
0
    libcerror_error_set(
2617
0
     error,
2618
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2619
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2620
0
     "%s: invalid data definition.",
2621
0
     function );
2622
2623
0
    return( -1 );
2624
0
  }
2625
0
  if( ( recursion_depth < 0 )
2626
0
   || ( recursion_depth > LIBESEDB_MAXIMUM_INDEX_NODE_RECURSION_DEPTH ) )
2627
0
  {
2628
0
    libcerror_error_set(
2629
0
     error,
2630
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2631
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2632
0
     "%s: invalid recursion depth value out of bounds.",
2633
0
     function );
2634
2635
0
    return( -1 );
2636
0
  }
2637
0
  if( libesedb_page_get_number_of_values(
2638
0
       page,
2639
0
       &number_of_page_values,
2640
0
       error ) != 1 )
2641
0
  {
2642
0
    libcerror_error_set(
2643
0
     error,
2644
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2645
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2646
0
     "%s: unable to retrieve number of page values.",
2647
0
     function );
2648
2649
0
    goto on_error;
2650
0
  }
2651
0
  if( number_of_page_values == 0 )
2652
0
  {
2653
0
    return( 1 );
2654
0
  }
2655
0
  if( libesedb_page_get_flags(
2656
0
       page,
2657
0
       &page_flags,
2658
0
       error ) != 1 )
2659
0
  {
2660
0
    libcerror_error_set(
2661
0
     error,
2662
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2663
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2664
0
     "%s: unable to retrieve page flags.",
2665
0
     function );
2666
2667
0
    goto on_error;
2668
0
  }
2669
        /* Use a local cache to prevent cache invalidation of the page
2670
         * when reading child pages.
2671
         */
2672
0
  if( libfcache_cache_initialize(
2673
0
       &child_page_cache,
2674
0
       1,
2675
0
       error ) != 1 )
2676
0
  {
2677
0
    libcerror_error_set(
2678
0
     error,
2679
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2680
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2681
0
     "%s: unable to create child page cache.",
2682
0
     function );
2683
2684
0
    goto on_error;
2685
0
  }
2686
0
  for( page_value_index = 1;
2687
0
       page_value_index < number_of_page_values;
2688
0
       page_value_index++ )
2689
0
  {
2690
0
    if( libesedb_page_get_value_by_index(
2691
0
         page,
2692
0
         page_value_index,
2693
0
         &page_value,
2694
0
         error ) != 1 )
2695
0
    {
2696
0
      libcerror_error_set(
2697
0
       error,
2698
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2699
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2700
0
       "%s: unable to retrieve page value: %" PRIu16 ".",
2701
0
       function,
2702
0
       page_value_index );
2703
2704
0
      goto on_error;
2705
0
    }
2706
0
    if( page_value == NULL )
2707
0
    {
2708
0
      libcerror_error_set(
2709
0
       error,
2710
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2711
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2712
0
       "%s: missing page value: %" PRIu16 ".",
2713
0
       function,
2714
0
       page_value_index );
2715
2716
0
      goto on_error;
2717
0
    }
2718
#if defined( HAVE_DEBUG_OUTPUT )
2719
    if( libcnotify_verbose != 0 )
2720
    {
2721
      libcnotify_printf(
2722
       "%s: page value: %03" PRIu16 " page tag flags\t\t: 0x%02" PRIx8 "",
2723
       function,
2724
       page_value_index,
2725
       page_value->flags );
2726
      libesedb_debug_print_page_tag_flags(
2727
       page_value->flags );
2728
      libcnotify_printf(
2729
       "\n" );
2730
    }
2731
#endif
2732
0
    if( ( page_value->flags & LIBESEDB_PAGE_TAG_FLAG_IS_DEFUNCT ) != 0 )
2733
0
    {
2734
0
      continue;
2735
0
    }
2736
0
    if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_ROOT ) != 0 )
2737
0
    {
2738
0
      if( ( page_value->flags & LIBESEDB_PAGE_TAG_FLAG_HAS_COMMON_KEY_SIZE ) != 0 )
2739
0
      {
2740
0
        libcerror_error_set(
2741
0
         error,
2742
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2743
0
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2744
0
         "%s: unsupported page - root flag is set and page value: %" PRIu16 " has common key.",
2745
0
         function,
2746
0
         page_value_index );
2747
2748
0
        goto on_error;
2749
0
      }
2750
0
    }
2751
0
    if( libesedb_page_tree_value_initialize(
2752
0
         &page_tree_value,
2753
0
         error ) != 1 )
2754
0
    {
2755
0
      libcerror_error_set(
2756
0
       error,
2757
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2758
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2759
0
       "%s: unable to create page tree value.",
2760
0
       function );
2761
2762
0
      goto on_error;
2763
0
    }
2764
0
    if( libesedb_page_tree_value_read_data(
2765
0
         page_tree_value,
2766
0
         page_value->data,
2767
0
         (size_t) page_value->size,
2768
0
         page_value->flags,
2769
0
         error ) != 1 )
2770
0
    {
2771
0
      libcerror_error_set(
2772
0
       error,
2773
0
       LIBCERROR_ERROR_DOMAIN_IO,
2774
0
       LIBCERROR_IO_ERROR_READ_FAILED,
2775
0
       "%s: unable to read page tree value: %" PRIu16 ".",
2776
0
       function,
2777
0
       page_value_index );
2778
2779
0
      goto on_error;
2780
0
    }
2781
0
    if( libesedb_page_tree_get_key(
2782
0
         page_tree,
2783
0
         page_tree_value,
2784
0
         page,
2785
0
         page_flags,
2786
0
         page_value_index,
2787
0
         &page_value_key,
2788
0
         error ) != 1 )
2789
0
    {
2790
0
      libcerror_error_set(
2791
0
       error,
2792
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2793
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2794
0
       "%s: unable to retrieve key of page value: %" PRIu16 ".",
2795
0
       function,
2796
0
       page_value_index );
2797
2798
0
      goto on_error;
2799
0
    }
2800
0
    compare_result = libesedb_page_tree_key_compare(
2801
0
                      leaf_value_key,
2802
0
                      page_value_key,
2803
0
                      error );
2804
2805
0
    if( compare_result == -1 )
2806
0
    {
2807
0
      libcerror_error_set(
2808
0
       error,
2809
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2810
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
2811
0
       "%s: unable to compare page value: %" PRIu16 " and leaf value keys.",
2812
0
       function,
2813
0
       page_value_index );
2814
2815
0
      goto on_error;
2816
0
    }
2817
0
    if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_LEAF ) != 0 )
2818
0
    {
2819
0
      if( compare_result == LIBFDATA_COMPARE_EQUAL )
2820
0
      {
2821
0
        if( libesedb_data_definition_initialize(
2822
0
             data_definition,
2823
0
             error ) != 1 )
2824
0
        {
2825
0
          libcerror_error_set(
2826
0
           error,
2827
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2828
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2829
0
           "%s: unable to create data definition.",
2830
0
           function );
2831
2832
0
          goto on_error;
2833
0
        }
2834
0
        data_offset = page_value->offset + 2 + page_tree_value->local_key_size;
2835
2836
0
        if( ( page_value->flags & LIBESEDB_PAGE_TAG_FLAG_HAS_COMMON_KEY_SIZE ) != 0 )
2837
0
        {
2838
0
          data_offset += 2;
2839
0
        }
2840
0
        ( *data_definition )->page_value_index = page_value_index;
2841
0
        ( *data_definition )->page_offset      = page->offset - ( 2 * page_tree->io_handle->page_size );
2842
0
        ( *data_definition )->page_number      = page->page_number;
2843
0
        ( *data_definition )->data_offset      = data_offset;
2844
0
        ( *data_definition )->data_size        = page_tree_value->data_size;
2845
2846
0
        result = 1;
2847
0
      }
2848
0
    }
2849
0
    else if( compare_result != LIBFDATA_COMPARE_GREATER )
2850
0
    {
2851
0
      if( page_tree_value->data_size < 4 )
2852
0
      {
2853
0
        libcerror_error_set(
2854
0
         error,
2855
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2856
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2857
0
         "%s: invalid page tree value: %" PRIu16 " data size value out of bounds.",
2858
0
         function,
2859
0
         page_value_index );
2860
2861
0
        goto on_error;
2862
0
      }
2863
0
      byte_stream_copy_to_uint32_little_endian(
2864
0
       page_tree_value->data,
2865
0
       child_page_number );
2866
2867
#if defined( HAVE_DEBUG_OUTPUT )
2868
      if( libcnotify_verbose != 0 )
2869
      {
2870
        libcnotify_printf(
2871
         "%s: page value: %03" PRIu16 " child page number\t: %" PRIu32 "",
2872
         function,
2873
         page_value_index,
2874
         child_page_number );
2875
2876
        if( child_page_number == 0 )
2877
        {
2878
          libcnotify_printf(
2879
           " (invalid page number)\n" );
2880
        }
2881
        else if( child_page_number > page_tree->io_handle->last_page_number )
2882
        {
2883
          libcnotify_printf(
2884
           " (exceeds last page number: %" PRIu32 ")\n",
2885
           page_tree->io_handle->last_page_number );
2886
        }
2887
        libcnotify_printf(
2888
         "\n" );
2889
        libcnotify_printf(
2890
         "\n" );
2891
      }
2892
#endif
2893
0
#if ( SIZEOF_INT <= 4 )
2894
0
      if( ( child_page_number < 1 )
2895
0
       || ( child_page_number > (uint32_t) INT_MAX ) )
2896
#else
2897
      if( ( child_page_number < 1 )
2898
       || ( (int) child_page_number > INT_MAX ) )
2899
#endif
2900
0
      {
2901
0
        libcerror_error_set(
2902
0
         error,
2903
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2904
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2905
0
         "%s: invalid child page number value out of bounds.",
2906
0
         function );
2907
2908
0
        goto on_error;
2909
0
      }
2910
#if defined( HAVE_DEBUG_OUTPUT )
2911
      if( libcnotify_verbose != 0 )
2912
      {
2913
        if( page_tree_value->data_size > 4 )
2914
        {
2915
          libcnotify_printf(
2916
           "%s: page value: %03" PRIu16 " trailing data:\n",
2917
           function,
2918
           page_value_index );
2919
          libcnotify_print_data(
2920
           &( page_tree_value->data[ 4 ] ),
2921
           page_tree_value->data_size - 4,
2922
           LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
2923
        }
2924
      }
2925
#endif
2926
0
      if( ( child_page_number > 0 )
2927
0
       && ( child_page_number <= page_tree->io_handle->last_page_number ) )
2928
0
      {
2929
0
        if( libfdata_vector_get_element_value_by_index(
2930
0
             page_tree->pages_vector,
2931
0
             (intptr_t *) file_io_handle,
2932
0
             (libfdata_cache_t *) child_page_cache,
2933
0
             (int) child_page_number - 1,
2934
0
             (intptr_t **) &child_page,
2935
0
             0,
2936
0
             error ) != 1 )
2937
0
        {
2938
0
          libcerror_error_set(
2939
0
           error,
2940
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2941
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2942
0
           "%s: unable to retrieve page: %" PRIu32 ".",
2943
0
           function,
2944
0
           child_page_number );
2945
2946
0
          goto on_error;
2947
0
        }
2948
0
        if( libesedb_page_validate_page(
2949
0
             child_page,
2950
0
             error ) != 1 )
2951
0
        {
2952
0
          libcerror_error_set(
2953
0
           error,
2954
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2955
0
           LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2956
0
           "%s: unsupported page.",
2957
0
           function );
2958
2959
0
          goto on_error;
2960
0
        }
2961
0
        result = libesedb_page_tree_get_leaf_value_by_key_from_page(
2962
0
                  page_tree,
2963
0
                  file_io_handle,
2964
0
                  child_page,
2965
0
                  leaf_value_key,
2966
0
                  data_definition,
2967
0
                  recursion_depth + 1,
2968
0
                  error );
2969
2970
0
        if( result == -1 )
2971
0
        {
2972
0
          libcerror_error_set(
2973
0
           error,
2974
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2975
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2976
0
           "%s: unable to retrieve leaf value from page: %" PRIu32 ".",
2977
0
           function,
2978
0
           child_page_number );
2979
2980
0
          goto on_error;
2981
0
        }
2982
0
      }
2983
0
    }
2984
0
    if( libesedb_page_tree_key_free(
2985
0
         &page_value_key,
2986
0
         error ) != 1 )
2987
0
    {
2988
0
      libcerror_error_set(
2989
0
       error,
2990
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2991
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2992
0
       "%s: unable to free page value key.",
2993
0
       function );
2994
2995
0
      goto on_error;
2996
0
    }
2997
0
    if( libesedb_page_tree_value_free(
2998
0
         &page_tree_value,
2999
0
         error ) != 1 )
3000
0
    {
3001
0
      libcerror_error_set(
3002
0
       error,
3003
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3004
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
3005
0
       "%s: unable to free page tree value.",
3006
0
       function );
3007
3008
0
      goto on_error;
3009
0
    }
3010
0
    if( result != 0 )
3011
0
    {
3012
0
      break;
3013
0
    }
3014
0
  }
3015
0
  if( libfcache_cache_free(
3016
0
       &child_page_cache,
3017
0
       error ) != 1 )
3018
0
  {
3019
0
    libcerror_error_set(
3020
0
     error,
3021
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3022
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
3023
0
     "%s: unable to free child page cache.",
3024
0
     function );
3025
3026
0
    goto on_error;
3027
0
  }
3028
0
  return( result );
3029
3030
0
on_error:
3031
0
  if( *data_definition != NULL )
3032
0
  {
3033
0
    libesedb_data_definition_free(
3034
0
     data_definition,
3035
0
     NULL );
3036
0
  }
3037
0
  if( page_value_key != NULL )
3038
0
  {
3039
0
    libesedb_page_tree_key_free(
3040
0
     &page_value_key,
3041
0
     NULL );
3042
0
  }
3043
0
  if( page_tree_value != NULL )
3044
0
  {
3045
0
    libesedb_page_tree_value_free(
3046
0
     &page_tree_value,
3047
0
     NULL );
3048
0
  }
3049
0
  if( child_page_cache != NULL )
3050
0
  {
3051
0
    libfcache_cache_free(
3052
0
     &child_page_cache,
3053
0
     NULL );
3054
0
  }
3055
0
  return( -1 );
3056
0
}
3057
3058
/* Retrieves a specific leaf value
3059
 * This function creates a new data definition
3060
 * Returns 1 if successful, 0 if no such value or -1 on error
3061
 */
3062
int libesedb_page_tree_get_leaf_value_by_key(
3063
     libesedb_page_tree_t *page_tree,
3064
     libbfio_handle_t *file_io_handle,
3065
     libesedb_page_tree_key_t *leaf_value_key,
3066
     libesedb_data_definition_t **data_definition,
3067
     libcerror_error_t **error )
3068
0
{
3069
0
  libesedb_page_t *root_page         = NULL;
3070
0
  libfcache_cache_t *root_page_cache = NULL;
3071
0
  static char *function              = "libesedb_page_tree_get_leaf_value_by_key";
3072
0
  int result                         = 0;
3073
3074
0
  if( page_tree == NULL )
3075
0
  {
3076
0
    libcerror_error_set(
3077
0
     error,
3078
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3079
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3080
0
     "%s: invalid page tree.",
3081
0
     function );
3082
3083
0
    return( -1 );
3084
0
  }
3085
  /* Use a local cache to prevent cache invalidation of the root page
3086
   * when reading child pages.
3087
   */
3088
0
  if( libfcache_cache_initialize(
3089
0
       &root_page_cache,
3090
0
       1,
3091
0
       error ) != 1 )
3092
0
  {
3093
0
    libcerror_error_set(
3094
0
     error,
3095
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3096
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3097
0
     "%s: unable to create root page cache.",
3098
0
     function );
3099
3100
0
    goto on_error;
3101
0
  }
3102
0
  if( libfdata_vector_get_element_value_by_index(
3103
0
       page_tree->pages_vector,
3104
0
       (intptr_t *) file_io_handle,
3105
0
       (libfdata_cache_t *) root_page_cache,
3106
0
       (int) page_tree->root_page_number - 1,
3107
0
       (intptr_t **) &root_page,
3108
0
       0,
3109
0
       error ) != 1 )
3110
0
  {
3111
0
    libcerror_error_set(
3112
0
     error,
3113
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3114
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3115
0
     "%s: unable to retrieve page: %" PRIu32 ".",
3116
0
     function,
3117
0
     page_tree->root_page_number );
3118
3119
0
    goto on_error;
3120
0
  }
3121
0
  if( libesedb_page_validate_root_page(
3122
0
       root_page,
3123
0
       error ) != 1 )
3124
0
  {
3125
0
    libcerror_error_set(
3126
0
     error,
3127
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3128
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
3129
0
     "%s: unsupported root page.",
3130
0
     function );
3131
3132
0
    goto on_error;
3133
0
  }
3134
#if defined( HAVE_DEBUG_OUTPUT )
3135
  if( page_tree->root_page_header == NULL )
3136
  {
3137
    if( libesedb_page_tree_read_root_page_header(
3138
         page_tree,
3139
         root_page,
3140
         error ) != 1 )
3141
    {
3142
      libcerror_error_set(
3143
       error,
3144
       LIBCERROR_ERROR_DOMAIN_IO,
3145
       LIBCERROR_IO_ERROR_READ_FAILED,
3146
       "%s: unable to read root page header.",
3147
       function );
3148
3149
      goto on_error;
3150
    }
3151
  }
3152
#endif
3153
0
  result = libesedb_page_tree_get_leaf_value_by_key_from_page(
3154
0
            page_tree,
3155
0
            file_io_handle,
3156
0
            root_page,
3157
0
            leaf_value_key,
3158
0
            data_definition,
3159
0
            0,
3160
0
            error );
3161
3162
0
  if( result == -1 )
3163
0
  {
3164
0
    libcerror_error_set(
3165
0
     error,
3166
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3167
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3168
0
     "%s: unable to retrieve leaf value from page: %" PRIu32 ".",
3169
0
     function,
3170
0
     page_tree->root_page_number );
3171
3172
0
    goto on_error;
3173
0
  }
3174
0
  if( libfcache_cache_free(
3175
0
       &root_page_cache,
3176
0
       error ) != 1 )
3177
0
  {
3178
0
    libcerror_error_set(
3179
0
     error,
3180
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3181
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
3182
0
     "%s: unable to free root page cache.",
3183
0
     function );
3184
3185
0
    goto on_error;
3186
0
  }
3187
0
  return( result );
3188
3189
0
on_error:
3190
0
  if( root_page_cache != NULL )
3191
0
  {
3192
0
    libfcache_cache_free(
3193
0
     &root_page_cache,
3194
0
     NULL );
3195
0
  }
3196
0
  return( -1 );
3197
0
}
3198
3199
#ifdef TODO
3200
/* TODO refactor */
3201
3202
  if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_LEAF ) != 0 )
3203
  {
3204
      if( libcnotify_verbose != 0 )
3205
      {
3206
        if( page_value_index > 1 )
3207
        {
3208
          if( child_page->page_number != previous_next_child_page_number )
3209
          {
3210
            libcnotify_printf(
3211
             "%s: mismatch in child page number (%" PRIu32 " != %" PRIu32 ").\n",
3212
             function,
3213
             previous_next_child_page_number,
3214
             child_page->page_number );
3215
          }
3216
          if( child_page->header->previous_page_number != previous_child_page_number )
3217
          {
3218
            libcnotify_printf(
3219
             "%s: mismatch in previous child page number (%" PRIu32 " != %" PRIu32 ").\n",
3220
             function,
3221
             previous_child_page_number,
3222
             child_page->header->previous_page_number );
3223
          }
3224
        }
3225
/* TODO need the actual values for the following checks
3226
        if( page_value_index == 1 )
3227
        {
3228
          if( child_page->header->previous_page_number != 0 )
3229
          {
3230
            libcnotify_printf(
3231
             "%s: mismatch in previous child page number (%" PRIu32 " != %" PRIu32 ").",
3232
             function,
3233
             0,
3234
             child_page->header->previous_page_number );
3235
          }
3236
        }
3237
        if( page_value_index == ( number_of_page_values - 1 ) )
3238
        {
3239
          if( child_page->header->next_page_number != 0 )
3240
          {
3241
            libcnotify_printf(
3242
             "%s: mismatch in next child page number (%" PRIu32 " != %" PRIu32 ").",
3243
             function,
3244
             0,
3245
             child_page->header->previous_page_number );
3246
          }
3247
        }
3248
*/
3249
      }
3250
      previous_child_page_number      = child_page->page_number;
3251
      previous_next_child_page_number = child_page->header->next_page_number;
3252
  }
3253
#endif /* TODO */
3254