Coverage Report

Created: 2024-02-25 07:19

/src/libesedb/libesedb/libesedb_page.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Page 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_checksum.h"
28
#include "libesedb_debug.h"
29
#include "libesedb_definitions.h"
30
#include "libesedb_libbfio.h"
31
#include "libesedb_libcdata.h"
32
#include "libesedb_libcerror.h"
33
#include "libesedb_libcnotify.h"
34
#include "libesedb_page.h"
35
#include "libesedb_page_header.h"
36
#include "libesedb_page_value.h"
37
38
#include "esedb_page.h"
39
40
/* Creates a page
41
 * Make sure the value page is referencing, is set to NULL
42
 * Returns 1 if successful or -1 on error
43
 */
44
int libesedb_page_initialize(
45
     libesedb_page_t **page,
46
     libcerror_error_t **error )
47
2.49k
{
48
2.49k
  static char *function = "libesedb_page_initialize";
49
50
2.49k
  if( page == NULL )
51
0
  {
52
0
    libcerror_error_set(
53
0
     error,
54
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
55
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
56
0
     "%s: invalid page.",
57
0
     function );
58
59
0
    return( -1 );
60
0
  }
61
2.49k
  if( *page != NULL )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
66
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
67
0
     "%s: invalid page value already set.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
2.49k
  *page = memory_allocate_structure(
73
2.49k
           libesedb_page_t );
74
75
2.49k
  if( *page == NULL )
76
0
  {
77
0
    libcerror_error_set(
78
0
     error,
79
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
80
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
81
0
     "%s: unable to create page.",
82
0
     function );
83
84
0
    goto on_error;
85
0
  }
86
2.49k
  if( memory_set(
87
2.49k
       *page,
88
2.49k
       0,
89
2.49k
       sizeof( libesedb_page_t ) ) == NULL )
90
0
  {
91
0
    libcerror_error_set(
92
0
     error,
93
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
94
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
95
0
     "%s: unable to clear page.",
96
0
     function );
97
98
0
    memory_free(
99
0
     *page );
100
101
0
    *page = NULL;
102
103
0
    return( -1 );
104
0
  }
105
2.49k
  if( libesedb_page_header_initialize(
106
2.49k
       &( ( *page )->header ),
107
2.49k
       error ) != 1 )
108
0
  {
109
0
    libcerror_error_set(
110
0
     error,
111
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
112
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
113
0
     "%s: unable to create header.",
114
0
     function );
115
116
0
    goto on_error;
117
0
  }
118
2.49k
  if( libcdata_array_initialize(
119
2.49k
       &( ( *page )->values_array ),
120
2.49k
       0,
121
2.49k
       error ) != 1 )
122
0
  {
123
0
    libcerror_error_set(
124
0
     error,
125
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
126
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
127
0
     "%s: unable to create values array.",
128
0
     function );
129
130
0
    goto on_error;
131
0
  }
132
2.49k
  return( 1 );
133
134
0
on_error:
135
0
  if( *page != NULL )
136
0
  {
137
0
    if( ( *page )->header != NULL )
138
0
    {
139
0
      libesedb_page_header_free(
140
0
       &( ( *page )->header ),
141
0
       NULL );
142
0
    }
143
0
    memory_free(
144
0
     *page );
145
146
0
    *page = NULL;
147
0
  }
148
0
  return( -1 );
149
2.49k
}
150
151
/* Frees a page
152
 * Returns 1 if successful or -1 on error
153
 */
154
int libesedb_page_free(
155
     libesedb_page_t **page,
156
     libcerror_error_t **error )
157
2.49k
{
158
2.49k
  static char *function = "libesedb_page_free";
159
2.49k
  int result            = 1;
160
161
2.49k
  if( page == NULL )
162
0
  {
163
0
    libcerror_error_set(
164
0
     error,
165
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
166
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
167
0
     "%s: invalid page.",
168
0
     function );
169
170
0
    return( -1 );
171
0
  }
172
2.49k
  if( *page != NULL )
173
2.49k
  {
174
2.49k
    if( libesedb_page_header_free(
175
2.49k
         &( ( *page )->header ),
176
2.49k
         error ) != 1 )
177
0
    {
178
0
      libcerror_error_set(
179
0
       error,
180
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
181
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
182
0
       "%s: unable to free header.",
183
0
       function );
184
185
0
      result = -1;
186
0
    }
187
2.49k
    if( libcdata_array_free(
188
2.49k
         &( ( *page )->values_array ),
189
2.49k
         (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_value_free,
190
2.49k
         error ) != 1 )
191
0
    {
192
0
      libcerror_error_set(
193
0
       error,
194
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
195
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
196
0
       "%s: unable to free values array.",
197
0
       function );
198
199
0
      result = -1;
200
0
    }
201
2.49k
    if( ( *page )->data != NULL )
202
2.34k
    {
203
2.34k
      memory_free(
204
2.34k
       ( *page )->data );
205
2.34k
    }
206
2.49k
    memory_free(
207
2.49k
     *page );
208
209
2.49k
    *page = NULL;
210
2.49k
  }
211
2.49k
  return( result );
212
2.49k
}
213
214
/* Calculates the page checksums
215
 * Returns 1 if successful, 0 if page is empty or -1 on error
216
 */
217
int libesedb_page_calculate_checksums(
218
     libesedb_page_t *page,
219
     libesedb_io_handle_t *io_handle,
220
     const uint8_t *page_data,
221
     size_t page_data_size,
222
     uint32_t *ecc32_checksum,
223
     uint32_t *xor32_checksum,
224
     libcerror_error_t **error )
225
2.44k
{
226
2.44k
  static char *function = "libesedb_page_calculate_checksums";
227
228
2.44k
  if( page == NULL )
229
0
  {
230
0
    libcerror_error_set(
231
0
     error,
232
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
233
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
234
0
     "%s: invalid page.",
235
0
     function );
236
237
0
    return( -1 );
238
0
  }
239
2.44k
  if( page_data == NULL )
240
0
  {
241
0
    libcerror_error_set(
242
0
     error,
243
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
244
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
245
0
     "%s: invalid page data.",
246
0
     function );
247
248
0
    return( -1 );
249
0
  }
250
2.44k
  if( ( page_data_size < 4 )
251
2.44k
   || ( page_data_size > (size_t) SSIZE_MAX ) )
252
0
  {
253
0
    libcerror_error_set(
254
0
     error,
255
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
256
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
257
0
     "%s: invalid page data size value out of bounds.",
258
0
     function );
259
260
0
    return( -1 );
261
0
  }
262
2.44k
  if( io_handle == NULL )
263
0
  {
264
0
    libcerror_error_set(
265
0
     error,
266
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
267
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
268
0
     "%s: invalid IO handle.",
269
0
     function );
270
271
0
    return( -1 );
272
0
  }
273
/* TODO for now don't bother calculating checksums for uninitialized pages */
274
275
2.44k
  if( ( page_data[ 0 ] == 0 )
276
2.44k
   && ( page_data[ 1 ] == 0 )
277
2.44k
   && ( page_data[ 2 ] == 0 )
278
2.44k
   && ( page_data[ 3 ] == 0 ) )
279
948
  {
280
948
    return( 0 );
281
948
  }
282
1.50k
  if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER )
283
1.50k
   && ( io_handle->page_size >= 16384 ) )
284
321
  {
285
/* TODO calculate checksum */
286
321
  }
287
1.17k
  else if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_NEW_RECORD_FORMAT )
288
1.17k
        && ( ( page->header->flags & LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT ) != 0 ) )
289
457
  {
290
457
    if( libesedb_checksum_calculate_little_endian_ecc32(
291
457
         ecc32_checksum,
292
457
         xor32_checksum,
293
457
         page_data,
294
457
         page_data_size,
295
457
         8,
296
457
         page->page_number,
297
457
         error ) != 1 )
298
0
    {
299
0
      libcerror_error_set(
300
0
       error,
301
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
302
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
303
0
       "%s: unable to calculate ECC-32 and XOR-32 checksum.",
304
0
       function );
305
306
0
      return( -1 );
307
0
    }
308
457
  }
309
722
  else
310
722
  {
311
722
    if( libesedb_checksum_calculate_little_endian_xor32(
312
722
         xor32_checksum,
313
722
         &( page_data[ 4 ] ),
314
722
         page_data_size - 4,
315
722
         0x89abcdef,
316
722
         error ) != 1 )
317
0
    {
318
0
      libcerror_error_set(
319
0
       error,
320
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
321
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
322
0
       "%s: unable to calculate XOR-32 checksum.",
323
0
       function );
324
325
0
      return( -1 );
326
0
    }
327
722
  }
328
1.50k
  return( 1 );
329
1.50k
}
330
331
/* Reads the page tags
332
 * Returns 1 if successful or -1 on error
333
 */
334
int libesedb_page_read_tags(
335
     libesedb_page_t *page,
336
     libesedb_io_handle_t *io_handle,
337
     const uint8_t *page_data,
338
     size_t page_data_size,
339
     uint16_t number_of_page_tags,
340
     libcerror_error_t **error )
341
1.06k
{
342
1.06k
  libesedb_page_value_t *page_value = NULL;
343
1.06k
  const uint8_t *page_tags_data     = NULL;
344
1.06k
  static char *function             = "libesedb_page_read_tags";
345
1.06k
  size_t page_tags_data_size        = 0;
346
1.06k
  uint16_t page_tag_offset          = 0;
347
1.06k
  uint16_t page_tag_size            = 0;
348
1.06k
  uint16_t page_tags_index          = 0;
349
350
1.06k
  if( page == NULL )
351
0
  {
352
0
    libcerror_error_set(
353
0
     error,
354
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
355
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
356
0
     "%s: invalid page.",
357
0
     function );
358
359
0
    return( -1 );
360
0
  }
361
1.06k
  if( io_handle == NULL )
362
0
  {
363
0
    libcerror_error_set(
364
0
     error,
365
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
366
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
367
0
     "%s: invalid IO handle.",
368
0
     function );
369
370
0
    return( -1 );
371
0
  }
372
1.06k
  if( page_data == NULL )
373
0
  {
374
0
    libcerror_error_set(
375
0
     error,
376
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
377
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
378
0
     "%s: invalid page data.",
379
0
     function );
380
381
0
    return( -1 );
382
0
  }
383
1.06k
  if( ( page_data_size < 2 )
384
1.06k
   || ( page_data_size > (size_t) SSIZE_MAX ) )
385
0
  {
386
0
    libcerror_error_set(
387
0
     error,
388
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
389
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
390
0
     "%s: invalid page data size value out of bounds.",
391
0
     function );
392
393
0
    return( -1 );
394
0
  }
395
1.06k
  page_tags_data_size = 4 * number_of_page_tags;
396
397
1.06k
  if( page_tags_data_size > page_data_size )
398
50
  {
399
50
    libcerror_error_set(
400
50
     error,
401
50
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
402
50
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
403
50
     "%s: invalid number of page tags value out of bounds.",
404
50
     function );
405
406
50
    goto on_error;
407
50
  }
408
#if defined( HAVE_DEBUG_OUTPUT )
409
  if( libcnotify_verbose != 0 )
410
  {
411
    libcnotify_printf(
412
     "%s: page tags:\n",
413
     function );
414
    libcnotify_print_data(
415
     &( page_data[ page_data_size - page_tags_data_size ] ),
416
     page_tags_data_size,
417
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
418
  }
419
#endif
420
1.01k
  if( libcdata_array_resize(
421
1.01k
       page->values_array,
422
1.01k
       number_of_page_tags,
423
1.01k
       (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_value_free,
424
1.01k
       error ) != 1 )
425
0
  {
426
0
    libcerror_error_set(
427
0
     error,
428
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
429
0
     LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
430
0
     "%s: unable to resize page values array.",
431
0
     function );
432
433
0
    goto on_error;
434
0
  }
435
  /* Read the page tags back to front
436
   */
437
1.01k
  page_tags_data = &( page_data[ page_data_size - 2 ] );
438
439
1.01k
  for( page_tags_index = 0;
440
269k
       page_tags_index < number_of_page_tags;
441
268k
       page_tags_index++ )
442
268k
  {
443
268k
    if( libesedb_page_value_initialize(
444
268k
         &page_value,
445
268k
         error ) != 1 )
446
0
    {
447
0
      libcerror_error_set(
448
0
       error,
449
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
450
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
451
0
       "%s: unable to create page value.",
452
0
       function );
453
454
0
      goto on_error;
455
0
    }
456
268k
    byte_stream_copy_to_uint16_little_endian(
457
268k
     page_tags_data,
458
268k
     page_tag_offset );
459
460
268k
    page_tags_data -= 2;
461
462
268k
    byte_stream_copy_to_uint16_little_endian(
463
268k
     page_tags_data,
464
268k
     page_tag_size );
465
466
268k
    page_tags_data -= 2;
467
468
268k
    if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER )
469
268k
     && ( io_handle->page_size >= 16384 ) )
470
223k
    {
471
223k
      page_value->flags  = 0;
472
223k
      page_value->offset = page_tag_offset & 0x7fff;
473
223k
      page_value->size   = page_tag_size & 0x7fff;;
474
223k
    }
475
44.2k
    else
476
44.2k
    {
477
44.2k
      page_value->flags  = page_tag_offset >> 13;
478
44.2k
      page_value->offset = page_tag_offset & 0x1fff;
479
44.2k
      page_value->size   = page_tag_size & 0x1fff;
480
44.2k
    }
481
#if defined( HAVE_DEBUG_OUTPUT )
482
    if( libcnotify_verbose != 0 )
483
    {
484
      libcnotify_printf(
485
       "%s: page tag: %03" PRIu16 " offset\t\t\t\t: %" PRIu16 " (0x%04" PRIx16 ")\n",
486
       function,
487
       page_tags_index,
488
       page_value->offset,
489
       page_tag_offset );
490
491
      libcnotify_printf(
492
       "%s: page tag: %03" PRIu16 " size\t\t\t\t: %" PRIu16 " (0x%04" PRIx16 ")\n",
493
       function,
494
       page_tags_index,
495
       page_value->size,
496
       page_tag_size );
497
498
      if( ( io_handle->format_revision < LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER )
499
       && ( io_handle->page_size < 16384 ) )
500
      {
501
        libcnotify_printf(
502
         "%s: page tag: %03" PRIu16 " flags\t\t\t\t: 0x%02" PRIx8 "",
503
         function,
504
         page_tags_index,
505
         page_value->flags );
506
        libesedb_debug_print_page_tag_flags(
507
         page_value->flags );
508
        libcnotify_printf(
509
         "\n" );
510
      }
511
    }
512
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
513
514
268k
    if( libcdata_array_set_entry_by_index(
515
268k
         page->values_array,
516
268k
         (int) page_tags_index,
517
268k
         (intptr_t *) page_value,
518
268k
         error ) != 1 )
519
0
    {
520
0
      libcerror_error_set(
521
0
       error,
522
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
523
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
524
0
       "%s: unable to set page value: %" PRIu16 ".",
525
0
       function,
526
0
       page_tags_index );
527
528
0
      goto on_error;
529
0
    }
530
268k
    page_value = NULL;
531
268k
  }
532
#if defined( HAVE_DEBUG_OUTPUT )
533
  if( libcnotify_verbose != 0 )
534
  {
535
    libcnotify_printf(
536
     "\n" );
537
  }
538
#endif
539
1.01k
  return( 1 );
540
541
50
on_error:
542
50
  if( page_value != NULL )
543
0
  {
544
0
    libesedb_page_value_free(
545
0
     &page_value,
546
0
     NULL );
547
0
  }
548
50
  libcdata_array_empty(
549
50
   page->values_array,
550
50
   (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_value_free,
551
50
   NULL );
552
553
50
  return( -1 );
554
1.01k
}
555
556
/* Reads the page values
557
 * Returns 1 if successful or -1 on error
558
 */
559
int libesedb_page_read_values(
560
     libesedb_page_t *page,
561
     libesedb_io_handle_t *io_handle,
562
     uint8_t *page_data,
563
     size_t page_data_size,
564
     size_t page_values_data_offset,
565
     libcerror_error_t **error )
566
2.44k
{
567
2.44k
  libesedb_page_value_t *page_value = NULL;
568
2.44k
  uint8_t *page_values_data         = NULL;
569
2.44k
  static char *function             = "libesedb_page_read_values";
570
2.44k
  size_t page_tags_data_size        = 0;
571
2.44k
  size_t page_values_data_size      = 0;
572
2.44k
  uint16_t number_of_page_tags      = 0;
573
2.44k
  uint16_t page_tags_index          = 0;
574
575
2.44k
  if( page == NULL )
576
0
  {
577
0
    libcerror_error_set(
578
0
     error,
579
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
580
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
581
0
     "%s: invalid page.",
582
0
     function );
583
584
0
    return( -1 );
585
0
  }
586
2.44k
  if( page_data == NULL )
587
0
  {
588
0
    libcerror_error_set(
589
0
     error,
590
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
591
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
592
0
     "%s: invalid page data.",
593
0
     function );
594
595
0
    return( -1 );
596
0
  }
597
2.44k
  if( page_data_size > (size_t) SSIZE_MAX )
598
0
  {
599
0
    libcerror_error_set(
600
0
     error,
601
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
602
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
603
0
     "%s: invalid page data size value out of bounds.",
604
0
     function );
605
606
0
    return( -1 );
607
0
  }
608
2.44k
  if( io_handle == NULL )
609
0
  {
610
0
    libcerror_error_set(
611
0
     error,
612
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
613
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
614
0
     "%s: invalid IO handle.",
615
0
     function );
616
617
0
    return( -1 );
618
0
  }
619
2.44k
  if( (size_t) page_values_data_offset >= page_data_size )
620
0
  {
621
0
    libcerror_error_set(
622
0
     error,
623
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
624
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
625
0
     "%s: invalid page values data offset value out of bounds.",
626
0
     function );
627
628
0
    return( -1 );
629
0
  }
630
2.44k
  number_of_page_tags = page->header->available_page_tag;
631
632
2.44k
  if( number_of_page_tags == 0 )
633
1.38k
  {
634
1.38k
    return( 1 );
635
1.38k
  }
636
1.06k
  if( libesedb_page_read_tags(
637
1.06k
       page,
638
1.06k
       io_handle,
639
1.06k
       page_data,
640
1.06k
       page_data_size,
641
1.06k
       number_of_page_tags,
642
1.06k
       error ) != 1 )
643
50
  {
644
50
    libcerror_error_set(
645
50
     error,
646
50
     LIBCERROR_ERROR_DOMAIN_IO,
647
50
     LIBCERROR_IO_ERROR_READ_FAILED,
648
50
     "%s: unable to read page tags.",
649
50
     function );
650
651
50
    goto on_error;
652
50
  }
653
  /* The offsets in the page tags are relative after the page header
654
   */
655
1.01k
  page_values_data      = &( page_data[ page_values_data_offset ] );
656
1.01k
  page_values_data_size = page_data_size - page_values_data_offset;
657
1.01k
  page_tags_data_size   = 4 * number_of_page_tags;
658
659
1.01k
  if( page_values_data_size < page_tags_data_size )
660
11
  {
661
11
    libcerror_error_set(
662
11
     error,
663
11
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
664
11
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
665
11
     "%s: invalid page values data size value out of bounds.",
666
11
     function );
667
668
11
    goto on_error;
669
11
  }
670
1.00k
  page_values_data_size -= page_tags_data_size;
671
672
#if defined( HAVE_DEBUG_OUTPUT )
673
  if( libcnotify_verbose != 0 )
674
  {
675
    libcnotify_printf(
676
     "%s: page values data:\n",
677
     function );
678
    libcnotify_print_data(
679
     page_values_data,
680
     page_values_data_size,
681
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
682
  }
683
#endif
684
1.00k
  for( page_tags_index = 0;
685
201k
       page_tags_index < number_of_page_tags;
686
200k
       page_tags_index++ )
687
200k
  {
688
200k
    if( libcdata_array_get_entry_by_index(
689
200k
         page->values_array,
690
200k
         page_tags_index,
691
200k
         (intptr_t **) &page_value,
692
200k
         error ) != 1 )
693
0
    {
694
0
      libcerror_error_set(
695
0
       error,
696
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
697
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
698
0
       "%s: unable to retrieve page value: %" PRIu16 ".",
699
0
       function,
700
0
       page_tags_index );
701
702
0
      goto on_error;
703
0
    }
704
200k
    if( page_value == NULL )
705
0
    {
706
0
      libcerror_error_set(
707
0
       error,
708
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
709
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
710
0
       "%s: invalid page value.",
711
0
       function );
712
713
0
      goto on_error;
714
0
    }
715
200k
    if( page_value->offset >= page_values_data_size )
716
21
    {
717
21
      libcerror_error_set(
718
21
       error,
719
21
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
720
21
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
721
21
       "%s: unsupported page tags value offset value out of bounds.",
722
21
       function );
723
724
#if defined( HAVE_DEBUG_OUTPUT )
725
      if( libcnotify_verbose != 0 )
726
      {
727
        libcnotify_printf(
728
         "%s: page value: %03" PRIu16 " offset: % 5" PRIu16 ", size: % 5" PRIu16 " (page value data size: %" PRIu16 ")\n",
729
         function,
730
         page_tags_index,
731
         page_value->offset,
732
         page_value->size,
733
         page_values_data_size );
734
      }
735
#endif
736
21
      goto on_error;
737
21
    }
738
200k
    if( (size_t) page_value->size > ( page_values_data_size - page_value->offset ) )
739
22
    {
740
22
      libcerror_error_set(
741
22
       error,
742
22
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
743
22
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
744
22
       "%s: unsupported page tags value size value out of bounds.",
745
22
       function );
746
747
#if defined( HAVE_DEBUG_OUTPUT )
748
      if( libcnotify_verbose != 0 )
749
      {
750
        libcnotify_printf(
751
         "%s: page value: %03" PRIu16 " offset: % 5" PRIu16 ", size: % 5" PRIu16 " (page value data size: %" PRIu16 ")\n",
752
         function,
753
         page_tags_index,
754
         page_value->offset,
755
         page_value->size,
756
         page_values_data_size );
757
      }
758
#endif
759
22
      goto on_error;
760
22
    }
761
200k
    if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER )
762
200k
     && ( io_handle->page_size >= 16384 ) )
763
171k
    {
764
171k
      if( page_value->size >= 2 )
765
136k
      {
766
        /* The page tags flags are stored in the upper byte of the first 16-bit value
767
         */
768
136k
        page_value->flags = page_values_data[ page_value->offset + 1 ] >> 5;
769
770
136k
        page_values_data[ page_value->offset + 1 ] &= 0x1f;
771
136k
      }
772
171k
    }
773
#if defined( HAVE_DEBUG_OUTPUT )
774
    if( libcnotify_verbose != 0 )
775
    {
776
      libcnotify_printf(
777
       "%s: page value: %03" PRIu16 " offset: % 5" PRIu16 ", size: % 5" PRIu16 ", flags: 0x%02" PRIx8 "",
778
       function,
779
       page_tags_index,
780
       page_value->offset,
781
       page_value->size,
782
       page_value->flags );
783
      libesedb_debug_print_page_tag_flags(
784
       page_value->flags );
785
      libcnotify_printf(
786
       "\n" );
787
    }
788
#endif
789
200k
    page_value->data    = &( page_values_data[ page_value->offset ] );
790
200k
    page_value->offset += page_values_data_offset;
791
792
#if defined( HAVE_DEBUG_OUTPUT )
793
    if( libcnotify_verbose != 0 )
794
    {
795
      libcnotify_printf(
796
       "%s: page value: %" PRIu16 " data:\n",
797
       function,
798
       page_tags_index );
799
      libcnotify_print_data(
800
       page_value->data,
801
       page_value->size,
802
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
803
    }
804
#endif
805
200k
  }
806
#if defined( HAVE_DEBUG_OUTPUT )
807
  if( libcnotify_verbose != 0 )
808
  {
809
    libcnotify_printf(
810
    "\n" );
811
  }
812
#endif
813
959
  return( 1 );
814
815
104
on_error:
816
104
  libcdata_array_empty(
817
104
   page->values_array,
818
104
   (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_value_free,
819
104
   NULL );
820
821
104
  return( -1 );
822
1.00k
}
823
824
/* Reads a page and its values
825
 * Returns 1 if successful or -1 on error
826
 */
827
int libesedb_page_read_file_io_handle(
828
     libesedb_page_t *page,
829
     libesedb_io_handle_t *io_handle,
830
     libbfio_handle_t *file_io_handle,
831
     off64_t file_offset,
832
     libcerror_error_t **error )
833
2.49k
{
834
2.49k
  static char *function              = "libesedb_page_read_file_io_handle";
835
2.49k
  ssize_t read_count                 = 0;
836
2.49k
  uint32_t calculated_ecc32_checksum = 0;
837
2.49k
  uint32_t calculated_xor32_checksum = 0;
838
2.49k
  int result                         = 0;
839
840
2.49k
  if( page == NULL )
841
0
  {
842
0
    libcerror_error_set(
843
0
     error,
844
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
845
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
846
0
     "%s: invalid page.",
847
0
     function );
848
849
0
    return( -1 );
850
0
  }
851
2.49k
  if( page->data != NULL )
852
0
  {
853
0
    libcerror_error_set(
854
0
     error,
855
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
856
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
857
0
     "%s: invalid page data already set.",
858
0
     function );
859
860
0
    return( -1 );
861
0
  }
862
2.49k
  if( io_handle == NULL )
863
0
  {
864
0
    libcerror_error_set(
865
0
     error,
866
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
867
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
868
0
     "%s: invalid IO handle.",
869
0
     function );
870
871
0
    return( -1 );
872
0
  }
873
2.49k
  page->page_number = (uint32_t) ( ( file_offset - io_handle->page_size ) / io_handle->page_size );
874
2.49k
  page->offset      = file_offset;
875
876
#if defined( HAVE_DEBUG_OUTPUT )
877
  if( libcnotify_verbose != 0 )
878
  {
879
    libcnotify_printf(
880
     "%s: current page number\t\t\t: %" PRIu32 "\n",
881
     function,
882
     page->page_number );
883
884
    libcnotify_printf(
885
     "\n" );
886
  }
887
#endif
888
889
2.49k
  page->data = (uint8_t *) memory_allocate(
890
2.49k
                            (size_t) io_handle->page_size );
891
892
2.49k
  if( page->data == NULL )
893
0
  {
894
0
    libcerror_error_set(
895
0
     error,
896
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
897
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
898
0
     "%s: unable to create page data.",
899
0
     function );
900
901
0
    goto on_error;
902
0
  }
903
2.49k
  page->data_size = (size_t) io_handle->page_size;
904
905
#if defined( HAVE_DEBUG_OUTPUT )
906
  if( libcnotify_verbose != 0 )
907
  {
908
    libcnotify_printf(
909
     "%s: reading page: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
910
     function,
911
     page->page_number,
912
     page->offset,
913
     page->offset );
914
  }
915
#endif
916
2.49k
  read_count = libbfio_handle_read_buffer_at_offset(
917
2.49k
                file_io_handle,
918
2.49k
                page->data,
919
2.49k
                page->data_size,
920
2.49k
                page->offset,
921
2.49k
                error );
922
923
2.49k
  if( read_count != (ssize_t) page->data_size )
924
50
  {
925
50
    libcerror_error_set(
926
50
     error,
927
50
     LIBCERROR_ERROR_DOMAIN_IO,
928
50
     LIBCERROR_IO_ERROR_READ_FAILED,
929
50
     "%s: unable to read page: %" PRIu32 " data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
930
50
     function,
931
50
     page->page_number,
932
50
     page->offset,
933
50
     page->offset );
934
935
50
    goto on_error;
936
50
  }
937
2.44k
  if( libesedb_page_header_read_data(
938
2.44k
       page->header,
939
2.44k
       io_handle,
940
2.44k
       page->data,
941
2.44k
       page->data_size,
942
2.44k
       error ) != 1 )
943
0
  {
944
0
    libcerror_error_set(
945
0
     error,
946
0
     LIBCERROR_ERROR_DOMAIN_IO,
947
0
     LIBCERROR_IO_ERROR_READ_FAILED,
948
0
     "%s: unable to read page header.",
949
0
     function );
950
951
0
    goto on_error;
952
0
  }
953
2.44k
  result = libesedb_page_calculate_checksums(
954
2.44k
            page,
955
2.44k
            io_handle,
956
2.44k
            page->data,
957
2.44k
            page->data_size,
958
2.44k
            &calculated_ecc32_checksum,
959
2.44k
            &calculated_xor32_checksum,
960
2.44k
            error );
961
962
2.44k
  if( result == -1 )
963
0
  {
964
0
    libcerror_error_set(
965
0
     error,
966
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
967
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
968
0
     "%s: unable to calculate page checksums.",
969
0
     function );
970
971
0
    goto on_error;
972
0
  }
973
2.44k
  else if( result != 0 )
974
1.50k
  {
975
1.50k
    if( page->header->xor32_checksum != calculated_xor32_checksum )
976
1.17k
    {
977
#ifdef TODO
978
      libcerror_error_set(
979
       error,
980
       LIBCERROR_ERROR_DOMAIN_INPUT,
981
       LIBCERROR_INPUT_ERROR_CRC_MISMATCH,
982
       "%s: mismatch in page XOR-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).",
983
       function,
984
       page->header->xor32_checksum,
985
       calculated_xor32_checksum );
986
987
      goto on_error;
988
#else
989
1.17k
      if( libcnotify_verbose != 0 )
990
0
      {
991
0
        libcnotify_printf(
992
0
         "%s: mismatch in page XOR-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n",
993
0
         function,
994
0
         page->header->xor32_checksum,
995
0
         calculated_xor32_checksum );
996
0
      }
997
1.17k
#endif
998
1.17k
    }
999
1.50k
    if( page->header->ecc32_checksum != calculated_ecc32_checksum )
1000
457
    {
1001
#ifdef TODO
1002
      libcerror_error_set(
1003
       error,
1004
       LIBCERROR_ERROR_DOMAIN_INPUT,
1005
       LIBCERROR_INPUT_ERROR_CRC_MISMATCH,
1006
       "%s: mismatch in page ECC-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).",
1007
       function,
1008
       page->header->ecc32_checksum,
1009
       calculated_ecc32_checksum );
1010
1011
      goto on_error;
1012
#else
1013
457
      if( libcnotify_verbose != 0 )
1014
0
      {
1015
0
        libcnotify_printf(
1016
0
         "%s: mismatch in page ECC-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n",
1017
0
         function,
1018
0
         page->header->ecc32_checksum,
1019
0
         calculated_ecc32_checksum );
1020
0
      }
1021
457
#endif
1022
457
    }
1023
1.50k
  }
1024
2.44k
  if( libesedb_page_read_values(
1025
2.44k
       page,
1026
2.44k
       io_handle,
1027
2.44k
       page->data,
1028
2.44k
       page->data_size,
1029
2.44k
       page->header->data_size,
1030
2.44k
       error ) != 1 )
1031
104
  {
1032
104
    libcerror_error_set(
1033
104
     error,
1034
104
     LIBCERROR_ERROR_DOMAIN_IO,
1035
104
     LIBCERROR_IO_ERROR_READ_FAILED,
1036
104
     "%s: unable to read page values.",
1037
104
     function );
1038
1039
104
    goto on_error;
1040
104
  }
1041
2.34k
  return( 1 );
1042
1043
154
on_error:
1044
154
  if( page->data != NULL )
1045
154
  {
1046
154
    memory_free(
1047
154
     page->data );
1048
1049
154
    page->data = NULL;
1050
154
  }
1051
154
  return( -1 );
1052
2.44k
}
1053
1054
/* Checks if the page is valid root page
1055
 * Returns 1 if successful or -1 on error
1056
 */
1057
int libesedb_page_validate_root_page(
1058
     libesedb_page_t *page,
1059
     libcerror_error_t **error )
1060
336
{
1061
336
  static char *function         = "libesedb_page_validate_root_page";
1062
336
  uint32_t page_flags           = 0;
1063
336
  uint32_t required_page_flags  = 0;
1064
336
  uint32_t supported_page_flags = 0;
1065
1066
336
  if( page == NULL )
1067
0
  {
1068
0
    libcerror_error_set(
1069
0
     error,
1070
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1071
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1072
0
     "%s: invalid page.",
1073
0
     function );
1074
1075
0
    return( -1 );
1076
0
  }
1077
336
  if( libesedb_page_header_get_flags(
1078
336
       page->header,
1079
336
       &page_flags,
1080
336
       error ) != 1 )
1081
0
  {
1082
0
    libcerror_error_set(
1083
0
     error,
1084
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1085
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1086
0
     "%s: unable to retrieve page flags from header.",
1087
0
     function );
1088
1089
0
    return( -1 );
1090
0
  }
1091
336
  required_page_flags = LIBESEDB_PAGE_FLAG_IS_ROOT;
1092
1093
336
  if( ( page_flags & required_page_flags ) != required_page_flags )
1094
0
  {
1095
0
    libcerror_error_set(
1096
0
     error,
1097
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1098
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1099
0
     "%s: missing required page flags: 0x%08" PRIx32 ".",
1100
0
     function,
1101
0
     page_flags );
1102
1103
0
    return( -1 );
1104
0
  }
1105
336
  if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_EMPTY ) != 0 )
1106
253
  {
1107
253
    return( 1 );
1108
253
  }
1109
83
  supported_page_flags = required_page_flags
1110
83
                       | LIBESEDB_PAGE_FLAG_IS_LEAF
1111
83
                       | LIBESEDB_PAGE_FLAG_IS_PARENT
1112
83
                       | LIBESEDB_PAGE_FLAG_IS_INDEX
1113
83
                       | LIBESEDB_PAGE_FLAG_IS_SPACE_TREE
1114
83
                       | LIBESEDB_PAGE_FLAG_IS_LONG_VALUE
1115
83
                       | LIBESEDB_PAGE_FLAG_0x0400
1116
83
                       | LIBESEDB_PAGE_FLAG_0x0800
1117
83
                       | LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT
1118
83
                       | LIBESEDB_PAGE_FLAG_IS_SCRUBBED
1119
83
                       | LIBESEDB_PAGE_FLAG_0x8000
1120
83
                       | LIBESEDB_PAGE_FLAG_0x10000;
1121
1122
83
  if( ( page_flags & ~( supported_page_flags ) ) != 0 )
1123
22
  {
1124
22
    libcerror_error_set(
1125
22
     error,
1126
22
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1127
22
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1128
22
     "%s: unsupported page flags: 0x%08" PRIx32 ".",
1129
22
     function,
1130
22
     page_flags );
1131
1132
22
    return( -1 );
1133
22
  }
1134
61
  return( 1 );
1135
83
}
1136
1137
/* Checks if the page is valid space tree page
1138
 * Returns 1 if successful or -1 on error
1139
 */
1140
int libesedb_page_validate_space_tree_page(
1141
     libesedb_page_t *page,
1142
     libcerror_error_t **error )
1143
0
{
1144
0
  static char *function         = "libesedb_page_validate_space_tree_page";
1145
0
  uint32_t next_page_number     = 0;
1146
0
  uint32_t page_flags           = 0;
1147
0
  uint32_t previous_page_number = 0;
1148
0
  uint32_t required_page_flags  = 0;
1149
0
  uint32_t supported_page_flags = 0;
1150
1151
0
  if( page == NULL )
1152
0
  {
1153
0
    libcerror_error_set(
1154
0
     error,
1155
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1156
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1157
0
     "%s: invalid page.",
1158
0
     function );
1159
1160
0
    return( -1 );
1161
0
  }
1162
0
  if( libesedb_page_header_get_flags(
1163
0
       page->header,
1164
0
       &page_flags,
1165
0
       error ) != 1 )
1166
0
  {
1167
0
    libcerror_error_set(
1168
0
     error,
1169
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1170
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1171
0
     "%s: unable to retrieve page flags from header.",
1172
0
     function );
1173
1174
0
    return( -1 );
1175
0
  }
1176
0
  required_page_flags = LIBESEDB_PAGE_FLAG_IS_SPACE_TREE;
1177
1178
0
  if( ( page_flags & required_page_flags ) != required_page_flags )
1179
0
  {
1180
0
    libcerror_error_set(
1181
0
     error,
1182
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1183
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1184
0
     "%s: missing required page flags: 0x%08" PRIx32 ".",
1185
0
     function,
1186
0
     page_flags );
1187
1188
0
    return( -1 );
1189
0
  }
1190
0
  if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_EMPTY ) != 0 )
1191
0
  {
1192
0
    return( 1 );
1193
0
  }
1194
0
  supported_page_flags = required_page_flags
1195
0
                       | LIBESEDB_PAGE_FLAG_IS_ROOT
1196
0
                       | LIBESEDB_PAGE_FLAG_IS_LEAF
1197
0
                       | LIBESEDB_PAGE_FLAG_IS_PARENT
1198
0
                       | LIBESEDB_PAGE_FLAG_IS_INDEX
1199
0
                       | LIBESEDB_PAGE_FLAG_IS_LONG_VALUE
1200
0
                       | LIBESEDB_PAGE_FLAG_0x0400
1201
0
                       | LIBESEDB_PAGE_FLAG_0x0800
1202
0
                       | LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT
1203
0
                       | LIBESEDB_PAGE_FLAG_IS_SCRUBBED
1204
0
                       | LIBESEDB_PAGE_FLAG_0x8000
1205
0
                       | LIBESEDB_PAGE_FLAG_0x10000;
1206
1207
0
  if( ( page_flags & ~( supported_page_flags ) ) != 0 )
1208
0
  {
1209
0
    libcerror_error_set(
1210
0
     error,
1211
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1212
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1213
0
     "%s: unsupported page flags: 0x%08" PRIx32 ".",
1214
0
     function,
1215
0
     page_flags );
1216
1217
0
    return( -1 );
1218
0
  }
1219
0
  if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_LEAF ) == 0 )
1220
0
  {
1221
0
    if( libesedb_page_header_get_previous_page_number(
1222
0
         page->header,
1223
0
         &previous_page_number,
1224
0
         error ) != 1 )
1225
0
    {
1226
0
      libcerror_error_set(
1227
0
       error,
1228
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1229
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1230
0
       "%s: unable to retrieve previous page number.",
1231
0
       function );
1232
1233
0
      return( -1 );
1234
0
    }
1235
0
    if( previous_page_number != 0 )
1236
0
    {
1237
0
      libcerror_error_set(
1238
0
       error,
1239
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1240
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1241
0
       "%s: unsupported previous page number: %" PRIu32 ".",
1242
0
       function,
1243
0
       previous_page_number );
1244
1245
0
      return( -1 );
1246
0
    }
1247
0
    if( libesedb_page_header_get_next_page_number(
1248
0
         page->header,
1249
0
         &next_page_number,
1250
0
         error ) != 1 )
1251
0
    {
1252
0
      libcerror_error_set(
1253
0
       error,
1254
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1255
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1256
0
       "%s: unable to retrieve next page number.",
1257
0
       function );
1258
1259
0
      return( -1 );
1260
0
    }
1261
0
    if( next_page_number != 0 )
1262
0
    {
1263
0
      libcerror_error_set(
1264
0
       error,
1265
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1266
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1267
0
       "%s: unsupported next page number: %" PRIu32 ".",
1268
0
       function,
1269
0
       next_page_number );
1270
1271
0
      return( -1 );
1272
0
    }
1273
0
  }
1274
0
  return( 1 );
1275
0
}
1276
1277
/* Checks if the page is valid (regular) page
1278
 * Returns 1 if successful or -1 on error
1279
 */
1280
int libesedb_page_validate_page(
1281
     libesedb_page_t *page,
1282
     libcerror_error_t **error )
1283
2.15k
{
1284
2.15k
  static char *function         = "libesedb_page_validate_page";
1285
2.15k
  uint32_t next_page_number     = 0;
1286
2.15k
  uint32_t page_flags           = 0;
1287
2.15k
  uint32_t previous_page_number = 0;
1288
2.15k
  uint32_t supported_page_flags = 0;
1289
1290
2.15k
  if( page == NULL )
1291
0
  {
1292
0
    libcerror_error_set(
1293
0
     error,
1294
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1295
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1296
0
     "%s: invalid page.",
1297
0
     function );
1298
1299
0
    return( -1 );
1300
0
  }
1301
2.15k
  if( libesedb_page_header_get_flags(
1302
2.15k
       page->header,
1303
2.15k
       &page_flags,
1304
2.15k
       error ) != 1 )
1305
0
  {
1306
0
    libcerror_error_set(
1307
0
     error,
1308
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1309
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1310
0
     "%s: unable to retrieve page flags from header.",
1311
0
     function );
1312
1313
0
    return( -1 );
1314
0
  }
1315
2.15k
  if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_EMPTY ) != 0 )
1316
1.32k
  {
1317
1.32k
    return( 1 );
1318
1.32k
  }
1319
838
  supported_page_flags = LIBESEDB_PAGE_FLAG_IS_ROOT
1320
838
                       | LIBESEDB_PAGE_FLAG_IS_LEAF
1321
838
                       | LIBESEDB_PAGE_FLAG_IS_PARENT
1322
838
                       | LIBESEDB_PAGE_FLAG_IS_INDEX
1323
838
                       | LIBESEDB_PAGE_FLAG_IS_LONG_VALUE
1324
838
                       | LIBESEDB_PAGE_FLAG_0x0400
1325
838
                       | LIBESEDB_PAGE_FLAG_0x0800
1326
838
                       | LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT
1327
838
                       | LIBESEDB_PAGE_FLAG_IS_SCRUBBED
1328
838
                       | LIBESEDB_PAGE_FLAG_0x8000
1329
838
                       | LIBESEDB_PAGE_FLAG_0x10000;
1330
1331
838
  if( ( page_flags & ~( supported_page_flags ) ) != 0 )
1332
25
  {
1333
25
    libcerror_error_set(
1334
25
     error,
1335
25
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1336
25
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1337
25
     "%s: unsupported page flags: 0x%08" PRIx32 ".",
1338
25
     function,
1339
25
     page_flags );
1340
1341
25
    return( -1 );
1342
25
  }
1343
813
  if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_LEAF ) == 0 )
1344
801
  {
1345
801
    if( libesedb_page_header_get_previous_page_number(
1346
801
         page->header,
1347
801
         &previous_page_number,
1348
801
         error ) != 1 )
1349
0
    {
1350
0
      libcerror_error_set(
1351
0
       error,
1352
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1353
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1354
0
       "%s: unable to retrieve previous page number.",
1355
0
       function );
1356
1357
0
      return( -1 );
1358
0
    }
1359
801
    if( previous_page_number != 0 )
1360
40
    {
1361
40
      libcerror_error_set(
1362
40
       error,
1363
40
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1364
40
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1365
40
       "%s: unsupported previous page number: %" PRIu32 ".",
1366
40
       function,
1367
40
       previous_page_number );
1368
1369
40
      return( -1 );
1370
40
    }
1371
761
    if( libesedb_page_header_get_next_page_number(
1372
761
         page->header,
1373
761
         &next_page_number,
1374
761
         error ) != 1 )
1375
0
    {
1376
0
      libcerror_error_set(
1377
0
       error,
1378
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1379
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1380
0
       "%s: unable to retrieve next page number.",
1381
0
       function );
1382
1383
0
      return( -1 );
1384
0
    }
1385
761
    if( next_page_number != 0 )
1386
43
    {
1387
43
      libcerror_error_set(
1388
43
       error,
1389
43
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1390
43
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1391
43
       "%s: unsupported next page number: %" PRIu32 ".",
1392
43
       function,
1393
43
       next_page_number );
1394
1395
43
      return( -1 );
1396
43
    }
1397
761
  }
1398
730
  return( 1 );
1399
813
}
1400
1401
/* Retrieves the previous page number
1402
 * Returns 1 if successful or -1 on error
1403
 */
1404
int libesedb_page_get_previous_page_number(
1405
     libesedb_page_t *page,
1406
     uint32_t *previous_page_number,
1407
     libcerror_error_t **error )
1408
1.42k
{
1409
1.42k
  static char *function = "libesedb_page_get_previous_page_number";
1410
1411
1.42k
  if( page == NULL )
1412
0
  {
1413
0
    libcerror_error_set(
1414
0
     error,
1415
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1416
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1417
0
     "%s: invalid page.",
1418
0
     function );
1419
1420
0
    return( -1 );
1421
0
  }
1422
1.42k
  if( libesedb_page_header_get_previous_page_number(
1423
1.42k
       page->header,
1424
1.42k
       previous_page_number,
1425
1.42k
       error ) != 1 )
1426
0
  {
1427
0
    libcerror_error_set(
1428
0
     error,
1429
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1430
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1431
0
     "%s: unable to retrieve previous page number from header.",
1432
0
     function );
1433
1434
0
    return( -1 );
1435
0
  }
1436
1.42k
  return( 1 );
1437
1.42k
}
1438
1439
/* Retrieves the next page number
1440
 * Returns 1 if successful or -1 on error
1441
 */
1442
int libesedb_page_get_next_page_number(
1443
     libesedb_page_t *page,
1444
     uint32_t *next_page_number,
1445
     libcerror_error_t **error )
1446
818
{
1447
818
  static char *function = "libesedb_page_get_next_page_number";
1448
1449
818
  if( page == NULL )
1450
0
  {
1451
0
    libcerror_error_set(
1452
0
     error,
1453
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1454
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1455
0
     "%s: invalid page.",
1456
0
     function );
1457
1458
0
    return( -1 );
1459
0
  }
1460
818
  if( libesedb_page_header_get_next_page_number(
1461
818
       page->header,
1462
818
       next_page_number,
1463
818
       error ) != 1 )
1464
0
  {
1465
0
    libcerror_error_set(
1466
0
     error,
1467
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1468
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1469
0
     "%s: unable to retrieve next page number from header.",
1470
0
     function );
1471
1472
0
    return( -1 );
1473
0
  }
1474
818
  return( 1 );
1475
818
}
1476
1477
/* Retrieves the father data page object identifier
1478
 * Returns 1 if successful or -1 on error
1479
 */
1480
int libesedb_page_get_father_data_page_object_identifier(
1481
     libesedb_page_t *page,
1482
     uint32_t *father_data_page_object_identifier,
1483
     libcerror_error_t **error )
1484
0
{
1485
0
  static char *function = "libesedb_page_get_father_data_page_object_identifier";
1486
1487
0
  if( page == NULL )
1488
0
  {
1489
0
    libcerror_error_set(
1490
0
     error,
1491
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1492
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1493
0
     "%s: invalid page.",
1494
0
     function );
1495
1496
0
    return( -1 );
1497
0
  }
1498
0
  if( libesedb_page_header_get_father_data_page_object_identifier(
1499
0
       page->header,
1500
0
       father_data_page_object_identifier,
1501
0
       error ) != 1 )
1502
0
  {
1503
0
    libcerror_error_set(
1504
0
     error,
1505
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1506
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1507
0
     "%s: unable to retrieve father data page object identifier from header.",
1508
0
     function );
1509
1510
0
    return( -1 );
1511
0
  }
1512
0
  return( 1 );
1513
0
}
1514
1515
/* Retrieves the flags
1516
 * Returns 1 if successful or -1 on error
1517
 */
1518
int libesedb_page_get_flags(
1519
     libesedb_page_t *page,
1520
     uint32_t *flags,
1521
     libcerror_error_t **error )
1522
6.44k
{
1523
6.44k
  static char *function = "libesedb_page_get_flags";
1524
1525
6.44k
  if( page == 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 page.",
1532
0
     function );
1533
1534
0
    return( -1 );
1535
0
  }
1536
6.44k
  if( libesedb_page_header_get_flags(
1537
6.44k
       page->header,
1538
6.44k
       flags,
1539
6.44k
       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 flags from header.",
1546
0
     function );
1547
1548
0
    return( -1 );
1549
0
  }
1550
6.44k
  return( 1 );
1551
6.44k
}
1552
1553
/* Retrieves the number of page values
1554
 * Returns 1 if successful or -1 on error
1555
 */
1556
int libesedb_page_get_number_of_values(
1557
     libesedb_page_t *page,
1558
     uint16_t *number_of_values,
1559
     libcerror_error_t **error )
1560
3.82k
{
1561
3.82k
  static char *function     = "libesedb_page_get_number_of_values";
1562
3.82k
  int page_number_of_values = 0;
1563
1564
3.82k
  if( page == NULL )
1565
0
  {
1566
0
    libcerror_error_set(
1567
0
     error,
1568
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1569
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1570
0
     "%s: invalid page.",
1571
0
     function );
1572
1573
0
    return( -1 );
1574
0
  }
1575
3.82k
  if( number_of_values == NULL )
1576
0
  {
1577
0
    libcerror_error_set(
1578
0
     error,
1579
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1580
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1581
0
     "%s: invalid number of values.",
1582
0
     function );
1583
1584
0
    return( -1 );
1585
0
  }
1586
3.82k
  if( libcdata_array_get_number_of_entries(
1587
3.82k
       page->values_array,
1588
3.82k
       &page_number_of_values,
1589
3.82k
       error ) != 1 )
1590
0
  {
1591
0
    libcerror_error_set(
1592
0
     error,
1593
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1594
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1595
0
     "%s: unable to retrieve number of values.",
1596
0
     function );
1597
1598
0
    return( -1 );
1599
0
  }
1600
3.82k
  if( page_number_of_values > (int) UINT16_MAX )
1601
0
  {
1602
0
    libcerror_error_set(
1603
0
     error,
1604
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1605
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1606
0
     "%s: invalid number of page values value exceeds maximum.",
1607
0
     function );
1608
1609
0
    return( -1 );
1610
0
  }
1611
3.82k
  *number_of_values = (uint16_t) page_number_of_values;
1612
1613
3.82k
  return( 1 );
1614
3.82k
}
1615
1616
/* Retrieves the page value at the index
1617
 * Returns 1 if successful or -1 on error
1618
 */
1619
int libesedb_page_get_value_by_index(
1620
     libesedb_page_t *page,
1621
     uint16_t value_index,
1622
     libesedb_page_value_t **page_value,
1623
     libcerror_error_t **error )
1624
40.8k
{
1625
40.8k
  static char *function = "libesedb_page_get_value_by_index";
1626
1627
40.8k
  if( page == NULL )
1628
0
  {
1629
0
    libcerror_error_set(
1630
0
     error,
1631
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1632
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1633
0
     "%s: invalid page.",
1634
0
     function );
1635
1636
0
    return( -1 );
1637
0
  }
1638
40.8k
  if( libcdata_array_get_entry_by_index(
1639
40.8k
       page->values_array,
1640
40.8k
       (int) value_index,
1641
40.8k
       (intptr_t **) page_value,
1642
40.8k
       error ) != 1 )
1643
0
  {
1644
0
    libcerror_error_set(
1645
0
     error,
1646
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1647
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1648
0
     "%s: unable to retrieve page value: %" PRIu16 ".",
1649
0
     function,
1650
0
     value_index );
1651
1652
0
    return( -1 );
1653
0
  }
1654
40.8k
  return( 1 );
1655
40.8k
}
1656