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