1 /*
2 * Recover functions
3 *
4 * Copyright (C) 2008-2018, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This software 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 software 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 software. If not, see <http://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 "libpff_data_block.h"
28 #include "libpff_definitions.h"
29 #include "libpff_descriptors_index.h"
30 #include "libpff_index.h"
31 #include "libpff_index_node.h"
32 #include "libpff_index_tree.h"
33 #include "libpff_index_value.h"
34 #include "libpff_item_descriptor.h"
35 #include "libpff_item_tree.h"
36 #include "libpff_io_handle.h"
37 #include "libpff_libbfio.h"
38 #include "libpff_libcerror.h"
39 #include "libpff_libcnotify.h"
40 #include "libpff_libfmapi.h"
41 #include "libpff_local_descriptor_node.h"
42 #include "libpff_offsets_index.h"
43 #include "libpff_recover.h"
44
45 #include "pff_block.h"
46 #include "pff_index_node.h"
47
48 /* Scans for recoverable items
49 * By default only the unallocated space is checked for recoverable items
50 * Returns 1 if successful or -1 on error
51 */
libpff_recover_items(libpff_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libpff_descriptors_index_t * descriptors_index,libpff_offsets_index_t * offsets_index,libcdata_range_list_t * unallocated_data_block_list,libcdata_range_list_t * unallocated_page_block_list,libcdata_list_t * recovered_item_list,uint8_t recovery_flags,libcerror_error_t ** error)52 int libpff_recover_items(
53 libpff_io_handle_t *io_handle,
54 libbfio_handle_t *file_io_handle,
55 libpff_descriptors_index_t *descriptors_index,
56 libpff_offsets_index_t *offsets_index,
57 libcdata_range_list_t *unallocated_data_block_list,
58 libcdata_range_list_t *unallocated_page_block_list,
59 libcdata_list_t *recovered_item_list,
60 uint8_t recovery_flags,
61 libcerror_error_t **error )
62 {
63 libfdata_tree_node_t *recovered_descriptor_index_leaf_node = NULL;
64 libpff_data_block_t *recovered_data_block = NULL;
65 libpff_index_t *recovered_descriptor_index = NULL;
66 libpff_index_t *recovered_offset_index = NULL;
67 libpff_index_value_t *descriptor_index_value = NULL;
68 libpff_index_value_t *offset_index_value = NULL;
69 libpff_item_descriptor_t *item_descriptor = NULL;
70 libcdata_tree_node_t *item_tree_node = NULL;
71 static char *function = "libpff_recover_items";
72 int data_identifier_value_index = 0;
73 int index_value_iterator = 0;
74 int local_descriptors_identifier_value_index = 0;
75 int number_of_index_values = 0;
76 int number_of_recovered_descriptor_index_values = 0;
77 int recovered_descriptor_index_value_iterator = 0;
78 int recoverable = 0;
79 int result = 0;
80
81 if( io_handle == NULL )
82 {
83 libcerror_error_set(
84 error,
85 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
86 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
87 "%s: invalid IO handle.",
88 function );
89
90 return( -1 );
91 }
92 if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT )
93 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT )
94 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
95 {
96 libcerror_error_set(
97 error,
98 LIBCERROR_ERROR_DOMAIN_RUNTIME,
99 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
100 "%s: unsupported file type.",
101 function );
102
103 return( -1 );
104 }
105 if( recovered_item_list == NULL )
106 {
107 libcerror_error_set(
108 error,
109 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
110 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
111 "%s: invalid recovered item list.",
112 function );
113
114 return( -1 );
115 }
116 if( libpff_descriptors_index_set_root_node(
117 descriptors_index,
118 0,
119 0,
120 1,
121 error ) != 1 )
122 {
123 libcerror_error_set(
124 error,
125 LIBCERROR_ERROR_DOMAIN_RUNTIME,
126 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
127 "%s: unable to set descriptors index root node.",
128 function );
129
130 goto on_error;
131 }
132 if( libpff_offsets_index_set_root_node(
133 offsets_index,
134 0,
135 0,
136 1,
137 error ) != 1 )
138 {
139 libcerror_error_set(
140 error,
141 LIBCERROR_ERROR_DOMAIN_RUNTIME,
142 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
143 "%s: unable to set offsets index root node.",
144 function );
145
146 goto on_error;
147 }
148 #if defined( HAVE_DEBUG_OUTPUT )
149 if( libbfio_handle_set_track_offsets_read(
150 file_io_handle,
151 0,
152 error ) != 1 )
153 {
154 libcerror_error_set(
155 error,
156 LIBCERROR_ERROR_DOMAIN_RUNTIME,
157 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
158 "%s: unable to set track offsets read in file IO handle.",
159 function );
160
161 goto on_error;
162 }
163 #endif
164 if( libpff_recover_index_nodes(
165 io_handle,
166 file_io_handle,
167 descriptors_index,
168 error ) != 1 )
169 {
170 libcerror_error_set(
171 error,
172 LIBCERROR_ERROR_DOMAIN_IO,
173 LIBCERROR_IO_ERROR_READ_FAILED,
174 "%s: unable to recover index nodes.",
175 function );
176
177 goto on_error;
178 }
179 if( libpff_recover_data_blocks(
180 io_handle,
181 file_io_handle,
182 descriptors_index,
183 offsets_index,
184 unallocated_data_block_list,
185 unallocated_page_block_list,
186 recovery_flags,
187 error ) != 1 )
188 {
189 libcerror_error_set(
190 error,
191 LIBCERROR_ERROR_DOMAIN_IO,
192 LIBCERROR_IO_ERROR_READ_FAILED,
193 "%s: unable to recover data blocks.",
194 function );
195
196 goto on_error;
197 }
198 /* For the recovered descriptor index nodes check
199 * if the local descriptor and data offset index value still exists
200 */
201 if( libfdata_tree_get_number_of_leaf_nodes(
202 descriptors_index->recovered_index_tree,
203 (intptr_t *) file_io_handle,
204 descriptors_index->index_cache,
205 &number_of_recovered_descriptor_index_values,
206 0,
207 error ) != 1 )
208 {
209 libcerror_error_set(
210 error,
211 LIBCERROR_ERROR_DOMAIN_RUNTIME,
212 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
213 "%s: unable to retrieve number of recovered descriptor index values.",
214 function );
215
216 goto on_error;
217 }
218 for( recovered_descriptor_index_value_iterator = 0;
219 recovered_descriptor_index_value_iterator < number_of_recovered_descriptor_index_values;
220 recovered_descriptor_index_value_iterator++ )
221 {
222 if( io_handle->abort != 0 )
223 {
224 goto on_error;
225 }
226 if( libfdata_tree_get_leaf_node_by_index(
227 descriptors_index->recovered_index_tree,
228 (intptr_t *) file_io_handle,
229 descriptors_index->index_cache,
230 recovered_descriptor_index_value_iterator,
231 &recovered_descriptor_index_leaf_node,
232 0,
233 error ) != 1 )
234 {
235 libcerror_error_set(
236 error,
237 LIBCERROR_ERROR_DOMAIN_RUNTIME,
238 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
239 "%s: unable to retrieve recovered descriptor leaf node: %d.",
240 function,
241 recovered_descriptor_index_value_iterator );
242
243 goto on_error;
244 }
245 if( libfdata_tree_node_get_node_value(
246 recovered_descriptor_index_leaf_node,
247 (intptr_t *) file_io_handle,
248 descriptors_index->index_cache,
249 (intptr_t **) &descriptor_index_value,
250 0,
251 error ) != 1 )
252 {
253 libcerror_error_set(
254 error,
255 LIBCERROR_ERROR_DOMAIN_RUNTIME,
256 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
257 "%s: unable to retrieve recovered descriptor index value: %d.",
258 function,
259 recovered_descriptor_index_value_iterator );
260
261 goto on_error;
262 }
263 if( descriptor_index_value == NULL )
264 {
265 libcerror_error_set(
266 error,
267 LIBCERROR_ERROR_DOMAIN_RUNTIME,
268 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
269 "%s: missing descriptor index value: %d.",
270 function,
271 recovered_descriptor_index_value_iterator );
272
273 goto on_error;
274 }
275 #if defined( HAVE_DEBUG_OUTPUT )
276 if( libcnotify_verbose != 0 )
277 {
278 libcnotify_printf(
279 "%s: analyzing identifier: %" PRIu64 ", data: %" PRIu64 ", local descriptors: %" PRIu64 ", parent: %" PRIu32 "\n",
280 function,
281 descriptor_index_value->identifier,
282 descriptor_index_value->data_identifier,
283 descriptor_index_value->local_descriptors_identifier,
284 descriptor_index_value->parent_identifier );
285 }
286 #endif
287 recoverable = 1;
288
289 /* Check if the data identifier is recoverable
290 */
291 if( recoverable != 0 )
292 {
293 if( libpff_index_tree_get_number_of_leaf_nodes_by_identifier(
294 offsets_index->recovered_index_tree,
295 file_io_handle,
296 offsets_index->index_cache,
297 descriptor_index_value->data_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK,
298 &number_of_index_values,
299 error ) != 1 )
300 {
301 libcerror_error_set(
302 error,
303 LIBCERROR_ERROR_DOMAIN_RUNTIME,
304 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
305 "%s: unable to retrieve number of recovered offset index values for data identifier: %" PRIu64 ".",
306 function,
307 descriptor_index_value->data_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK );
308
309 goto on_error;
310 }
311 /* TODO what if more than 1 identifier is recoverable ? now uses first come first serve */
312 result = 0;
313
314 for( index_value_iterator = 0;
315 index_value_iterator < number_of_index_values;
316 index_value_iterator++ )
317 {
318 result = libpff_index_tree_get_value_by_identifier(
319 offsets_index->recovered_index_tree,
320 file_io_handle,
321 offsets_index->index_cache,
322 descriptor_index_value->data_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK,
323 index_value_iterator,
324 &offset_index_value,
325 error );
326
327 if( result == -1 )
328 {
329 libcerror_error_set(
330 error,
331 LIBCERROR_ERROR_DOMAIN_RUNTIME,
332 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
333 "%s: unable to retrieve recovered offset index value for data identifier: %" PRIu64 ".",
334 function,
335 descriptor_index_value->data_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK );
336
337 goto on_error;
338 }
339 else if( result != 0 )
340 {
341 /* Check if the data block is readable
342 */
343 #if defined( HAVE_DEBUG_OUTPUT )
344 if( libcnotify_verbose != 0 )
345 {
346 libcnotify_printf(
347 "%s: reading data block at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
348 function,
349 offset_index_value->file_offset,
350 offset_index_value->file_offset );
351 }
352 #endif
353 if( libbfio_handle_seek_offset(
354 file_io_handle,
355 offset_index_value->file_offset,
356 SEEK_SET,
357 error ) == -1 )
358 {
359 libcerror_error_set(
360 error,
361 LIBCERROR_ERROR_DOMAIN_IO,
362 LIBCERROR_IO_ERROR_SEEK_FAILED,
363 "%s: unable to seek data block offset: %" PRIi64 ".",
364 function,
365 offset_index_value->file_offset );
366
367 goto on_error;
368 }
369 if( libpff_data_block_initialize(
370 &recovered_data_block,
371 io_handle,
372 (uint32_t) descriptor_index_value->identifier,
373 offset_index_value->identifier,
374 error ) != 1 )
375 {
376 libcerror_error_set(
377 error,
378 LIBCERROR_ERROR_DOMAIN_RUNTIME,
379 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
380 "%s: unable to create data block.",
381 function );
382
383 goto on_error;
384 }
385 result = libpff_data_block_read_file_io_handle(
386 recovered_data_block,
387 file_io_handle,
388 offset_index_value->file_offset,
389 offset_index_value->data_size,
390 io_handle->file_type,
391 error );
392
393 if( result != 1 )
394 {
395 libcerror_error_set(
396 error,
397 LIBCERROR_ERROR_DOMAIN_IO,
398 LIBCERROR_IO_ERROR_READ_FAILED,
399 "%s: unable to read data block.",
400 function );
401 #if defined( HAVE_DEBUG_OUTPUT )
402 if( ( libcnotify_verbose != 0 )
403 && ( error != NULL )
404 && ( *error != NULL ) )
405 {
406 libcnotify_print_error_backtrace(
407 *error );
408 }
409 #endif
410 libcerror_error_free(
411 error );
412
413 /* TODO delete unreadable offset identifier in offsets_index->recovered_index_tree */
414 }
415 if( libpff_data_block_free(
416 &recovered_data_block,
417 error ) != 1 )
418 {
419 libcerror_error_set(
420 error,
421 LIBCERROR_ERROR_DOMAIN_RUNTIME,
422 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
423 "%s: unable to free recovered data block.",
424 function );
425
426 goto on_error;
427 }
428 /* TODO validate the block data ? */
429 if( result == 1 )
430 {
431 break;
432 }
433 }
434 }
435 if( result == 0 )
436 {
437 #if defined( HAVE_DEBUG_OUTPUT )
438 if( libcnotify_verbose != 0 )
439 {
440 libcnotify_printf(
441 "%s: recovered offset index value for data identifier: %" PRIu64 " not available.\n",
442 function,
443 descriptor_index_value->data_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK );
444 }
445 #endif
446 recoverable = 0;
447 }
448 else
449 {
450 data_identifier_value_index = index_value_iterator;
451 }
452 }
453 /* Check if the local descriptors are also recoverable
454 */
455 if( recoverable != 0 )
456 {
457 /* Allow desciptors to have a zero local descriptors value
458 */
459 if( descriptor_index_value->local_descriptors_identifier > 0 )
460 {
461 if( libpff_index_tree_get_number_of_leaf_nodes_by_identifier(
462 offsets_index->recovered_index_tree,
463 file_io_handle,
464 offsets_index->index_cache,
465 descriptor_index_value->local_descriptors_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK,
466 &number_of_index_values,
467 error ) != 1 )
468 {
469 libcerror_error_set(
470 error,
471 LIBCERROR_ERROR_DOMAIN_RUNTIME,
472 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
473 "%s: unable to retrieve number of recovered offset index values for local descriptors identifier: %" PRIu64 ".",
474 function,
475 descriptor_index_value->local_descriptors_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK );
476
477 goto on_error;
478 }
479 /* TODO what if more than 1 identifier is recoverable ? now uses first come first serve */
480 result = 0;
481
482 for( index_value_iterator = 0;
483 index_value_iterator < number_of_index_values;
484 index_value_iterator++ )
485 {
486 result = libpff_index_tree_get_value_by_identifier(
487 offsets_index->recovered_index_tree,
488 file_io_handle,
489 offsets_index->index_cache,
490 descriptor_index_value->local_descriptors_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK,
491 index_value_iterator,
492 &offset_index_value,
493 error );
494
495 if( result == -1 )
496 {
497 libcerror_error_set(
498 error,
499 LIBCERROR_ERROR_DOMAIN_RUNTIME,
500 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
501 "%s: unable to retrieve recovered offset index value for local descriptors identifier: %" PRIu64 ".",
502 function,
503 descriptor_index_value->local_descriptors_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK );
504
505 goto on_error;
506 }
507 else if( result != 0 )
508 {
509 /* Check if local descriptors are readable
510 */
511 result = libpff_recover_local_descriptors(
512 io_handle,
513 file_io_handle,
514 offsets_index,
515 descriptor_index_value->local_descriptors_identifier,
516 error );
517
518 if( result == -1 )
519 {
520 libcerror_error_set(
521 error,
522 LIBCERROR_ERROR_DOMAIN_IO,
523 LIBCERROR_IO_ERROR_READ_FAILED,
524 "%s: unable to read local descriptors with identifier: %" PRIu64 ".",
525 function,
526 descriptor_index_value->local_descriptors_identifier );
527
528 goto on_error;
529 }
530 else if( result != 0 )
531 {
532 break;
533 }
534 }
535 }
536 if( result == 0 )
537 {
538 #if defined( HAVE_DEBUG_OUTPUT )
539 if( libcnotify_verbose != 0 )
540 {
541 libcnotify_printf(
542 "%s: recovered offset index value for local descriptors identifier: %" PRIu64 " not available.\n",
543 function,
544 descriptor_index_value->local_descriptors_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK );
545 }
546 #endif
547 recoverable = 0;
548 }
549 if( recoverable != 0 )
550 {
551 local_descriptors_identifier_value_index = index_value_iterator;
552 }
553 }
554 }
555 if( recoverable == 0 )
556 {
557 if( libfdata_tree_node_set_deleted(
558 recovered_descriptor_index_leaf_node,
559 error ) != 1 )
560 {
561 libcerror_error_set(
562 error,
563 LIBCERROR_ERROR_DOMAIN_RUNTIME,
564 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
565 "%s: unable to set deleted in recovered index tree leaf node: %d.",
566 function,
567 recovered_descriptor_index_value_iterator );
568
569 goto on_error;
570 }
571 number_of_recovered_descriptor_index_values--;
572 recovered_descriptor_index_value_iterator--;
573 }
574 else
575 {
576 #if defined( HAVE_DEBUG_OUTPUT )
577 if( libcnotify_verbose != 0 )
578 {
579 libcnotify_printf(
580 "%s: item descriptor: %" PRIu64 " is recoverable.\n",
581 function,
582 descriptor_index_value->identifier );
583 }
584 #endif
585 /* Create a new item descriptor
586 */
587 if( libpff_item_descriptor_initialize(
588 &item_descriptor,
589 (uint32_t) descriptor_index_value->identifier,
590 descriptor_index_value->data_identifier,
591 descriptor_index_value->local_descriptors_identifier,
592 1,
593 error ) != 1 )
594 {
595 libcerror_error_set(
596 error,
597 LIBCERROR_ERROR_DOMAIN_RUNTIME,
598 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
599 "%s: unable to create item descriptor.",
600 function );
601
602 goto on_error;
603 }
604 if( item_descriptor == NULL )
605 {
606 libcerror_error_set(
607 error,
608 LIBCERROR_ERROR_DOMAIN_RUNTIME,
609 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
610 "%s: missing item descriptor.",
611 function );
612
613 goto on_error;
614 }
615 /* TODO add to initialize function or create a separate function for setting these value in the item descriptor */
616 item_descriptor->recovered_data_identifier_value_index = data_identifier_value_index;
617 item_descriptor->recovered_local_descriptors_identifier_value_index = local_descriptors_identifier_value_index;
618
619 /* Create a new tree node with item tree values
620 */
621 if( libcdata_tree_node_initialize(
622 &item_tree_node,
623 error ) != 1 )
624 {
625 libcerror_error_set(
626 error,
627 LIBCERROR_ERROR_DOMAIN_RUNTIME,
628 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
629 "%s: unable to create item tree node.",
630 function );
631
632 goto on_error;
633 }
634 if( libcdata_tree_node_set_value(
635 item_tree_node,
636 (intptr_t *) item_descriptor,
637 error ) != 1 )
638 {
639 libcerror_error_set(
640 error,
641 LIBCERROR_ERROR_DOMAIN_RUNTIME,
642 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
643 "%s: unable to set item descriptor in item tree node.",
644 function );
645
646 goto on_error;
647 }
648 item_descriptor = NULL;
649
650 if( libcdata_list_append_value(
651 recovered_item_list,
652 (intptr_t *) item_tree_node,
653 error ) != 1 )
654 {
655 libcerror_error_set(
656 error,
657 LIBCERROR_ERROR_DOMAIN_RUNTIME,
658 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
659 "%s: unable to append tree node to recovered item list.",
660 function );
661
662 goto on_error;
663 }
664 item_tree_node = NULL;
665 }
666 }
667 #if defined( HAVE_DEBUG_OUTPUT )
668 if( libbfio_handle_set_track_offsets_read(
669 file_io_handle,
670 0,
671 error ) != 1 )
672 {
673 libcerror_error_set(
674 error,
675 LIBCERROR_ERROR_DOMAIN_RUNTIME,
676 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
677 "%s: unable to set track offsets read in file IO handle.",
678 function );
679
680 goto on_error;
681 }
682 #endif
683 /* TODO
684 * link recovered descriptors to parent? and add to item hierarchy?
685 * handle scanning without index data
686 * what about 'encryption' ?
687 */
688 return( 1 );
689
690 on_error:
691 if( recovered_data_block != NULL )
692 {
693 libpff_data_block_free(
694 &recovered_data_block,
695 NULL );
696 }
697 if( item_tree_node != NULL )
698 {
699 libcdata_tree_node_free(
700 &item_tree_node,
701 (int (*)(intptr_t **, libcerror_error_t **)) &libpff_item_descriptor_free,
702 NULL );
703 }
704 if( item_descriptor != NULL )
705 {
706 libpff_item_descriptor_free(
707 &item_descriptor,
708 NULL );
709 }
710 if( recovered_offset_index != NULL )
711 {
712 libpff_index_free(
713 &recovered_offset_index,
714 NULL );
715 }
716 if( recovered_descriptor_index != NULL )
717 {
718 libpff_index_free(
719 &recovered_descriptor_index,
720 NULL );
721 }
722 libcdata_list_empty(
723 recovered_item_list,
724 (int (*)(intptr_t **, libcerror_error_t **)) &libpff_item_tree_node_free_recovered,
725 NULL );
726
727 return( -1 );
728 }
729
730 /* Scans for recoverable index nodes
731 * Returns 1 if successful or -1 on error
732 */
libpff_recover_index_nodes(libpff_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libpff_descriptors_index_t * descriptors_index,libcerror_error_t ** error)733 int libpff_recover_index_nodes(
734 libpff_io_handle_t *io_handle,
735 libbfio_handle_t *file_io_handle,
736 libpff_descriptors_index_t *descriptors_index,
737 libcerror_error_t **error )
738 {
739 libfdata_tree_node_t *deleted_index_leaf_node = NULL;
740 libpff_index_value_t *deleted_index_value = NULL;
741 libpff_index_value_t *index_value = NULL;
742 static char *function = "libpff_recover_index_nodes";
743 off64_t node_data_offset = 0;
744 size64_t node_data_size = 0;
745 uint32_t node_data_flags = 0;
746 int deleted_index_value_iterator = 0;
747 int index_value_iterator = 0;
748 int node_data_file_index = 0;
749 int number_of_index_values = 0;
750 int number_of_deleted_index_values = 0;
751 int result = 0;
752
753 #ifdef TODO
754 uint32_t maximum_data_block_data_size = 0;
755 #endif
756
757 if( io_handle == NULL )
758 {
759 libcerror_error_set(
760 error,
761 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
762 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
763 "%s: invalid IO handle.",
764 function );
765
766 return( -1 );
767 }
768 #ifdef TODO
769 if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT )
770 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT )
771 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
772 {
773 libcerror_error_set(
774 error,
775 LIBCERROR_ERROR_DOMAIN_RUNTIME,
776 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
777 "%s: unsupported file type.",
778 function );
779
780 return( -1 );
781 }
782 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
783 {
784 maximum_data_block_data_size = 8192 - 12;
785 }
786 else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
787 {
788 maximum_data_block_data_size = 8192 - 16;
789 }
790 else
791 {
792 /* TODO: this value is currently assumed based on the 512 x 8 = 4k page */
793 maximum_data_block_data_size = 65536 - 24;
794 }
795 #endif
796 /* Scan the existing descriptor index nodes for remnant values
797 */
798 if( libfdata_tree_get_number_of_deleted_leaf_nodes(
799 descriptors_index->index_tree,
800 (intptr_t *) file_io_handle,
801 descriptors_index->index_cache,
802 &number_of_deleted_index_values,
803 0,
804 error ) != 1 )
805 {
806 libcerror_error_set(
807 error,
808 LIBCERROR_ERROR_DOMAIN_RUNTIME,
809 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
810 "%s: unable to retrieve number of deleted descriptor index values.",
811 function );
812
813 return( -1 );
814 }
815 for( deleted_index_value_iterator = 0;
816 deleted_index_value_iterator < number_of_deleted_index_values;
817 deleted_index_value_iterator++ )
818 {
819 if( io_handle->abort != 0 )
820 {
821 return( -1 );
822 }
823 if( libfdata_tree_get_deleted_leaf_node_by_index(
824 descriptors_index->index_tree,
825 (intptr_t *) file_io_handle,
826 descriptors_index->index_cache,
827 deleted_index_value_iterator,
828 &deleted_index_leaf_node,
829 0,
830 error ) != 1 )
831 {
832 libcerror_error_set(
833 error,
834 LIBCERROR_ERROR_DOMAIN_RUNTIME,
835 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
836 "%s: unable to retrieve deleted descriptor leaf node: %d.",
837 function,
838 deleted_index_value_iterator );
839
840 return( -1 );
841 }
842 if( libfdata_tree_node_get_node_value(
843 deleted_index_leaf_node,
844 (intptr_t *) file_io_handle,
845 descriptors_index->index_cache,
846 (intptr_t **) &deleted_index_value,
847 0,
848 error ) != 1 )
849 {
850 libcerror_error_set(
851 error,
852 LIBCERROR_ERROR_DOMAIN_RUNTIME,
853 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
854 "%s: unable to retrieve deleted descriptor index value: %d.",
855 function,
856 deleted_index_value_iterator );
857
858 return( -1 );
859 }
860 if( deleted_index_value == NULL )
861 {
862 libcerror_error_set(
863 error,
864 LIBCERROR_ERROR_DOMAIN_RUNTIME,
865 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
866 "%s: missing deleted descriptor index value: %d.",
867 function,
868 deleted_index_value_iterator );
869
870 return( -1 );
871 }
872 #if defined( HAVE_DEBUG_OUTPUT )
873 if( libcnotify_verbose != 0 )
874 {
875 libcnotify_printf(
876 "%s: analyzing identifier: %" PRIu64 ", data: %" PRIu64 ", local descriptors: %" PRIu64 ", parent: %" PRIu32 "\n",
877 function,
878 deleted_index_value->identifier,
879 deleted_index_value->data_identifier,
880 deleted_index_value->local_descriptors_identifier,
881 deleted_index_value->parent_identifier );
882 }
883 #endif
884 /* Check if the item value matches the existing item value
885 */
886 result = libpff_index_tree_get_value_by_identifier(
887 descriptors_index->index_tree,
888 file_io_handle,
889 descriptors_index->index_cache,
890 deleted_index_value->identifier,
891 0,
892 &index_value,
893 error );
894
895 if( result == -1 )
896 {
897 libcerror_error_set(
898 error,
899 LIBCERROR_ERROR_DOMAIN_RUNTIME,
900 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
901 "%s: unable to retrieve descriptor index value for identifier: %" PRIu64 ".",
902 function,
903 deleted_index_value->identifier );
904
905 return( -1 );
906 }
907 else if( result != 0 )
908 {
909 /* TODO what about parent changes ? */
910 if( ( deleted_index_value->data_identifier == index_value->data_identifier )
911 && ( deleted_index_value->local_descriptors_identifier == index_value->local_descriptors_identifier ) )
912 {
913 #if defined( HAVE_DEBUG_OUTPUT )
914 if( libcnotify_verbose != 0 )
915 {
916 libcnotify_printf(
917 "%s: deleted descriptor index value: %" PRIu64 " matches existing item value.\n",
918 function,
919 deleted_index_value->identifier );
920 }
921 #endif
922 continue;
923 }
924 }
925 /* Check for duplicates
926 */
927 if( libpff_index_tree_get_number_of_leaf_nodes_by_identifier(
928 descriptors_index->recovered_index_tree,
929 file_io_handle,
930 descriptors_index->index_cache,
931 deleted_index_value->identifier,
932 &number_of_index_values,
933 error ) != 1 )
934 {
935 libcerror_error_set(
936 error,
937 LIBCERROR_ERROR_DOMAIN_RUNTIME,
938 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
939 "%s: unable to retrieve number of recovered descriptor index values for identifier: %" PRIu64 ".",
940 function,
941 deleted_index_value->identifier );
942
943 return( -1 );
944 }
945 result = 0;
946
947 for( index_value_iterator = 0;
948 index_value_iterator < number_of_index_values;
949 index_value_iterator++ )
950 {
951 result = libpff_index_tree_get_value_by_identifier(
952 descriptors_index->recovered_index_tree,
953 file_io_handle,
954 descriptors_index->index_cache,
955 deleted_index_value->identifier,
956 index_value_iterator,
957 &index_value,
958 error );
959
960 if( result == -1 )
961 {
962 libcerror_error_set(
963 error,
964 LIBCERROR_ERROR_DOMAIN_RUNTIME,
965 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
966 "%s: unable to retrieve recovered descriptor index value for identifier: %" PRIu64 ".",
967 function,
968 deleted_index_value->identifier );
969
970 return( -1 );
971 }
972 else if( result != 0 )
973 {
974 /* TODO what about parent changes ? */
975 if( ( deleted_index_value->data_identifier == index_value->data_identifier )
976 && ( deleted_index_value->local_descriptors_identifier == index_value->local_descriptors_identifier ) )
977 {
978 break;
979 }
980 result = 0;
981 }
982 }
983 if( result != 0 )
984 {
985 #if defined( HAVE_DEBUG_OUTPUT )
986 if( libcnotify_verbose != 0 )
987 {
988 libcnotify_printf(
989 "%s: deleted descriptor index value: %" PRIu64 " matches existing recovered item value.\n",
990 function,
991 deleted_index_value->identifier );
992 }
993 #endif
994 continue;
995 }
996 /* Add the recovered descriptor index values to the index tree
997 */
998 #if defined( HAVE_DEBUG_OUTPUT )
999 if( libcnotify_verbose != 0 )
1000 {
1001 libcnotify_printf(
1002 "%s: decriptor index value: %d identifier: %" PRIu64 " is recoverable.\n",
1003 function,
1004 deleted_index_value_iterator,
1005 deleted_index_value->identifier );
1006 }
1007 #endif
1008 if( libfdata_tree_node_get_data_range(
1009 deleted_index_leaf_node,
1010 &node_data_file_index,
1011 &node_data_offset,
1012 &node_data_size,
1013 &node_data_flags,
1014 error ) != 1 )
1015 {
1016 libcerror_error_set(
1017 error,
1018 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1019 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1020 "%s: unable to retrieve deleted descriptor leaf node: %d range.",
1021 function,
1022 deleted_index_value_iterator );
1023
1024 return( -1 );
1025 }
1026 if( libpff_index_tree_insert_value(
1027 descriptors_index->recovered_index_tree,
1028 file_io_handle,
1029 descriptors_index->index_cache,
1030 deleted_index_value->identifier,
1031 node_data_offset,
1032 node_data_size,
1033 error ) != 1 )
1034 {
1035 libcerror_error_set(
1036 error,
1037 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1038 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1039 "%s: unable to insert descriptor index value: %" PRIu64 " to recovered index tree.",
1040 function,
1041 deleted_index_value->identifier );
1042
1043 return( -1 );
1044 }
1045 }
1046 #ifdef TODO
1047 /* Scan the existing offset index nodes for remnant values
1048 */
1049 if( libfdata_tree_get_number_of_deleted_leaf_nodes(
1050 offsets_index->index_tree,
1051 (intptr_t *) file_io_handle,
1052 offsets_index->index_cache,
1053 &number_of_deleted_index_values,
1054 0,
1055 error ) != 1 )
1056 {
1057 libcerror_error_set(
1058 error,
1059 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1060 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1061 "%s: unable to retrieve number of deleted offset index values.",
1062 function );
1063
1064 return( -1 );
1065 }
1066 for( deleted_index_value_iterator = 0;
1067 deleted_index_value_iterator < number_of_deleted_index_values;
1068 deleted_index_value_iterator++ )
1069 {
1070 if( io_handle->abort != 0 )
1071 {
1072 return( -1 );
1073 }
1074 if( libfdata_tree_get_deleted_leaf_node_by_index(
1075 offsets_index->index_tree,
1076 (intptr_t *) file_io_handle,
1077 offsets_index->index_cache,
1078 deleted_index_value_iterator,
1079 &deleted_index_leaf_node,
1080 0,
1081 error ) != 1 )
1082 {
1083 libcerror_error_set(
1084 error,
1085 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1086 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1087 "%s: unable to retrieve deleted offset leaf node: %d.",
1088 function,
1089 deleted_index_value_iterator );
1090
1091 return( -1 );
1092 }
1093 if( libfdata_tree_node_get_node_value(
1094 deleted_index_leaf_node,
1095 (intptr_t *) file_io_handle,
1096 offsets_index->index_cache,
1097 (intptr_t **) &deleted_index_value,
1098 0,
1099 error ) != 1 )
1100 {
1101 libcerror_error_set(
1102 error,
1103 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1104 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1105 "%s: unable to retrieve deleted offset index value: %d.",
1106 function,
1107 deleted_index_value_iterator );
1108
1109 return( -1 );
1110 }
1111 if( deleted_index_value == NULL )
1112 {
1113 libcerror_error_set(
1114 error,
1115 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1116 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1117 "%s: missing deleted offset index value: %d.",
1118 function,
1119 deleted_index_value_iterator );
1120
1121 return( -1 );
1122 }
1123 #if defined( HAVE_DEBUG_OUTPUT )
1124 if( libcnotify_verbose != 0 )
1125 {
1126 libcnotify_printf(
1127 "%s: analyzing identifier: %" PRIu64 " (%s) at offset: %" PRIi64 " of size: %" PRIu32 "\n",
1128 function,
1129 deleted_index_value->identifier,
1130 ( ( deleted_index_value->identifier & LIBPFF_OFFSET_INDEX_IDENTIFIER_FLAG_INTERNAL ) ? "internal" : "external" ),
1131 deleted_index_value->file_offset,
1132 deleted_index_value->data_size );
1133 }
1134 #endif
1135 /* Ignore index values without a valid file offset
1136 */
1137 if( deleted_index_value->file_offset <= 0 )
1138 {
1139 #if defined( HAVE_DEBUG_OUTPUT )
1140 if( libcnotify_verbose != 0 )
1141 {
1142 libcnotify_printf(
1143 "%s: deleted offset index value: %" PRIu64 " has an invalid file offset: %" PRIi64 ".\n",
1144 function,
1145 deleted_index_value->identifier,
1146 deleted_index_value->file_offset );
1147 }
1148 #endif
1149 continue;
1150 }
1151 /* Ignore index values without a valid data size
1152 */
1153 if( ( deleted_index_value->data_size == 0 )
1154 || ( (uint32_t) deleted_index_value->data_size > maximum_data_block_data_size ) )
1155 {
1156 #if defined( HAVE_DEBUG_OUTPUT )
1157 if( libcnotify_verbose != 0 )
1158 {
1159 libcnotify_printf(
1160 "%s: deleted offset index value: %" PRIu64 " has an invalid data size: %" PRIu32 ".\n",
1161 function,
1162 deleted_index_value->identifier,
1163 deleted_index_value->data_size );
1164 }
1165 #endif
1166 continue;
1167 }
1168 /* Check if the item value matches the existing item value
1169 */
1170 result = libpff_index_tree_get_value_by_identifier(
1171 offsets_index->index_tree,
1172 file_io_handle,
1173 offsets_index->index_cache,
1174 deleted_index_value->identifier,
1175 0,
1176 &index_value,
1177 error );
1178
1179 if( result == -1 )
1180 {
1181 libcerror_error_set(
1182 error,
1183 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1184 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1185 "%s: unable to retrieve offset index value for identifier: %" PRIu64 ".",
1186 function,
1187 deleted_index_value->identifier );
1188
1189 return( -1 );
1190 }
1191 else if( result != 0 )
1192 {
1193 if( ( deleted_index_value->file_offset == index_value->file_offset )
1194 && ( deleted_index_value->data_size == index_value->data_size ) )
1195 {
1196 #if defined( HAVE_DEBUG_OUTPUT )
1197 if( libcnotify_verbose != 0 )
1198 {
1199 libcnotify_printf(
1200 "%s: deleted offset index value: %" PRIu64 " matches existing item value.\n",
1201 function,
1202 deleted_index_value->identifier );
1203 }
1204 #endif
1205 continue;
1206 }
1207 }
1208 /* Check for duplicates
1209 */
1210 if( libpff_index_tree_get_number_of_leaf_nodes_by_identifier(
1211 offsets_index->recovered_index_tree,
1212 file_io_handle,
1213 offsets_index->index_cache,
1214 deleted_index_value->identifier,
1215 &number_of_index_values,
1216 error ) != 1 )
1217 {
1218 libcerror_error_set(
1219 error,
1220 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1221 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1222 "%s: unable to retrieve number of recovered offset index values for identifier: %" PRIu64 ".",
1223 function,
1224 deleted_index_value->identifier );
1225
1226 return( -1 );
1227 }
1228 result = 0;
1229
1230 for( index_value_iterator = 0;
1231 index_value_iterator < number_of_index_values;
1232 index_value_iterator++ )
1233 {
1234 result = libpff_index_tree_get_value_by_identifier(
1235 offsets_index->recovered_index_tree,
1236 file_io_handle,
1237 offsets_index->index_cache,
1238 deleted_index_value->identifier,
1239 index_value_iterator,
1240 &index_value,
1241 error );
1242
1243 if( result == -1 )
1244 {
1245 libcerror_error_set(
1246 error,
1247 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1248 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1249 "%s: unable to retrieve recovered offset index value for identifier: %" PRIu64 ".",
1250 function,
1251 deleted_index_value->identifier );
1252
1253 return( -1 );
1254 }
1255 else if( result != 0 )
1256 {
1257 if( ( deleted_index_value->file_offset == index_value->file_offset )
1258 && ( deleted_index_value->data_size == index_value->data_size ) )
1259 {
1260 break;
1261 }
1262 result = 0;
1263 }
1264 }
1265 if( result != 0 )
1266 {
1267 #if defined( HAVE_DEBUG_OUTPUT )
1268 if( libcnotify_verbose != 0 )
1269 {
1270 libcnotify_printf(
1271 "%s: deleted offset index value: %" PRIu64 " matches existing recovered item value.\n",
1272 function,
1273 deleted_index_value->identifier );
1274 }
1275 #endif
1276 continue;
1277 }
1278 /* Add the recovered offset index values to the index tree
1279 */
1280 #if defined( HAVE_DEBUG_OUTPUT )
1281 if( libcnotify_verbose != 0 )
1282 {
1283 libcnotify_printf(
1284 "%s: offset index value: %d identifier: %" PRIu64 " is recoverable.\n",
1285 function,
1286 deleted_index_value_iterator,
1287 deleted_index_value->identifier );
1288 }
1289 #endif
1290 if( libfdata_tree_node_get_data_range(
1291 deleted_index_leaf_node,
1292 &node_data_file_index,
1293 &node_data_offset,
1294 &node_data_size,
1295 &node_data_flags,
1296 error ) != 1 )
1297 {
1298 libcerror_error_set(
1299 error,
1300 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1301 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1302 "%s: unable to retrieve deleted offset leaf node: %d range.",
1303 function,
1304 deleted_index_value_iterator );
1305
1306 return( -1 );
1307 }
1308 if( libpff_index_tree_insert_value(
1309 offsets_index->recovered_index_tree,
1310 file_io_handle,
1311 offsets_index->index_cache,
1312 deleted_index_value->identifier,
1313 node_data_offset,
1314 node_data_size,
1315 error ) != 1 )
1316 {
1317 libcerror_error_set(
1318 error,
1319 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1320 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1321 "%s: unable to insert offset index value: %" PRIu64 " to recovered index tree.",
1322 function,
1323 deleted_index_value->identifier );
1324
1325 return( -1 );
1326 }
1327 }
1328 #endif
1329 return( 1 );
1330 }
1331
1332 /* Scans for recoverable data blocks
1333 * Returns 1 if successful or -1 on error
1334 */
libpff_recover_data_blocks(libpff_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libpff_descriptors_index_t * descriptors_index,libpff_offsets_index_t * offsets_index,libcdata_range_list_t * unallocated_data_block_list,libcdata_range_list_t * unallocated_page_block_list,uint8_t recovery_flags,libcerror_error_t ** error)1335 int libpff_recover_data_blocks(
1336 libpff_io_handle_t *io_handle,
1337 libbfio_handle_t *file_io_handle,
1338 libpff_descriptors_index_t *descriptors_index,
1339 libpff_offsets_index_t *offsets_index,
1340 libcdata_range_list_t *unallocated_data_block_list,
1341 libcdata_range_list_t *unallocated_page_block_list,
1342 uint8_t recovery_flags,
1343 libcerror_error_t **error )
1344 {
1345 libpff_index_value_t *index_value = NULL;
1346 uint8_t *block_buffer = NULL;
1347 uint8_t *data_block_footer = NULL;
1348 intptr_t *value = NULL;
1349 static char *function = "libpff_recover_data_blocks";
1350 off64_t block_buffer_data_offset = 0;
1351 off64_t block_offset = 0;
1352 off64_t data_block_offset = 0;
1353 off64_t page_block_offset = 0;
1354 size64_t block_size = 0;
1355 size64_t data_block_size = 0;
1356 size64_t page_block_size = 0;
1357 size_t block_buffer_offset = 0;
1358 size_t block_buffer_size_available = 0;
1359 size_t data_block_data_offset = 0;
1360 size_t read_size = 0;
1361 ssize_t read_count = 0;
1362 uint64_t data_block_back_pointer = 0;
1363 uint32_t data_block_calculated_checksum = 0;
1364 uint32_t data_block_stored_checksum = 0;
1365 uint32_t maximum_data_block_size = 0;
1366 uint16_t data_block_data_size = 0;
1367 uint16_t format_data_block_size = 0;
1368 uint16_t format_page_block_size = 0;
1369 uint16_t scan_block_size = 0;
1370 uint8_t supported_recovery_flags = 0;
1371 int index_value_iterator = 0;
1372 int number_of_index_values = 0;
1373 int number_of_unallocated_data_blocks = 0;
1374 int number_of_unallocated_page_blocks = 0;
1375 int result = 0;
1376 int unallocated_data_block_index = 0;
1377 int unallocated_page_block_index = 0;
1378
1379 if( io_handle == NULL )
1380 {
1381 libcerror_error_set(
1382 error,
1383 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1384 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1385 "%s: invalid IO handle.",
1386 function );
1387
1388 return( -1 );
1389 }
1390 if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT )
1391 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT )
1392 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
1393 {
1394 libcerror_error_set(
1395 error,
1396 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1397 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1398 "%s: unsupported file type.",
1399 function );
1400
1401 return( -1 );
1402 }
1403 if( ( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
1404 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) )
1405 {
1406 format_data_block_size = 64;
1407 format_page_block_size = 512;
1408 }
1409 else
1410 {
1411 format_data_block_size = 512;
1412 format_page_block_size = 4096;
1413 }
1414 if( ( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
1415 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) )
1416 {
1417 maximum_data_block_size = 8192;
1418 }
1419 else
1420 {
1421 /* TODO: this value is currently assumed based on the 512 x 8 = 4k page */
1422 maximum_data_block_size = 65536;
1423 }
1424 supported_recovery_flags = LIBPFF_RECOVERY_FLAG_IGNORE_ALLOCATION_DATA
1425 | LIBPFF_RECOVERY_FLAG_SCAN_FOR_FRAGMENTS;
1426
1427 if( ( recovery_flags & ~( supported_recovery_flags ) ) != 0 )
1428 {
1429 libcerror_error_set(
1430 error,
1431 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1432 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1433 "%s: unsupported recovery flags.",
1434 function );
1435
1436 return( -1 );
1437 }
1438 /* Scan the unallocated page block list or all blocks for index nodes
1439 */
1440 if( ( recovery_flags & LIBPFF_RECOVERY_FLAG_IGNORE_ALLOCATION_DATA ) == 0 )
1441 {
1442 if( libcdata_range_list_get_number_of_elements(
1443 unallocated_data_block_list,
1444 &number_of_unallocated_data_blocks,
1445 error ) != 1 )
1446 {
1447 libcerror_error_set(
1448 error,
1449 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1450 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1451 "%s: unable to retrieve number of unallocated data blocks.",
1452 function );
1453
1454 goto on_error;
1455 }
1456 if( ( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
1457 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) )
1458 {
1459 if( libcdata_range_list_get_number_of_elements(
1460 unallocated_page_block_list,
1461 &number_of_unallocated_page_blocks,
1462 error ) != 1 )
1463 {
1464 libcerror_error_set(
1465 error,
1466 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1467 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1468 "%s: unable to retrieve number of unallocated page blocks.",
1469 function );
1470
1471 goto on_error;
1472 }
1473 }
1474 else
1475 {
1476 number_of_unallocated_page_blocks = 0;
1477 }
1478 }
1479 if( ( recovery_flags & LIBPFF_RECOVERY_FLAG_SCAN_FOR_FRAGMENTS ) == 0 )
1480 {
1481 scan_block_size = format_page_block_size;
1482 }
1483 else
1484 {
1485 scan_block_size = format_data_block_size;
1486 }
1487 block_buffer = (uint8_t *) memory_allocate(
1488 sizeof( uint8_t ) * ( maximum_data_block_size * 2 ) );
1489
1490 if( block_buffer == NULL )
1491 {
1492 libcerror_error_set(
1493 error,
1494 LIBCERROR_ERROR_DOMAIN_MEMORY,
1495 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1496 "%s: unable to create block buffer.",
1497 function );
1498
1499 goto on_error;
1500 }
1501 if( ( number_of_unallocated_data_blocks > 0 )
1502 || ( number_of_unallocated_page_blocks > 0 )
1503 || ( ( recovery_flags & LIBPFF_RECOVERY_FLAG_IGNORE_ALLOCATION_DATA ) != 0 ) )
1504 {
1505 block_offset = 0;
1506 data_block_offset = -1;
1507 page_block_offset = -1;
1508
1509 while( block_offset < (off64_t) io_handle->file_size )
1510 {
1511 if( io_handle->abort != 0 )
1512 {
1513 goto on_error;
1514 }
1515 if( ( recovery_flags & LIBPFF_RECOVERY_FLAG_IGNORE_ALLOCATION_DATA ) == 0 )
1516 {
1517 if( data_block_offset < block_offset )
1518 {
1519 if( unallocated_data_block_index < number_of_unallocated_data_blocks )
1520 {
1521 if( libcdata_range_list_get_range_by_index(
1522 unallocated_data_block_list,
1523 unallocated_data_block_index,
1524 (uint64_t *) &data_block_offset,
1525 (uint64_t *) &data_block_size,
1526 &value,
1527 error ) != 1 )
1528 {
1529 libcerror_error_set(
1530 error,
1531 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1532 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1533 "%s: unable to retrieve unallocated data block: %d.",
1534 function,
1535 unallocated_data_block_index );
1536
1537 goto on_error;
1538 }
1539 unallocated_data_block_index++;
1540 }
1541 else
1542 {
1543 data_block_offset = (off64_t) io_handle->file_size;
1544 data_block_size = 0;
1545 }
1546 }
1547 if( page_block_offset < block_offset )
1548 {
1549 if( unallocated_page_block_index < number_of_unallocated_page_blocks )
1550 {
1551 if( libcdata_range_list_get_range_by_index(
1552 unallocated_page_block_list,
1553 unallocated_page_block_index,
1554 (uint64_t *) &page_block_offset,
1555 (uint64_t *) &page_block_size,
1556 &value,
1557 error ) != 1 )
1558 {
1559 libcerror_error_set(
1560 error,
1561 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1562 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1563 "%s: unable to retrieve unallocated page block: %d.",
1564 function,
1565 unallocated_page_block_index );
1566
1567 goto on_error;
1568 }
1569 unallocated_page_block_index++;
1570 }
1571 else
1572 {
1573 page_block_offset = (off64_t) io_handle->file_size;
1574 page_block_size = 0;
1575 }
1576 }
1577 }
1578 if( ( recovery_flags & LIBPFF_RECOVERY_FLAG_IGNORE_ALLOCATION_DATA ) == 0 )
1579 {
1580 if( ( data_block_offset >= (off64_t) io_handle->file_size )
1581 && ( page_block_offset >= (off64_t) io_handle->file_size ) )
1582 {
1583 break;
1584 }
1585 /* Process the smallest offset
1586 */
1587 else if( ( data_block_offset < page_block_offset )
1588 && ( data_block_size > scan_block_size ) )
1589 {
1590 block_offset = data_block_offset;
1591 block_size = data_block_size;
1592 }
1593 else if( ( page_block_offset < data_block_offset )
1594 && ( page_block_size > scan_block_size ) )
1595 {
1596 block_offset = page_block_offset;
1597 block_size = page_block_size;
1598 }
1599 /* Process the largest range
1600 */
1601 else if( data_block_size > page_block_size )
1602 {
1603 block_offset = data_block_offset;
1604 block_size = data_block_size;
1605 }
1606 else
1607 {
1608 block_offset = page_block_offset;
1609 block_size = page_block_size;
1610 }
1611 }
1612 else
1613 {
1614 block_size = scan_block_size;
1615 }
1616 if( ( block_offset % scan_block_size ) != 0 )
1617 {
1618 block_offset = ( ( block_offset / scan_block_size ) + 1 ) * scan_block_size;
1619 block_size -= block_size % scan_block_size;
1620 }
1621 if( block_size < scan_block_size )
1622 {
1623 block_offset += block_size;
1624
1625 continue;
1626 }
1627 while( block_size >= scan_block_size )
1628 {
1629 /* The index nodes have a fixed block size and stored block size aligned
1630 */
1631 if( ( block_size >= format_page_block_size )
1632 && ( ( block_offset % format_page_block_size ) == 0 ) )
1633 {
1634 /* Scan for index values in the index node
1635 */
1636 result = libpff_recover_index_values(
1637 io_handle,
1638 file_io_handle,
1639 descriptors_index,
1640 offsets_index,
1641 unallocated_data_block_list,
1642 block_offset,
1643 recovery_flags,
1644 error );
1645
1646 if( result == -1 )
1647 {
1648 libcerror_error_set(
1649 error,
1650 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1651 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1652 "%s: unable to recover index node at offset: %" PRIi64 ".\n",
1653 function,
1654 block_offset );
1655
1656 goto on_error;
1657 }
1658 else if( result == 1 )
1659 {
1660 block_offset += format_page_block_size;
1661 block_size -= format_page_block_size;
1662
1663 continue;
1664 }
1665 }
1666 if( ( recovery_flags & LIBPFF_RECOVERY_FLAG_SCAN_FOR_FRAGMENTS ) == 0 )
1667 {
1668 block_offset += scan_block_size;
1669 block_size -= scan_block_size;
1670
1671 continue;
1672 }
1673 /* TODO optimize by minimizing amount of reads */
1674 if( block_buffer_size_available == 0 )
1675 {
1676 block_buffer_data_offset = block_offset;
1677
1678 if( block_buffer_offset > 0 )
1679 {
1680 /* TODO optimize by copying the needed data to the front of the buffer */
1681 block_buffer_data_offset -= format_data_block_size;
1682 block_buffer_offset = maximum_data_block_size - format_data_block_size;
1683 }
1684 read_size = (size_t) block_size;
1685
1686 if( read_size > (size_t) maximum_data_block_size )
1687 {
1688 read_size = (size_t) maximum_data_block_size;
1689 }
1690 #if defined( HAVE_DEBUG_OUTPUT )
1691 if( libcnotify_verbose != 0 )
1692 {
1693 libcnotify_printf(
1694 "%s: reading data block at offset: %" PRIi64 " (0x%08" PRIx64 ") of size: %" PRIzd "\n",
1695 function,
1696 block_buffer_data_offset,
1697 block_buffer_data_offset,
1698 read_size );
1699 }
1700 #endif
1701 if( libbfio_handle_seek_offset(
1702 file_io_handle,
1703 block_buffer_data_offset,
1704 SEEK_SET,
1705 error ) == -1 )
1706 {
1707 libcerror_error_set(
1708 error,
1709 LIBCERROR_ERROR_DOMAIN_IO,
1710 LIBCERROR_IO_ERROR_SEEK_FAILED,
1711 "%s: unable to seek data block offset: %" PRIi64 ".",
1712 function,
1713 block_buffer_data_offset );
1714
1715 goto on_error;
1716 }
1717 read_count = libbfio_handle_read_buffer(
1718 file_io_handle,
1719 &( block_buffer[ block_buffer_offset ] ),
1720 read_size,
1721 error );
1722
1723 if( read_count != (ssize_t) read_size )
1724 {
1725 libcerror_error_set(
1726 error,
1727 LIBCERROR_ERROR_DOMAIN_IO,
1728 LIBCERROR_IO_ERROR_READ_FAILED,
1729 "%s: unable to read data block.",
1730 function );
1731
1732 goto on_error;
1733 }
1734 block_buffer_size_available = read_size;
1735 }
1736 if( block_buffer_size_available >= format_data_block_size )
1737 {
1738 /* Scan the block for a data block footer
1739 */
1740 data_block_footer = &( block_buffer[ block_buffer_offset ] );
1741
1742 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
1743 {
1744 data_block_footer += format_data_block_size - sizeof( pff_block_footer_32bit_t );
1745
1746 byte_stream_copy_to_uint16_little_endian(
1747 ( (pff_block_footer_32bit_t *) data_block_footer )->data_size,
1748 data_block_data_size );
1749 byte_stream_copy_to_uint32_little_endian(
1750 ( (pff_block_footer_32bit_t *) data_block_footer )->back_pointer,
1751 data_block_back_pointer );
1752 byte_stream_copy_to_uint32_little_endian(
1753 ( (pff_block_footer_32bit_t *) data_block_footer )->checksum,
1754 data_block_stored_checksum );
1755 }
1756 else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
1757 {
1758 data_block_footer += format_data_block_size - sizeof( pff_block_footer_64bit_t );
1759
1760 byte_stream_copy_to_uint16_little_endian(
1761 ( (pff_block_footer_64bit_t *) data_block_footer )->data_size,
1762 data_block_data_size );
1763 byte_stream_copy_to_uint32_little_endian(
1764 ( (pff_block_footer_64bit_t *) data_block_footer )->checksum,
1765 data_block_stored_checksum );
1766 byte_stream_copy_to_uint64_little_endian(
1767 ( (pff_block_footer_64bit_t *) data_block_footer )->back_pointer,
1768 data_block_back_pointer );
1769 }
1770 else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
1771 {
1772 data_block_footer += format_data_block_size - sizeof( pff_block_footer_64bit_4k_page_t );
1773
1774 byte_stream_copy_to_uint16_little_endian(
1775 ( (pff_block_footer_64bit_4k_page_t *) data_block_footer )->data_size,
1776 data_block_data_size );
1777 byte_stream_copy_to_uint32_little_endian(
1778 ( (pff_block_footer_64bit_4k_page_t *) data_block_footer )->checksum,
1779 data_block_stored_checksum );
1780 byte_stream_copy_to_uint64_little_endian(
1781 ( (pff_block_footer_64bit_4k_page_t *) data_block_footer )->back_pointer,
1782 data_block_back_pointer );
1783 }
1784 /* Check if back pointer itself is not empty but the upper 32-bit are
1785 */
1786 if( ( data_block_back_pointer != 0 )
1787 && ( ( data_block_back_pointer >> 32 ) == 0 ) )
1788 {
1789 data_block_data_offset = block_buffer_offset - ( ( data_block_data_size / format_data_block_size ) * format_data_block_size );
1790
1791 if( (size_t) data_block_data_size < read_size )
1792 {
1793 /* Check for duplicates
1794 */
1795 if( libpff_index_tree_get_number_of_leaf_nodes_by_identifier(
1796 offsets_index->recovered_index_tree,
1797 file_io_handle,
1798 offsets_index->index_cache,
1799 data_block_back_pointer,
1800 &number_of_index_values,
1801 error ) != 1 )
1802 {
1803 libcerror_error_set(
1804 error,
1805 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1806 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1807 "%s: unable to retrieve number of recovered offset index values for identifier: %" PRIu64 ".",
1808 function,
1809 data_block_back_pointer );
1810
1811 goto on_error;
1812 }
1813 result = 0;
1814
1815 for( index_value_iterator = 0;
1816 index_value_iterator < number_of_index_values;
1817 index_value_iterator++ )
1818 {
1819 result = libpff_index_tree_get_value_by_identifier(
1820 offsets_index->recovered_index_tree,
1821 file_io_handle,
1822 offsets_index->index_cache,
1823 data_block_back_pointer,
1824 index_value_iterator,
1825 &index_value,
1826 error );
1827
1828 if( result == -1 )
1829 {
1830 libcerror_error_set(
1831 error,
1832 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1833 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1834 "%s: unable to retrieve recovered offset index value for identifier: %" PRIu64 ".",
1835 function,
1836 data_block_back_pointer );
1837
1838 goto on_error;
1839 }
1840 else if( result != 0 )
1841 {
1842 if( ( (off64_t) ( block_buffer_data_offset + data_block_data_offset ) == index_value->file_offset )
1843 && ( (size32_t) data_block_data_size == index_value->data_size ) )
1844 {
1845 break;
1846 }
1847 result = 0;
1848 }
1849 }
1850 if( result != 0 )
1851 {
1852 #if defined( HAVE_DEBUG_OUTPUT )
1853 if( libcnotify_verbose != 0 )
1854 {
1855 libcnotify_printf(
1856 "%s: recovered data block with identifier: %" PRIu64 " matches existing recovered item value.\n",
1857 function,
1858 data_block_back_pointer );
1859 }
1860 #endif
1861 block_offset += format_data_block_size;
1862 block_size -= format_data_block_size;
1863
1864 /* TODO reset block_buffer_offset and block_buffer_size_available ? */
1865
1866 continue;
1867 }
1868 if( data_block_stored_checksum != 0 )
1869 {
1870 if( libfmapi_checksum_calculate_weak_crc32(
1871 &data_block_calculated_checksum,
1872 &( block_buffer[ data_block_data_offset ] ),
1873 data_block_data_size,
1874 0,
1875 error ) != 1 )
1876 {
1877 libcerror_error_set(
1878 error,
1879 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1880 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1881 "%s: unable to calculate weak CRC-32.",
1882 function );
1883
1884 goto on_error;
1885 }
1886 if( data_block_stored_checksum != data_block_calculated_checksum )
1887 {
1888 #if defined( HAVE_DEBUG_OUTPUT )
1889 if( libcnotify_verbose != 0 )
1890 {
1891 libcnotify_printf(
1892 "%s: mismatch in data block: %" PRIu64 " checksum ( %" PRIu32 " != %" PRIu32 " ).\n",
1893 function,
1894 data_block_back_pointer,
1895 data_block_stored_checksum,
1896 data_block_calculated_checksum );
1897 }
1898 #endif
1899 block_offset += format_data_block_size;
1900 block_size -= format_data_block_size;
1901
1902 continue;
1903 }
1904 }
1905 /* TODO consider data block as fragment */
1906
1907 data_block_data_size = ( ( data_block_data_size / format_data_block_size ) + 1 ) * format_data_block_size;
1908
1909 #if defined( HAVE_DEBUG_OUTPUT )
1910 if( libcnotify_verbose != 0 )
1911 {
1912 libcnotify_printf(
1913 "%s: data block back pointer: 0x%08" PRIx64 "\n",
1914 function,
1915 data_block_back_pointer );
1916
1917 libcnotify_printf(
1918 "%s: data block data at offset: %" PRIi64 " (0x%08" PRIx64 ") of size: %" PRIzd "\n",
1919 function,
1920 block_buffer_data_offset + data_block_data_offset,
1921 block_buffer_data_offset + data_block_data_offset,
1922 data_block_data_size );
1923 libcnotify_print_data(
1924 &( block_buffer[ data_block_data_offset ] ),
1925 data_block_data_size,
1926 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1927 }
1928 #endif
1929 }
1930 }
1931 block_buffer_offset += format_data_block_size;
1932 block_buffer_size_available -= format_data_block_size;
1933 }
1934 else
1935 {
1936 block_buffer_offset = 0;
1937 block_buffer_size_available = 0;
1938 }
1939 block_offset += scan_block_size;
1940 block_size -= scan_block_size;
1941 }
1942 }
1943 }
1944 memory_free(
1945 block_buffer );
1946
1947 return( 1 );
1948
1949 on_error:
1950 if( block_buffer != NULL )
1951 {
1952 memory_free(
1953 block_buffer );
1954 }
1955 return( -1 );
1956 }
1957
1958 /* Scans for recoverable index values in an index node
1959 * Returns 1 if successful, returns 0 if no valid index node could be found or -1 on error
1960 */
libpff_recover_index_values(libpff_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libpff_descriptors_index_t * descriptors_index,libpff_offsets_index_t * offsets_index,libcdata_range_list_t * unallocated_data_block_list,size64_t node_offset,uint8_t recovery_flags,libcerror_error_t ** error)1961 int libpff_recover_index_values(
1962 libpff_io_handle_t *io_handle,
1963 libbfio_handle_t *file_io_handle,
1964 libpff_descriptors_index_t *descriptors_index,
1965 libpff_offsets_index_t *offsets_index,
1966 libcdata_range_list_t *unallocated_data_block_list,
1967 size64_t node_offset,
1968 uint8_t recovery_flags,
1969 libcerror_error_t **error )
1970 {
1971 libpff_index_value_t *index_value = NULL;
1972 libpff_index_node_t *index_node = NULL;
1973 uint8_t *node_entry_data = NULL;
1974 const char *index_string = NULL;
1975 static char *function = "libpff_recover_index_values";
1976 off64_t index_value_file_offset = 0;
1977 uint64_t index_value_data_identifier = 0;
1978 uint64_t index_value_identifier = 0;
1979 uint64_t index_value_local_descriptors_identifier = 0;
1980 uint32_t maximum_data_block_data_size = 0;
1981 uint16_t index_value_data_size = 0;
1982 uint8_t entry_index = 0;
1983 int index_value_iterator = 0;
1984 int number_of_index_values = 0;
1985 int result = 0;
1986
1987 if( io_handle == NULL )
1988 {
1989 libcerror_error_set(
1990 error,
1991 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1992 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1993 "%s: invalid IO handle.",
1994 function );
1995
1996 return( -1 );
1997 }
1998 if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT )
1999 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT )
2000 && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
2001 {
2002 libcerror_error_set(
2003 error,
2004 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2005 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2006 "%s: unsupported file type.",
2007 function );
2008
2009 return( -1 );
2010 }
2011 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
2012 {
2013 maximum_data_block_data_size = 8192 - 12;
2014 }
2015 else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
2016 {
2017 maximum_data_block_data_size = 8192 - 16;
2018 }
2019 else
2020 {
2021 /* TODO: this value is currently assumed based on the 512 x 8 = 4k page */
2022 maximum_data_block_data_size = 65536 - 24;
2023 }
2024 if( libpff_index_node_initialize(
2025 &index_node,
2026 error ) != 1 )
2027 {
2028 libcerror_error_set(
2029 error,
2030 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2031 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2032 "%s: unable to create index node.",
2033 function );
2034
2035 goto on_error;
2036 }
2037 if( libpff_index_node_read_file_io_handle(
2038 index_node,
2039 file_io_handle,
2040 node_offset,
2041 io_handle->file_type,
2042 error ) != 1 )
2043 {
2044 #if defined( HAVE_DEBUG_OUTPUT )
2045 if( ( libcnotify_verbose != 0 )
2046 && ( error != NULL )
2047 && ( *error != NULL ) )
2048 {
2049 libcnotify_print_error_backtrace(
2050 *error );
2051 }
2052 #endif
2053 libcerror_error_free(
2054 error );
2055
2056 libpff_index_node_free(
2057 &index_node,
2058 NULL );
2059
2060 return( 0 );
2061 }
2062 if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
2063 {
2064 index_string = "descriptor";
2065 }
2066 else if( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
2067 {
2068 index_string = "offset";
2069 }
2070 if( ( index_node->type != LIBPFF_INDEX_TYPE_DESCRIPTOR )
2071 && ( index_node->type != LIBPFF_INDEX_TYPE_OFFSET ) )
2072 {
2073 #if defined( HAVE_DEBUG_OUTPUT )
2074 if( libcnotify_verbose != 0 )
2075 {
2076 libcnotify_printf(
2077 "%s: unsupported index type: 0x%02" PRIx8 ".\n",
2078 function,
2079 index_node->type );
2080 }
2081 #endif
2082 }
2083 else if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF )
2084 {
2085 #if defined( HAVE_DEBUG_OUTPUT )
2086 if( libcnotify_verbose != 0 )
2087 {
2088 libcnotify_printf(
2089 "%s: skipping %s index branch node at level: %" PRIu8 ".\n",
2090 function,
2091 index_string,
2092 index_node->level );
2093 }
2094 #endif
2095 }
2096 else
2097 {
2098 /* Check if the index leaf entries are recoverable
2099 */
2100 for( entry_index = 0;
2101 entry_index < index_node->maximum_number_of_entries;
2102 entry_index++ )
2103 {
2104 if( libpff_index_node_get_entry_data(
2105 index_node,
2106 entry_index,
2107 &node_entry_data,
2108 error ) != 1 )
2109 {
2110 libcerror_error_set(
2111 error,
2112 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2113 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2114 "%s: unable to retrieve node entry: %" PRIu8 " data.",
2115 function,
2116 entry_index );
2117
2118 goto on_error;
2119 }
2120 if( node_entry_data == NULL )
2121 {
2122 libcerror_error_set(
2123 error,
2124 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2125 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2126 "%s: missing node entry: %" PRIu8 " data.",
2127 function,
2128 entry_index );
2129
2130 goto on_error;
2131 }
2132 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
2133 {
2134 byte_stream_copy_to_uint32_little_endian(
2135 node_entry_data,
2136 index_value_identifier );
2137 }
2138 else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
2139 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
2140 {
2141 byte_stream_copy_to_uint64_little_endian(
2142 node_entry_data,
2143 index_value_identifier );
2144 }
2145 /* Ignore the upper 32-bit of descriptor identifiers
2146 */
2147 if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
2148 {
2149 index_value_identifier &= 0xffffffffUL;
2150 }
2151 #if defined( HAVE_DEBUG_OUTPUT )
2152 if( libcnotify_verbose != 0 )
2153 {
2154 libcnotify_printf(
2155 "%s: analyzing %s index entry: %" PRIu8 " identifier: %" PRIu64 ".\n",
2156 function,
2157 index_string,
2158 entry_index,
2159 index_value_identifier );
2160 }
2161 #endif
2162 /* Ignore index values without an identifier
2163 */
2164 if( index_value_identifier == 0 )
2165 {
2166 #if defined( HAVE_DEBUG_OUTPUT )
2167 if( libcnotify_verbose != 0 )
2168 {
2169 libcnotify_printf(
2170 "%s: %s index entry: %" PRIu8 " indentifier: %" PRIu64 " has an empty identifier.\n",
2171 function,
2172 index_string,
2173 entry_index,
2174 index_value_identifier );
2175 }
2176 #endif
2177 continue;
2178 }
2179 if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
2180 {
2181 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
2182 {
2183 byte_stream_copy_to_uint32_little_endian(
2184 ( (pff_index_node_descriptor_entry_32bit_t *) node_entry_data )->data_identifier,
2185 index_value_data_identifier );
2186 byte_stream_copy_to_uint32_little_endian(
2187 ( (pff_index_node_descriptor_entry_32bit_t *) node_entry_data )->local_descriptors_identifier,
2188 index_value_local_descriptors_identifier );
2189 }
2190 else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
2191 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
2192 {
2193 byte_stream_copy_to_uint64_little_endian(
2194 ( (pff_index_node_descriptor_entry_64bit_t *) node_entry_data )->data_identifier,
2195 index_value_data_identifier );
2196 byte_stream_copy_to_uint64_little_endian(
2197 ( (pff_index_node_descriptor_entry_64bit_t *) node_entry_data )->local_descriptors_identifier,
2198 index_value_local_descriptors_identifier );
2199 }
2200 }
2201 else if( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
2202 {
2203 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
2204 {
2205 byte_stream_copy_to_uint32_little_endian(
2206 ( (pff_index_node_offset_entry_32bit_t *) node_entry_data )->file_offset,
2207 index_value_file_offset );
2208 byte_stream_copy_to_uint16_little_endian(
2209 ( (pff_index_node_offset_entry_32bit_t *) node_entry_data )->data_size,
2210 index_value_data_size );
2211 }
2212 else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
2213 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
2214 {
2215 byte_stream_copy_to_uint64_little_endian(
2216 ( (pff_index_node_offset_entry_64bit_t *) node_entry_data )->file_offset,
2217 index_value_file_offset );
2218 byte_stream_copy_to_uint16_little_endian(
2219 ( (pff_index_node_offset_entry_64bit_t *) node_entry_data )->data_size,
2220 index_value_data_size );
2221 }
2222 }
2223 if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
2224 {
2225 /* Ignore descriptor index values without a data identifier
2226 */
2227 if( index_value_data_identifier == 0 )
2228 {
2229 #if defined( HAVE_DEBUG_OUTPUT )
2230 if( libcnotify_verbose != 0 )
2231 {
2232 libcnotify_printf(
2233 "%s: %s index entry: %" PRIu8 " identifier: %" PRIu64 " has an empty data identifier.\n",
2234 function,
2235 index_string,
2236 entry_index,
2237 index_value_identifier );
2238 }
2239 #endif
2240 continue;
2241 }
2242 }
2243 else if( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
2244 {
2245 /* Ignore index values without a valid file offset
2246 */
2247 if( index_value_file_offset <= 0 )
2248 {
2249 #if defined( HAVE_DEBUG_OUTPUT )
2250 if( libcnotify_verbose != 0 )
2251 {
2252 libcnotify_printf(
2253 "%s: %s index entry: %" PRIu8 " identifier: %" PRIu64 " has an invalid file offset: %" PRIi64 ".\n",
2254 function,
2255 index_string,
2256 entry_index,
2257 index_value_identifier,
2258 index_value_file_offset );
2259 }
2260 #endif
2261 continue;
2262 }
2263 /* Ignore index values without a valid data size
2264 */
2265 if( ( index_value_data_size == 0 )
2266 || ( (uint32_t) index_value_data_size > maximum_data_block_data_size ) )
2267 {
2268 #if defined( HAVE_DEBUG_OUTPUT )
2269 if( libcnotify_verbose != 0 )
2270 {
2271 libcnotify_printf(
2272 "%s: %s index entry: %" PRIu8 " identifier: %" PRIu64 " has an invalid data size: %" PRIu16 ".\n",
2273 function,
2274 index_string,
2275 entry_index,
2276 index_value_identifier,
2277 index_value_data_size );
2278 }
2279 #endif
2280 continue;
2281 }
2282 }
2283 /* Check if the recovered item value matches the existing item value
2284 */
2285 if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
2286 {
2287 result = libpff_index_tree_get_value_by_identifier(
2288 descriptors_index->index_tree,
2289 file_io_handle,
2290 descriptors_index->index_cache,
2291 index_value_identifier,
2292 0,
2293 &index_value,
2294 error );
2295 }
2296 else if( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
2297 {
2298 result = libpff_index_tree_get_value_by_identifier(
2299 offsets_index->index_tree,
2300 file_io_handle,
2301 offsets_index->index_cache,
2302 index_value_identifier,
2303 0,
2304 &index_value,
2305 error );
2306 }
2307 if( result == -1 )
2308 {
2309 libcerror_error_set(
2310 error,
2311 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2312 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2313 "%s: unable to retrieve %s index value for identifier: %" PRIu64 ".",
2314 function,
2315 index_string,
2316 index_value_identifier );
2317
2318 goto on_error;
2319 }
2320 else if( result != 0 )
2321 {
2322 if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
2323 {
2324 /* TODO what about parent changes ? */
2325 if( ( index_value_data_identifier == index_value->data_identifier )
2326 && ( index_value_local_descriptors_identifier == index_value->local_descriptors_identifier ) )
2327 {
2328 #if defined( HAVE_DEBUG_OUTPUT )
2329 if( libcnotify_verbose != 0 )
2330 {
2331 libcnotify_printf(
2332 "%s: recovered descriptor index value: %" PRIu64 " matches existing item value.\n",
2333 function,
2334 index_value_identifier );
2335 }
2336 #endif
2337 continue;
2338 }
2339 }
2340 else if( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
2341 {
2342 if( ( index_value_file_offset == index_value->file_offset )
2343 && ( (size32_t) index_value_data_size == index_value->data_size ) )
2344 {
2345 #if defined( HAVE_DEBUG_OUTPUT )
2346 if( libcnotify_verbose != 0 )
2347 {
2348 libcnotify_printf(
2349 "%s: recovered offset index value: %" PRIu64 " matches existing item value.\n",
2350 function,
2351 index_value_identifier );
2352 }
2353 #endif
2354 continue;
2355 }
2356 }
2357 }
2358 /* Check for duplicates
2359 */
2360 if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
2361 {
2362 result = libpff_index_tree_get_number_of_leaf_nodes_by_identifier(
2363 descriptors_index->recovered_index_tree,
2364 file_io_handle,
2365 descriptors_index->index_cache,
2366 index_value_identifier,
2367 &number_of_index_values,
2368 error );
2369 }
2370 else if( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
2371 {
2372 result = libpff_index_tree_get_number_of_leaf_nodes_by_identifier(
2373 offsets_index->recovered_index_tree,
2374 file_io_handle,
2375 offsets_index->index_cache,
2376 index_value_identifier,
2377 &number_of_index_values,
2378 error );
2379 }
2380 if( result != 1 )
2381 {
2382 libcerror_error_set(
2383 error,
2384 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2385 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2386 "%s: unable to retrieve number of recovered %s index values for identifier: %" PRIu64 ".",
2387 function,
2388 index_string,
2389 index_value_identifier );
2390
2391 goto on_error;
2392 }
2393 result = 0;
2394
2395 for( index_value_iterator = 0;
2396 index_value_iterator < number_of_index_values;
2397 index_value_iterator++ )
2398 {
2399 if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
2400 {
2401 result = libpff_index_tree_get_value_by_identifier(
2402 descriptors_index->recovered_index_tree,
2403 file_io_handle,
2404 descriptors_index->index_cache,
2405 index_value_identifier,
2406 index_value_iterator,
2407 &index_value,
2408 error );
2409 }
2410 else if( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
2411 {
2412 result = libpff_index_tree_get_value_by_identifier(
2413 offsets_index->recovered_index_tree,
2414 file_io_handle,
2415 offsets_index->index_cache,
2416 index_value_identifier,
2417 index_value_iterator,
2418 &index_value,
2419 error );
2420 }
2421 if( result == -1 )
2422 {
2423 libcerror_error_set(
2424 error,
2425 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2426 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2427 "%s: unable to retrieve recovered %s index value for identifier: %" PRIu64 ".",
2428 function,
2429 index_string,
2430 index_value_identifier );
2431
2432 goto on_error;
2433 }
2434 else if( result != 0 )
2435 {
2436 if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
2437 {
2438 /* TODO what about parent changes ? */
2439 if( ( index_value_data_identifier == index_value->data_identifier )
2440 && ( index_value_local_descriptors_identifier == index_value->local_descriptors_identifier ) )
2441 {
2442 break;
2443 }
2444 }
2445 else if( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
2446 {
2447 if( ( index_value_file_offset == index_value->file_offset )
2448 && ( (size32_t) index_value_data_size == index_value->data_size ) )
2449 {
2450 break;
2451 }
2452 }
2453 result = 0;
2454 }
2455 }
2456 if( result != 0 )
2457 {
2458 #if defined( HAVE_DEBUG_OUTPUT )
2459 if( libcnotify_verbose != 0 )
2460 {
2461 libcnotify_printf(
2462 "%s: recovered %s index value: %" PRIu64 " matches existing item value.\n",
2463 function,
2464 index_string,
2465 index_value_identifier );
2466 }
2467 #endif
2468 continue;
2469 }
2470 /* Check if the offset index value is unallocated according to the
2471 * unallocated data block list
2472 */
2473 if( ( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
2474 && ( ( recovery_flags & LIBPFF_RECOVERY_FLAG_IGNORE_ALLOCATION_DATA ) == 0 ) )
2475 {
2476 result = libcdata_range_list_range_is_present(
2477 unallocated_data_block_list,
2478 (uint64_t) index_value_file_offset,
2479 (uint64_t) index_value_data_size,
2480 error );
2481
2482 if( result == -1 )
2483 {
2484 libcerror_error_set(
2485 error,
2486 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2487 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2488 "%s: error determining if offset range is unallocated.",
2489 function );
2490
2491 goto on_error;
2492 }
2493 else if( result == 0 )
2494 {
2495 #if defined( HAVE_DEBUG_OUTPUT )
2496 if( libcnotify_verbose != 0 )
2497 {
2498 libcnotify_printf(
2499 "%s: %s index entry: %" PRIu8 " identifier: %" PRIu64 " refers to allocated range: 0x%08" PRIx64 " - 0x%08" PRIx64 " (%" PRIu64 ").\n",
2500 function,
2501 index_string,
2502 entry_index,
2503 index_value_identifier,
2504 index_value_file_offset,
2505 index_value_file_offset + index_value_data_size,
2506 index_value_data_size );
2507 }
2508 #endif
2509 continue;
2510 }
2511 #if defined( HAVE_DEBUG_OUTPUT )
2512 if( libcnotify_verbose != 0 )
2513 {
2514 libcnotify_printf(
2515 "%s: %s index entry: %" PRIu8 " identifier: %" PRIu64 " refers to unallocated range: 0x%08" PRIx64 " - 0x%08" PRIx64 " (%" PRIu64 ").\n",
2516 function,
2517 index_string,
2518 entry_index,
2519 index_value_identifier,
2520 index_value_file_offset,
2521 index_value_file_offset + index_value_data_size,
2522 index_value_data_size );
2523 }
2524 #endif
2525 }
2526 /* Move the recovered node to the index
2527 */
2528 #if defined( HAVE_DEBUG_OUTPUT )
2529 if( libcnotify_verbose != 0 )
2530 {
2531 libcnotify_printf(
2532 "%s: %s index entry: %" PRIu8 " identifier: %" PRIu64 " is recoverable.\n",
2533 function,
2534 index_string,
2535 entry_index,
2536 index_value_identifier );
2537 }
2538 #endif
2539 if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
2540 {
2541 result = libpff_index_tree_insert_value(
2542 descriptors_index->recovered_index_tree,
2543 file_io_handle,
2544 descriptors_index->index_cache,
2545 index_value_identifier,
2546 node_offset,
2547 (size64_t) entry_index,
2548 error );
2549 }
2550 else if( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
2551 {
2552 result = libpff_index_tree_insert_value(
2553 offsets_index->recovered_index_tree,
2554 file_io_handle,
2555 offsets_index->index_cache,
2556 index_value_identifier,
2557 node_offset,
2558 (size64_t) entry_index,
2559 error );
2560 }
2561 if( result != 1 )
2562 {
2563 libcerror_error_set(
2564 error,
2565 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2566 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2567 "%s: unable to insert %s index value: %" PRIu64 " to recovered index tree.",
2568 function,
2569 index_string,
2570 index_value_identifier );
2571
2572 goto on_error;
2573 }
2574 node_offset += index_node->entry_size;
2575 }
2576 }
2577 if( libpff_index_node_free(
2578 &index_node,
2579 error ) != 1 )
2580 {
2581 libcerror_error_set(
2582 error,
2583 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2584 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2585 "%s: unable to free index node.",
2586 function );
2587
2588 goto on_error;
2589 }
2590 #if defined( HAVE_DEBUG_OUTPUT )
2591 if( libcnotify_verbose != 0 )
2592 {
2593 libcnotify_printf(
2594 "\n" );
2595 }
2596 #endif
2597 return( 1 );
2598
2599 on_error:
2600 if( index_node != NULL )
2601 {
2602 libpff_index_node_free(
2603 &index_node,
2604 NULL );
2605 }
2606 return( -1 );
2607 }
2608
2609 /* Scans for recoverable local descriptors
2610 * Returns 1 if successful, returns 0 if no valid local descriptors node could be found or -1 on error
2611 */
libpff_recover_local_descriptors(libpff_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libpff_offsets_index_t * offsets_index,uint64_t local_descriptors_identifier,libcerror_error_t ** error)2612 int libpff_recover_local_descriptors(
2613 libpff_io_handle_t *io_handle,
2614 libbfio_handle_t *file_io_handle,
2615 libpff_offsets_index_t *offsets_index,
2616 uint64_t local_descriptors_identifier,
2617 libcerror_error_t **error )
2618 {
2619 libpff_index_value_t *offset_index_value = NULL;
2620 libpff_local_descriptor_node_t *local_descriptor_node = NULL;
2621 uint8_t *node_entry_data = NULL;
2622 static char *function = "libpff_recover_local_descriptors";
2623 uint64_t local_descriptor_value_identifier = 0;
2624 uint64_t local_descriptor_value_data_identifier = 0;
2625 uint64_t local_descriptor_value_local_descriptors_identifier = 0;
2626 uint64_t local_descriptor_value_sub_node_identifier = 0;
2627 uint16_t entry_index = 0;
2628 int result = 1;
2629
2630 if( io_handle == NULL )
2631 {
2632 libcerror_error_set(
2633 error,
2634 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2635 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2636 "%s: invalid IO handle.",
2637 function );
2638
2639 return( -1 );
2640 }
2641 if( libpff_offsets_index_get_index_value_by_identifier(
2642 offsets_index,
2643 file_io_handle,
2644 local_descriptors_identifier,
2645 1,
2646 0,
2647 &offset_index_value,
2648 error ) != 1 )
2649 {
2650 #if defined( HAVE_DEBUG_OUTPUT )
2651 if( ( libcnotify_verbose != 0 )
2652 && ( error != NULL )
2653 && ( *error != NULL ) )
2654 {
2655 libcnotify_print_error_backtrace(
2656 *error );
2657 }
2658 #endif
2659 libcerror_error_free(
2660 error );
2661
2662 return( 0 );
2663 }
2664 if( offset_index_value == NULL )
2665 {
2666 libcerror_error_set(
2667 error,
2668 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2669 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2670 "%s: missing offset index value.",
2671 function );
2672
2673 return( -1 );
2674 }
2675 #if defined( HAVE_DEBUG_OUTPUT )
2676 if( libcnotify_verbose != 0 )
2677 {
2678 libcnotify_printf(
2679 "%s: local descriptor node identifier: %" PRIu64 " (%s) at offset: %" PRIi64 " of size: %" PRIu32 "\n",
2680 function,
2681 offset_index_value->identifier,
2682 ( ( offset_index_value->identifier & LIBPFF_OFFSET_INDEX_IDENTIFIER_FLAG_INTERNAL ) ? "internal" : "external" ),
2683 offset_index_value->file_offset,
2684 offset_index_value->data_size );
2685 }
2686 #endif
2687 if( libpff_local_descriptor_node_initialize(
2688 &local_descriptor_node,
2689 error ) != 1 )
2690 {
2691 libcerror_error_set(
2692 error,
2693 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2694 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2695 "%s: unable to create local descriptor node.",
2696 function );
2697
2698 return( -1 );
2699 }
2700 if( libpff_local_descriptor_node_read(
2701 local_descriptor_node,
2702 io_handle,
2703 file_io_handle,
2704 0 /* TODO descriptor identifier */,
2705 offset_index_value->identifier,
2706 offset_index_value->file_offset,
2707 offset_index_value->data_size,
2708 error ) != 1 )
2709 {
2710 #if defined( HAVE_DEBUG_OUTPUT )
2711 if( ( libcnotify_verbose != 0 )
2712 && ( error != NULL )
2713 && ( *error != NULL ) )
2714 {
2715 libcnotify_print_error_backtrace(
2716 *error );
2717 }
2718 #endif
2719 libcerror_error_free(
2720 error );
2721
2722 libpff_local_descriptor_node_free(
2723 &local_descriptor_node,
2724 NULL );
2725
2726 return( 0 );
2727 }
2728 for( entry_index = 0;
2729 entry_index < local_descriptor_node->number_of_entries;
2730 entry_index++ )
2731 {
2732 if( libpff_local_descriptor_node_get_entry_data(
2733 local_descriptor_node,
2734 entry_index,
2735 &node_entry_data,
2736 error ) != 1 )
2737 {
2738 libcerror_error_set(
2739 error,
2740 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2741 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2742 "%s: unable to retrieve node entry: %" PRIu16 " data.",
2743 function,
2744 entry_index );
2745
2746 return( -1 );
2747 }
2748 if( node_entry_data == NULL )
2749 {
2750 libcerror_error_set(
2751 error,
2752 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2753 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2754 "%s: missing node entry: %" PRIu16 " data.",
2755 function,
2756 entry_index );
2757
2758 return( -1 );
2759 }
2760 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
2761 {
2762 byte_stream_copy_to_uint32_little_endian(
2763 node_entry_data,
2764 local_descriptor_value_identifier );
2765
2766 node_entry_data += 4;
2767 }
2768 else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
2769 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
2770 {
2771 byte_stream_copy_to_uint64_little_endian(
2772 node_entry_data,
2773 local_descriptor_value_identifier );
2774
2775 node_entry_data += 8;
2776 }
2777 /* Ignore the upper 32-bit of local descriptor identifiers
2778 */
2779 local_descriptor_value_identifier &= 0xffffffffUL;
2780
2781 /* Ignore local descriptor values without a data identifier
2782 */
2783 if( local_descriptor_value_identifier == 0 )
2784 {
2785 #if defined( HAVE_DEBUG_OUTPUT )
2786 if( libcnotify_verbose != 0 )
2787 {
2788 libcnotify_printf(
2789 "%s: local descriptor entry: %" PRIu8 " identifier: %" PRIu64 " has an empty identifier.\n",
2790 function,
2791 entry_index,
2792 local_descriptor_value_identifier );
2793 }
2794 #endif
2795 result = 0;
2796
2797 break;
2798 }
2799 if( local_descriptor_node->level == LIBPFF_LOCAL_DESCRIPTOR_NODE_LEVEL_LEAF )
2800 {
2801 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
2802 {
2803 byte_stream_copy_to_uint32_little_endian(
2804 node_entry_data,
2805 local_descriptor_value_data_identifier );
2806
2807 node_entry_data += 4;
2808
2809 byte_stream_copy_to_uint32_little_endian(
2810 node_entry_data,
2811 local_descriptor_value_local_descriptors_identifier );
2812
2813 node_entry_data += 4;
2814 }
2815 else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
2816 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
2817 {
2818 byte_stream_copy_to_uint64_little_endian(
2819 node_entry_data,
2820 local_descriptor_value_data_identifier );
2821
2822 node_entry_data += 8;
2823
2824 byte_stream_copy_to_uint64_little_endian(
2825 node_entry_data,
2826 local_descriptor_value_local_descriptors_identifier );
2827
2828 node_entry_data += 8;
2829 }
2830 /* Ignore local descriptor values without a data identifier
2831 */
2832 if( local_descriptor_value_data_identifier == 0 )
2833 {
2834 #if defined( HAVE_DEBUG_OUTPUT )
2835 if( libcnotify_verbose != 0 )
2836 {
2837 libcnotify_printf(
2838 "%s: local descriptor entry: %" PRIu8 " identifier: %" PRIu64 " has an empty data identifier.\n",
2839 function,
2840 entry_index,
2841 local_descriptor_value_identifier );
2842 }
2843 #endif
2844 result = 0;
2845
2846 break;
2847 }
2848 }
2849 else
2850 {
2851 if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
2852 {
2853 byte_stream_copy_to_uint32_little_endian(
2854 node_entry_data,
2855 local_descriptor_value_sub_node_identifier );
2856
2857 node_entry_data += 4;
2858 }
2859 else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
2860 || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
2861 {
2862 byte_stream_copy_to_uint64_little_endian(
2863 node_entry_data,
2864 local_descriptor_value_sub_node_identifier );
2865
2866 node_entry_data += 8;
2867 }
2868 /* Ignore local descriptor values without a sub node identifier
2869 */
2870 if( local_descriptor_value_sub_node_identifier == 0 )
2871 {
2872 #if defined( HAVE_DEBUG_OUTPUT )
2873 if( libcnotify_verbose != 0 )
2874 {
2875 libcnotify_printf(
2876 "%s: local descriptor entry: %" PRIu8 " identifier: %" PRIu64 " has an empty sub node identifier.\n",
2877 function,
2878 entry_index,
2879 local_descriptor_value_identifier );
2880 }
2881 #endif
2882 result = 0;
2883
2884 break;
2885 }
2886 result = libpff_recover_local_descriptors(
2887 io_handle,
2888 file_io_handle,
2889 offsets_index,
2890 local_descriptor_value_sub_node_identifier,
2891 error );
2892
2893 if( result == -1 )
2894 {
2895 libcerror_error_set(
2896 error,
2897 LIBCERROR_ERROR_DOMAIN_IO,
2898 LIBCERROR_IO_ERROR_READ_FAILED,
2899 "%s: unable to read local descriptors with identifier: %" PRIu64 ".",
2900 function,
2901 local_descriptor_value_sub_node_identifier );
2902
2903 libpff_local_descriptor_node_free(
2904 &local_descriptor_node,
2905 NULL );
2906
2907 return( -1 );
2908 }
2909 else if( result == 0 )
2910 {
2911 break;
2912 }
2913 }
2914 }
2915 if( libpff_local_descriptor_node_free(
2916 &local_descriptor_node,
2917 error ) != 1 )
2918 {
2919 libcerror_error_set(
2920 error,
2921 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2922 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2923 "%s: unable to free local descriptor node.",
2924 function );
2925
2926 return( -1 );
2927 }
2928 #if defined( HAVE_DEBUG_OUTPUT )
2929 if( libcnotify_verbose != 0 )
2930 {
2931 libcnotify_printf(
2932 "\n" );
2933 }
2934 #endif
2935 return( result );
2936 }
2937
2938