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