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