Coverage Report

Created: 2025-09-05 06:58

/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
12.2k
{
48
12.2k
  static char *function = "libesedb_page_initialize";
49
50
12.2k
  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
12.2k
  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
12.2k
  *page = memory_allocate_structure(
73
12.2k
           libesedb_page_t );
74
75
12.2k
  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
12.2k
  if( memory_set(
87
12.2k
       *page,
88
12.2k
       0,
89
12.2k
       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
12.2k
  if( libesedb_page_header_initialize(
106
12.2k
       &( ( *page )->header ),
107
12.2k
       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
12.2k
  if( libcdata_array_initialize(
119
12.2k
       &( ( *page )->values_array ),
120
12.2k
       0,
121
12.2k
       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
12.2k
  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
12.2k
}
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
12.2k
{
158
12.2k
  static char *function = "libesedb_page_free";
159
12.2k
  int result            = 1;
160
161
12.2k
  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
12.2k
  if( *page != NULL )
173
12.2k
  {
174
12.2k
    if( libesedb_page_header_free(
175
12.2k
         &( ( *page )->header ),
176
12.2k
         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
12.2k
    if( libcdata_array_free(
188
12.2k
         &( ( *page )->values_array ),
189
12.2k
         (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_value_free,
190
12.2k
         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
12.2k
    if( ( *page )->data != NULL )
202
11.6k
    {
203
11.6k
      memory_free(
204
11.6k
       ( *page )->data );
205
11.6k
    }
206
12.2k
    memory_free(
207
12.2k
     *page );
208
209
12.2k
    *page = NULL;
210
12.2k
  }
211
12.2k
  return( result );
212
12.2k
}
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
12.0k
{
226
12.0k
  static char *function = "libesedb_page_calculate_checksums";
227
228
12.0k
  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
12.0k
  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
12.0k
  if( ( page_data_size < 4 )
251
12.0k
   || ( 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
12.0k
  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
12.0k
  if( ( page_data[ 0 ] == 0 )
276
12.0k
   && ( page_data[ 1 ] == 0 )
277
12.0k
   && ( page_data[ 2 ] == 0 )
278
12.0k
   && ( page_data[ 3 ] == 0 ) )
279
3.60k
  {
280
3.60k
    return( 0 );
281
3.60k
  }
282
8.48k
  if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER )
283
8.48k
   && ( io_handle->page_size >= 16384 ) )
284
2.34k
  {
285
/* TODO calculate checksum */
286
2.34k
  }
287
6.14k
  else if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_NEW_RECORD_FORMAT )
288
6.14k
        && ( ( page->header->flags & LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT ) != 0 ) )
289
2.40k
  {
290
2.40k
    if( libesedb_checksum_calculate_little_endian_ecc32(
291
2.40k
         ecc32_checksum,
292
2.40k
         xor32_checksum,
293
2.40k
         page_data,
294
2.40k
         page_data_size,
295
2.40k
         8,
296
2.40k
         page->page_number,
297
2.40k
         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
2.40k
  }
309
3.73k
  else
310
3.73k
  {
311
3.73k
    if( libesedb_checksum_calculate_little_endian_xor32(
312
3.73k
         xor32_checksum,
313
3.73k
         &( page_data[ 4 ] ),
314
3.73k
         page_data_size - 4,
315
3.73k
         0x89abcdef,
316
3.73k
         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
3.73k
  }
328
8.48k
  return( 1 );
329
8.48k
}
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
5.46k
{
342
5.46k
  libesedb_page_value_t *page_value = NULL;
343
5.46k
  const uint8_t *page_tags_data     = NULL;
344
5.46k
  static char *function             = "libesedb_page_read_tags";
345
5.46k
  size_t page_tags_data_size        = 0;
346
5.46k
  uint16_t page_tag_offset          = 0;
347
5.46k
  uint16_t page_tag_size            = 0;
348
5.46k
  uint16_t page_tags_index          = 0;
349
350
5.46k
  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
5.46k
  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
5.46k
  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
5.46k
  if( ( page_data_size < 2 )
384
5.46k
   || ( 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
5.46k
  page_tags_data_size = 4 * number_of_page_tags;
396
397
5.46k
  if( page_tags_data_size > page_data_size )
398
242
  {
399
242
    libcerror_error_set(
400
242
     error,
401
242
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
402
242
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
403
242
     "%s: invalid number of page tags value out of bounds.",
404
242
     function );
405
406
242
    goto on_error;
407
242
  }
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
5.22k
  if( libcdata_array_resize(
421
5.22k
       page->values_array,
422
5.22k
       number_of_page_tags,
423
5.22k
       (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_value_free,
424
5.22k
       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
5.22k
  page_tags_data = &( page_data[ page_data_size - 2 ] );
438
439
5.22k
  for( page_tags_index = 0;
440
1.57M
       page_tags_index < number_of_page_tags;
441
1.56M
       page_tags_index++ )
442
1.56M
  {
443
1.56M
    if( libesedb_page_value_initialize(
444
1.56M
         &page_value,
445
1.56M
         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
1.56M
    byte_stream_copy_to_uint16_little_endian(
457
1.56M
     page_tags_data,
458
1.56M
     page_tag_offset );
459
460
1.56M
    page_tags_data -= 2;
461
462
1.56M
    byte_stream_copy_to_uint16_little_endian(
463
1.56M
     page_tags_data,
464
1.56M
     page_tag_size );
465
466
1.56M
    page_tags_data -= 2;
467
468
1.56M
    if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER )
469
1.56M
     && ( io_handle->page_size >= 16384 ) )
470
1.39M
    {
471
1.39M
      page_value->flags  = 0;
472
1.39M
      page_value->offset = page_tag_offset & 0x7fff;
473
1.39M
      page_value->size   = page_tag_size & 0x7fff;;
474
1.39M
    }
475
168k
    else
476
168k
    {
477
168k
      page_value->flags  = page_tag_offset >> 13;
478
168k
      page_value->offset = page_tag_offset & 0x1fff;
479
168k
      page_value->size   = page_tag_size & 0x1fff;
480
168k
    }
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
1.56M
    if( libcdata_array_set_entry_by_index(
515
1.56M
         page->values_array,
516
1.56M
         (int) page_tags_index,
517
1.56M
         (intptr_t *) page_value,
518
1.56M
         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
1.56M
    page_value = NULL;
531
1.56M
  }
532
#if defined( HAVE_DEBUG_OUTPUT )
533
  if( libcnotify_verbose != 0 )
534
  {
535
    libcnotify_printf(
536
     "\n" );
537
  }
538
#endif
539
5.22k
  return( 1 );
540
541
242
on_error:
542
242
  if( page_value != NULL )
543
0
  {
544
0
    libesedb_page_value_free(
545
0
     &page_value,
546
0
     NULL );
547
0
  }
548
242
  libcdata_array_empty(
549
242
   page->values_array,
550
242
   (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_value_free,
551
242
   NULL );
552
553
242
  return( -1 );
554
5.22k
}
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
12.0k
{
567
12.0k
  libesedb_page_value_t *page_value = NULL;
568
12.0k
  uint8_t *page_values_data         = NULL;
569
12.0k
  static char *function             = "libesedb_page_read_values";
570
12.0k
  size_t page_tags_data_size        = 0;
571
12.0k
  size_t page_values_data_size      = 0;
572
12.0k
  uint16_t number_of_page_tags      = 0;
573
12.0k
  uint16_t page_tags_index          = 0;
574
575
12.0k
  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
12.0k
  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
12.0k
  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
12.0k
  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
12.0k
  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
12.0k
  number_of_page_tags = page->header->available_page_tag;
631
632
12.0k
  if( number_of_page_tags == 0 )
633
6.62k
  {
634
6.62k
    return( 1 );
635
6.62k
  }
636
5.46k
  if( libesedb_page_read_tags(
637
5.46k
       page,
638
5.46k
       io_handle,
639
5.46k
       page_data,
640
5.46k
       page_data_size,
641
5.46k
       number_of_page_tags,
642
5.46k
       error ) != 1 )
643
242
  {
644
242
    libcerror_error_set(
645
242
     error,
646
242
     LIBCERROR_ERROR_DOMAIN_IO,
647
242
     LIBCERROR_IO_ERROR_READ_FAILED,
648
242
     "%s: unable to read page tags.",
649
242
     function );
650
651
242
    goto on_error;
652
242
  }
653
  /* The offsets in the page tags are relative after the page header
654
   */
655
5.22k
  page_values_data      = &( page_data[ page_values_data_offset ] );
656
5.22k
  page_values_data_size = page_data_size - page_values_data_offset;
657
5.22k
  page_tags_data_size   = 4 * number_of_page_tags;
658
659
5.22k
  if( page_values_data_size < page_tags_data_size )
660
33
  {
661
33
    libcerror_error_set(
662
33
     error,
663
33
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
664
33
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
665
33
     "%s: invalid page values data size value out of bounds.",
666
33
     function );
667
668
33
    goto on_error;
669
33
  }
670
5.19k
  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
5.19k
  for( page_tags_index = 0;
685
1.27M
       page_tags_index < number_of_page_tags;
686
1.26M
       page_tags_index++ )
687
1.26M
  {
688
1.26M
    if( libcdata_array_get_entry_by_index(
689
1.26M
         page->values_array,
690
1.26M
         page_tags_index,
691
1.26M
         (intptr_t **) &page_value,
692
1.26M
         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
1.26M
    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
1.26M
    if( page_value->offset >= page_values_data_size )
716
88
    {
717
88
      libcerror_error_set(
718
88
       error,
719
88
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
720
88
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
721
88
       "%s: unsupported page tags value offset value out of bounds.",
722
88
       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
88
      goto on_error;
737
88
    }
738
1.26M
    if( (size_t) page_value->size > ( page_values_data_size - page_value->offset ) )
739
79
    {
740
79
      libcerror_error_set(
741
79
       error,
742
79
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
743
79
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
744
79
       "%s: unsupported page tags value size value out of bounds.",
745
79
       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
79
      goto on_error;
760
79
    }
761
1.26M
    if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER )
762
1.26M
     && ( io_handle->page_size >= 16384 ) )
763
1.14M
    {
764
1.14M
      if( page_value->size >= 2 )
765
859k
      {
766
        /* The page tags flags are stored in the upper byte of the first 16-bit value
767
         */
768
859k
        page_value->flags = page_values_data[ page_value->offset + 1 ] >> 5;
769
770
859k
        page_values_data[ page_value->offset + 1 ] &= 0x1f;
771
859k
      }
772
1.14M
    }
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
1.26M
    page_value->data    = &( page_values_data[ page_value->offset ] );
790
1.26M
    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
1.26M
  }
806
#if defined( HAVE_DEBUG_OUTPUT )
807
  if( libcnotify_verbose != 0 )
808
  {
809
    libcnotify_printf(
810
    "\n" );
811
  }
812
#endif
813
5.02k
  return( 1 );
814
815
442
on_error:
816
442
  libcdata_array_empty(
817
442
   page->values_array,
818
442
   (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_value_free,
819
442
   NULL );
820
821
442
  return( -1 );
822
5.19k
}
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
12.2k
{
834
12.2k
  static char *function              = "libesedb_page_read_file_io_handle";
835
12.2k
  ssize_t read_count                 = 0;
836
12.2k
  uint32_t calculated_ecc32_checksum = 0;
837
12.2k
  uint32_t calculated_xor32_checksum = 0;
838
12.2k
  int result                         = 0;
839
840
12.2k
  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
12.2k
  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
12.2k
  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
12.2k
  page->page_number = (uint32_t) ( ( file_offset - io_handle->page_size ) / io_handle->page_size );
874
12.2k
  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
12.2k
  page->data = (uint8_t *) memory_allocate(
890
12.2k
                            (size_t) io_handle->page_size );
891
892
12.2k
  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
12.2k
  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
12.2k
  read_count = libbfio_handle_read_buffer_at_offset(
917
12.2k
                file_io_handle,
918
12.2k
                page->data,
919
12.2k
                page->data_size,
920
12.2k
                page->offset,
921
12.2k
                error );
922
923
12.2k
  if( read_count != (ssize_t) page->data_size )
924
200
  {
925
200
    libcerror_error_set(
926
200
     error,
927
200
     LIBCERROR_ERROR_DOMAIN_IO,
928
200
     LIBCERROR_IO_ERROR_READ_FAILED,
929
200
     "%s: unable to read page: %" PRIu32 " data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
930
200
     function,
931
200
     page->page_number,
932
200
     page->offset,
933
200
     page->offset );
934
935
200
    goto on_error;
936
200
  }
937
12.0k
  if( libesedb_page_header_read_data(
938
12.0k
       page->header,
939
12.0k
       io_handle,
940
12.0k
       page->data,
941
12.0k
       page->data_size,
942
12.0k
       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
12.0k
  result = libesedb_page_calculate_checksums(
954
12.0k
            page,
955
12.0k
            io_handle,
956
12.0k
            page->data,
957
12.0k
            page->data_size,
958
12.0k
            &calculated_ecc32_checksum,
959
12.0k
            &calculated_xor32_checksum,
960
12.0k
            error );
961
962
12.0k
  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
12.0k
  else if( result != 0 )
974
8.48k
  {
975
8.48k
    if( page->header->xor32_checksum != calculated_xor32_checksum )
976
6.12k
    {
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
6.12k
      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
6.12k
#endif
998
6.12k
    }
999
8.48k
    if( page->header->ecc32_checksum != calculated_ecc32_checksum )
1000
2.40k
    {
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
2.40k
      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
2.40k
#endif
1022
2.40k
    }
1023
8.48k
  }
1024
12.0k
  if( libesedb_page_read_values(
1025
12.0k
       page,
1026
12.0k
       io_handle,
1027
12.0k
       page->data,
1028
12.0k
       page->data_size,
1029
12.0k
       page->header->data_size,
1030
12.0k
       error ) != 1 )
1031
442
  {
1032
442
    libcerror_error_set(
1033
442
     error,
1034
442
     LIBCERROR_ERROR_DOMAIN_IO,
1035
442
     LIBCERROR_IO_ERROR_READ_FAILED,
1036
442
     "%s: unable to read page values.",
1037
442
     function );
1038
1039
442
    goto on_error;
1040
442
  }
1041
11.6k
  return( 1 );
1042
1043
642
on_error:
1044
642
  if( page->data != NULL )
1045
642
  {
1046
642
    memory_free(
1047
642
     page->data );
1048
1049
642
    page->data = NULL;
1050
642
  }
1051
642
  return( -1 );
1052
12.0k
}
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
3.09k
{
1061
3.09k
  static char *function         = "libesedb_page_validate_root_page";
1062
3.09k
  uint32_t page_flags           = 0;
1063
3.09k
  uint32_t required_page_flags  = 0;
1064
3.09k
  uint32_t supported_page_flags = 0;
1065
1066
3.09k
  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
3.09k
  if( libesedb_page_header_get_flags(
1078
3.09k
       page->header,
1079
3.09k
       &page_flags,
1080
3.09k
       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
3.09k
  required_page_flags = LIBESEDB_PAGE_FLAG_IS_ROOT;
1092
1093
3.09k
  if( ( page_flags & required_page_flags ) != required_page_flags )
1094
1
  {
1095
1
    libcerror_error_set(
1096
1
     error,
1097
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1098
1
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1099
1
     "%s: missing required page flags: 0x%08" PRIx32 ".",
1100
1
     function,
1101
1
     page_flags );
1102
1103
1
    return( -1 );
1104
1
  }
1105
3.09k
  if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_EMPTY ) != 0 )
1106
2.18k
  {
1107
2.18k
    return( 1 );
1108
2.18k
  }
1109
909
  supported_page_flags = required_page_flags
1110
909
                       | LIBESEDB_PAGE_FLAG_IS_LEAF
1111
909
                       | LIBESEDB_PAGE_FLAG_IS_PARENT
1112
909
                       | LIBESEDB_PAGE_FLAG_IS_INDEX
1113
909
                       | LIBESEDB_PAGE_FLAG_IS_SPACE_TREE
1114
909
                       | LIBESEDB_PAGE_FLAG_IS_LONG_VALUE
1115
909
                       | LIBESEDB_PAGE_FLAG_0x0400
1116
909
                       | LIBESEDB_PAGE_FLAG_0x0800
1117
909
                       | LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT
1118
909
                       | LIBESEDB_PAGE_FLAG_IS_SCRUBBED
1119
909
                       | LIBESEDB_PAGE_FLAG_0x8000
1120
909
                       | LIBESEDB_PAGE_FLAG_0x10000;
1121
1122
909
  if( ( page_flags & ~( supported_page_flags ) ) != 0 )
1123
92
  {
1124
92
    libcerror_error_set(
1125
92
     error,
1126
92
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1127
92
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1128
92
     "%s: unsupported page flags: 0x%08" PRIx32 ".",
1129
92
     function,
1130
92
     page_flags );
1131
1132
92
    return( -1 );
1133
92
  }
1134
817
  return( 1 );
1135
909
}
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
9.52k
{
1284
9.52k
  static char *function         = "libesedb_page_validate_page";
1285
9.52k
  uint32_t next_page_number     = 0;
1286
9.52k
  uint32_t page_flags           = 0;
1287
9.52k
  uint32_t previous_page_number = 0;
1288
9.52k
  uint32_t supported_page_flags = 0;
1289
1290
9.52k
  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
9.52k
  if( libesedb_page_header_get_flags(
1302
9.52k
       page->header,
1303
9.52k
       &page_flags,
1304
9.52k
       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
9.52k
  if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_EMPTY ) != 0 )
1316
5.50k
  {
1317
5.50k
    return( 1 );
1318
5.50k
  }
1319
4.01k
  supported_page_flags = LIBESEDB_PAGE_FLAG_IS_ROOT
1320
4.01k
                       | LIBESEDB_PAGE_FLAG_IS_LEAF
1321
4.01k
                       | LIBESEDB_PAGE_FLAG_IS_PARENT
1322
4.01k
                       | LIBESEDB_PAGE_FLAG_IS_INDEX
1323
4.01k
                       | LIBESEDB_PAGE_FLAG_IS_LONG_VALUE
1324
4.01k
                       | LIBESEDB_PAGE_FLAG_0x0400
1325
4.01k
                       | LIBESEDB_PAGE_FLAG_0x0800
1326
4.01k
                       | LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT
1327
4.01k
                       | LIBESEDB_PAGE_FLAG_IS_SCRUBBED
1328
4.01k
                       | LIBESEDB_PAGE_FLAG_0x8000
1329
4.01k
                       | LIBESEDB_PAGE_FLAG_0x10000;
1330
1331
4.01k
  if( ( page_flags & ~( supported_page_flags ) ) != 0 )
1332
86
  {
1333
86
    libcerror_error_set(
1334
86
     error,
1335
86
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1336
86
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1337
86
     "%s: unsupported page flags: 0x%08" PRIx32 ".",
1338
86
     function,
1339
86
     page_flags );
1340
1341
86
    return( -1 );
1342
86
  }
1343
3.93k
  if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_LEAF ) == 0 )
1344
3.53k
  {
1345
3.53k
    if( libesedb_page_header_get_previous_page_number(
1346
3.53k
         page->header,
1347
3.53k
         &previous_page_number,
1348
3.53k
         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
3.53k
    if( previous_page_number != 0 )
1360
158
    {
1361
158
      libcerror_error_set(
1362
158
       error,
1363
158
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1364
158
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1365
158
       "%s: unsupported previous page number: %" PRIu32 ".",
1366
158
       function,
1367
158
       previous_page_number );
1368
1369
158
      return( -1 );
1370
158
    }
1371
3.37k
    if( libesedb_page_header_get_next_page_number(
1372
3.37k
         page->header,
1373
3.37k
         &next_page_number,
1374
3.37k
         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
3.37k
    if( next_page_number != 0 )
1386
9
    {
1387
9
      libcerror_error_set(
1388
9
       error,
1389
9
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1390
9
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1391
9
       "%s: unsupported next page number: %" PRIu32 ".",
1392
9
       function,
1393
9
       next_page_number );
1394
1395
9
      return( -1 );
1396
9
    }
1397
3.37k
  }
1398
3.76k
  return( 1 );
1399
3.93k
}
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
6.51k
{
1409
6.51k
  static char *function = "libesedb_page_get_previous_page_number";
1410
1411
6.51k
  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
6.51k
  if( libesedb_page_header_get_previous_page_number(
1423
6.51k
       page->header,
1424
6.51k
       previous_page_number,
1425
6.51k
       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
6.51k
  return( 1 );
1437
6.51k
}
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
110k
{
1447
110k
  static char *function = "libesedb_page_get_next_page_number";
1448
1449
110k
  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
110k
  if( libesedb_page_header_get_next_page_number(
1461
110k
       page->header,
1462
110k
       next_page_number,
1463
110k
       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
110k
  return( 1 );
1475
110k
}
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
135k
{
1523
135k
  static char *function = "libesedb_page_get_flags";
1524
1525
135k
  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
135k
  if( libesedb_page_header_get_flags(
1537
135k
       page->header,
1538
135k
       flags,
1539
135k
       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
135k
  return( 1 );
1551
135k
}
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
123k
{
1561
123k
  static char *function     = "libesedb_page_get_number_of_values";
1562
123k
  int page_number_of_values = 0;
1563
1564
123k
  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
123k
  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
123k
  if( libcdata_array_get_number_of_entries(
1587
123k
       page->values_array,
1588
123k
       &page_number_of_values,
1589
123k
       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
123k
  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
123k
  *number_of_values = (uint16_t) page_number_of_values;
1612
1613
123k
  return( 1 );
1614
123k
}
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
56.9M
{
1625
56.9M
  static char *function = "libesedb_page_get_value_by_index";
1626
1627
56.9M
  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
56.9M
  if( libcdata_array_get_entry_by_index(
1639
56.9M
       page->values_array,
1640
56.9M
       (int) value_index,
1641
56.9M
       (intptr_t **) page_value,
1642
56.9M
       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
56.9M
  return( 1 );
1655
56.9M
}
1656