Coverage Report

Created: 2025-06-24 07:14

/src/libpff/libpff/libpff_recover.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Recover functions
3
 *
4
 * Copyright (C) 2008-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 "libpff_checksum.h"
28
#include "libpff_data_block.h"
29
#include "libpff_definitions.h"
30
#include "libpff_descriptors_index.h"
31
#include "libpff_index.h"
32
#include "libpff_index_node.h"
33
#include "libpff_index_value.h"
34
#include "libpff_index_values_list.h"
35
#include "libpff_item_descriptor.h"
36
#include "libpff_item_tree.h"
37
#include "libpff_io_handle.h"
38
#include "libpff_libbfio.h"
39
#include "libpff_libcdata.h"
40
#include "libpff_libcerror.h"
41
#include "libpff_libcnotify.h"
42
#include "libpff_local_descriptors_node.h"
43
#include "libpff_offsets_index.h"
44
#include "libpff_recover.h"
45
46
#include "pff_block.h"
47
#include "pff_index_node.h"
48
49
/* Scans for recoverable items
50
 * By default only the unallocated space is checked for recoverable items
51
 * Returns 1 if successful or -1 on error
52
 */
53
int libpff_recover_items(
54
     libpff_io_handle_t *io_handle,
55
     libbfio_handle_t *file_io_handle,
56
     libpff_descriptors_index_t *descriptors_index,
57
     libpff_offsets_index_t *offsets_index,
58
     libcdata_range_list_t *unallocated_data_block_list,
59
     libcdata_range_list_t *unallocated_page_block_list,
60
     libcdata_list_t *recovered_item_list,
61
     uint8_t recovery_flags,
62
     libcerror_error_t **error )
63
0
{
64
0
  libcdata_tree_node_t *item_tree_node          = NULL;
65
0
  libpff_index_value_t *descriptors_index_value = NULL;
66
0
  libpff_index_values_list_t *index_values_list = NULL;
67
0
  libpff_item_descriptor_t *item_descriptor     = NULL;
68
0
  static char *function                         = "libpff_recover_items";
69
0
  int data_identifier_value_index               = 0;
70
0
  int index_value_iterator                      = 0;
71
0
  int index_values_list_iterator                = 0;
72
0
  int local_descriptors_identifier_value_index  = 0;
73
0
  int number_of_index_values                    = 0;
74
0
  int number_of_index_values_lists              = 0;
75
0
  int result                                    = 0;
76
77
#ifdef TODO
78
        uint32_t maximum_data_block_data_size         = 0;
79
#endif
80
81
0
  if( io_handle == NULL )
82
0
  {
83
0
    libcerror_error_set(
84
0
     error,
85
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
86
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
87
0
     "%s: invalid IO handle.",
88
0
     function );
89
90
0
    return( -1 );
91
0
  }
92
0
  if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT )
93
0
   && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT )
94
0
   && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
95
0
  {
96
0
    libcerror_error_set(
97
0
     error,
98
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
99
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
100
0
     "%s: unsupported file type.",
101
0
     function );
102
103
0
    return( -1 );
104
0
  }
105
0
  if( descriptors_index == NULL )
106
0
  {
107
0
    libcerror_error_set(
108
0
     error,
109
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
110
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
111
0
     "%s: invalid descriptors index.",
112
0
     function );
113
114
0
    return( -1 );
115
0
  }
116
0
  if( descriptors_index->index == NULL )
117
0
  {
118
0
    libcerror_error_set(
119
0
     error,
120
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
121
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
122
0
     "%s: invalid descriptors index - missing index.",
123
0
     function );
124
125
0
    return( -1 );
126
0
  }
127
0
  if( offsets_index == NULL )
128
0
  {
129
0
    libcerror_error_set(
130
0
     error,
131
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
132
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
133
0
     "%s: invalid offsets index.",
134
0
     function );
135
136
0
    return( -1 );
137
0
  }
138
0
  if( offsets_index->index == NULL )
139
0
  {
140
0
    libcerror_error_set(
141
0
     error,
142
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
143
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
144
0
     "%s: invalid offsets index - missing index.",
145
0
     function );
146
147
0
    return( -1 );
148
0
  }
149
0
  if( recovered_item_list == NULL )
150
0
  {
151
0
    libcerror_error_set(
152
0
     error,
153
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
154
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
155
0
     "%s: invalid recovered item list.",
156
0
     function );
157
158
0
    return( -1 );
159
0
  }
160
#ifdef TODO
161
  if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
162
  {
163
    maximum_data_block_data_size = 8192 - 12;
164
  }
165
  else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
166
  {
167
    maximum_data_block_data_size = 8192 - 16;
168
  }
169
  else
170
  {
171
/* TODO: this value is currently assumed based on the 512 x 8 = 4k page */
172
    maximum_data_block_data_size = 65536 - 24;
173
  }
174
#endif /* TODO */
175
#if defined( HAVE_DEBUG_OUTPUT )
176
  if( libbfio_handle_set_track_offsets_read(
177
       file_io_handle,
178
       0,
179
       error ) != 1 )
180
  {
181
                libcerror_error_set(
182
                 error,
183
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
184
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
185
                 "%s: unable to set track offsets read in file IO handle.",
186
                 function );
187
188
    goto on_error;
189
  }
190
#endif
191
#ifdef TODO
192
  /* Scan the offsets index nodes for deleted values
193
   */
194
  if( libpff_recover_analyze_offsets_index_node(
195
       offsets_index,
196
       io_handle,
197
       file_io_handle,
198
       offsets_index->index->root_node_offset,
199
       offsets_index->index->root_node_back_pointer,
200
       maximum_data_block_data_size,
201
       0,
202
       error ) != 1 )
203
  {
204
    libcerror_error_set(
205
     error,
206
     LIBCERROR_ERROR_DOMAIN_IO,
207
     LIBCERROR_IO_ERROR_READ_FAILED,
208
     "%s: unable to recover offsets index nodes.",
209
     function );
210
211
    return( -1 );
212
  }
213
#endif /* TODO */
214
215
0
  if( libpff_recover_data_blocks(
216
0
       io_handle,
217
0
       file_io_handle,
218
0
       descriptors_index,
219
0
       offsets_index,
220
0
       unallocated_data_block_list,
221
0
       unallocated_page_block_list,
222
0
       recovery_flags,
223
0
       error ) != 1 )
224
0
  {
225
0
    libcerror_error_set(
226
0
     error,
227
0
     LIBCERROR_ERROR_DOMAIN_IO,
228
0
     LIBCERROR_IO_ERROR_READ_FAILED,
229
0
     "%s: unable to recover data blocks.",
230
0
     function );
231
232
0
    goto on_error;
233
0
  }
234
  /* Scan the descriptors index nodes for deleted values
235
   */
236
0
  if( libpff_recover_descriptors_index_values(
237
0
       descriptors_index,
238
0
       io_handle,
239
0
       file_io_handle,
240
0
       descriptors_index->index->root_node_offset,
241
0
       descriptors_index->index->root_node_back_pointer,
242
0
       0,
243
0
       error ) != 1 )
244
0
  {
245
0
    libcerror_error_set(
246
0
     error,
247
0
     LIBCERROR_ERROR_DOMAIN_IO,
248
0
     LIBCERROR_IO_ERROR_READ_FAILED,
249
0
     "%s: unable to recover descriptors index values.",
250
0
     function );
251
252
0
    return( -1 );
253
0
  }
254
/* TODO combine the offsets index value check part with libpff_recover_descriptors_index_values so that the size of descriptors_index->recovered_index_values_tree remains small */
255
256
  /* For each recovered descriptors index value check if the corresonding local descriptor and data offsets index values exist
257
   */
258
0
  if( libcdata_btree_get_number_of_values(
259
0
       descriptors_index->recovered_index_values_tree,
260
0
       &number_of_index_values_lists,
261
0
       error ) != 1 )
262
0
  {
263
0
    libcerror_error_set(
264
0
     error,
265
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
266
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
267
0
     "%s: unable to retrieve number of recovered descriptors index values.",
268
0
     function );
269
270
0
    goto on_error;
271
0
  }
272
0
  for( index_values_list_iterator = 0;
273
0
       index_values_list_iterator < number_of_index_values_lists;
274
0
       index_values_list_iterator++ )
275
0
  {
276
0
    if( io_handle->abort != 0 )
277
0
    {
278
/* TODO break instead of error ? */
279
0
      goto on_error;
280
0
    }
281
0
    if( libcdata_btree_get_value_by_index(
282
0
         descriptors_index->recovered_index_values_tree,
283
0
         index_values_list_iterator,
284
0
         (intptr_t **) &index_values_list,
285
0
         error ) != 1 )
286
0
    {
287
0
      libcerror_error_set(
288
0
       error,
289
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
290
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
291
0
       "%s: unable to retrieve recovered descriptors index values list: %d.",
292
0
       function,
293
0
       index_values_list_iterator );
294
295
0
      goto on_error;
296
0
    }
297
0
    if( libpff_index_values_list_number_of_values(
298
0
         index_values_list,
299
0
         &number_of_index_values,
300
0
         error ) != 1 )
301
0
    {
302
0
      libcerror_error_set(
303
0
       error,
304
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
305
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
306
0
       "%s: unable to retrieve number of recovered descriptors index values list: %d elements.",
307
0
       function,
308
0
       index_values_list_iterator );
309
310
0
      goto on_error;
311
0
    }
312
0
    for( index_value_iterator = 0;
313
0
         index_value_iterator < number_of_index_values;
314
0
         index_value_iterator++ )
315
0
    {
316
0
      if( io_handle->abort != 0 )
317
0
      {
318
/* TODO break instead of error ? */
319
0
        goto on_error;
320
0
      }
321
0
      if( libpff_index_values_list_get_value_by_index(
322
0
           index_values_list,
323
0
           index_value_iterator,
324
0
           &descriptors_index_value,
325
0
           error ) != 1 )
326
0
      {
327
0
        libcerror_error_set(
328
0
         error,
329
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
330
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
331
0
         "%s: unable to retrieve recovered descriptors index value: %" PRIu64 " list element: %d.",
332
0
         function,
333
0
         index_values_list->identifier,
334
0
         index_value_iterator );
335
336
0
        goto on_error;
337
0
      }
338
0
      if( descriptors_index_value == NULL )
339
0
      {
340
0
        libcerror_error_set(
341
0
         error,
342
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
343
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
344
0
         "%s: missing recovered descriptors index value: %" PRIu64 " list element: %d.",
345
0
         function,
346
0
         index_values_list->identifier,
347
0
         index_value_iterator );
348
349
0
        goto on_error;
350
0
      }
351
#if defined( HAVE_DEBUG_OUTPUT )
352
      if( libcnotify_verbose != 0 )
353
      {
354
        libcnotify_printf(
355
         "%s: analyzing identifier: %" PRIu64 ", data: %" PRIu64 ", local descriptors: %" PRIu64 ", parent: %" PRIu32 "\n",
356
         function,
357
         descriptors_index_value->identifier,
358
         descriptors_index_value->data_identifier,
359
         descriptors_index_value->local_descriptors_identifier,
360
         descriptors_index_value->parent_identifier );
361
      }
362
#endif
363
0
      result = libpff_recover_analyze_descriptor_data_identifier(
364
0
          io_handle,
365
0
          file_io_handle,
366
0
          offsets_index,
367
0
          descriptors_index_value,
368
0
          &data_identifier_value_index,
369
0
          error );
370
371
0
      if( result == -1 )
372
0
      {
373
0
        libcerror_error_set(
374
0
         error,
375
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
376
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
377
0
         "%s: unable to recover descriptors index value: %" PRIu64 " data identifier: %" PRIu64 ".",
378
0
         function,
379
0
         descriptors_index_value->identifier,
380
0
         descriptors_index_value->data_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK );
381
382
0
        goto on_error;
383
0
      }
384
0
      else if( result == 0 )
385
0
      {
386
0
        continue;
387
0
      }
388
0
      result = libpff_recover_analyze_descriptor_local_descriptors_identifier(
389
0
          io_handle,
390
0
          file_io_handle,
391
0
          offsets_index,
392
0
          descriptors_index_value,
393
0
          &local_descriptors_identifier_value_index,
394
0
          error );
395
396
0
      if( result == -1 )
397
0
      {
398
0
        libcerror_error_set(
399
0
         error,
400
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
401
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
402
0
         "%s: unable to recover descriptors index value: %" PRIu64 " local descriptors identifier: %" PRIu64 ".",
403
0
         function,
404
0
         descriptors_index_value->identifier,
405
0
         descriptors_index_value->local_descriptors_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK );
406
407
0
        goto on_error;
408
0
      }
409
0
      else if( result == 0 )
410
0
      {
411
0
        continue;
412
0
      }
413
#if defined( HAVE_DEBUG_OUTPUT )
414
      if( libcnotify_verbose != 0 )
415
      {
416
        libcnotify_printf(
417
         "%s: item descriptor: %" PRIu64 " is recoverable.\n",
418
         function,
419
         descriptors_index_value->identifier );
420
      }
421
#endif
422
      /* Create a new item descriptor
423
       */
424
0
      if( libpff_item_descriptor_initialize(
425
0
           &item_descriptor,
426
0
           (uint32_t) descriptors_index_value->identifier,
427
0
           descriptors_index_value->data_identifier,
428
0
           descriptors_index_value->local_descriptors_identifier,
429
0
           1,
430
0
           error ) != 1 )
431
0
      {
432
0
        libcerror_error_set(
433
0
         error,
434
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
435
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
436
0
         "%s: unable to create item descriptor: %" PRIu64 ".",
437
0
         function,
438
0
         descriptors_index_value->identifier );
439
440
0
        goto on_error;
441
0
      }
442
0
      if( item_descriptor == NULL )
443
0
      {
444
0
        libcerror_error_set(
445
0
         error,
446
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
447
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
448
0
         "%s: missing item descriptor: %" PRIu64 ".",
449
0
         function,
450
0
         descriptors_index_value->identifier );
451
452
0
        goto on_error;
453
0
      }
454
/* TODO add to initialize function or create a separate function for setting these value in the item descriptor */
455
0
      item_descriptor->recovered_data_identifier_value_index              = data_identifier_value_index;
456
0
      item_descriptor->recovered_local_descriptors_identifier_value_index = local_descriptors_identifier_value_index;
457
458
      /* Create a new item tree node
459
       */
460
0
      if( libcdata_tree_node_initialize(
461
0
           &item_tree_node,
462
0
           error ) != 1 )
463
0
      {
464
0
        libcerror_error_set(
465
0
         error,
466
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
467
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
468
0
         "%s: unable to create item tree node.",
469
0
         function );
470
471
0
        goto on_error;
472
0
      }
473
0
      if( libcdata_tree_node_set_value(
474
0
           item_tree_node,
475
0
           (intptr_t *) item_descriptor,
476
0
           error ) != 1 )
477
0
      {
478
0
        libcerror_error_set(
479
0
         error,
480
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
481
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
482
0
         "%s: unable to set item descriptor in item tree node.",
483
0
         function );
484
485
0
        goto on_error;
486
0
      }
487
0
      item_descriptor = NULL;
488
489
0
      if( libcdata_list_append_value(
490
0
           recovered_item_list,
491
0
           (intptr_t *) item_tree_node,
492
0
           error ) != 1 )
493
0
      {
494
0
        libcerror_error_set(
495
0
         error,
496
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
497
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
498
0
         "%s: unable to append tree node to recovered item list.",
499
0
         function );
500
501
0
        goto on_error;
502
0
      }
503
0
      item_tree_node = NULL;
504
0
    }
505
0
  }
506
#if defined( HAVE_DEBUG_OUTPUT )
507
  if( libbfio_handle_set_track_offsets_read(
508
       file_io_handle,
509
       0,
510
       error ) != 1 )
511
  {
512
                libcerror_error_set(
513
                 error,
514
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
515
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
516
                 "%s: unable to set track offsets read in file IO handle.",
517
                 function );
518
519
                goto on_error;
520
  }
521
#endif
522
  /* TODO
523
   * link recovered descriptors to parent? and add to item hierarchy?
524
   * handle scanning without index data
525
   * what about 'encryption' ?
526
   */
527
0
  return( 1 );
528
529
0
on_error:
530
0
  if( item_tree_node != NULL )
531
0
  {
532
0
    libcdata_tree_node_free(
533
0
     &item_tree_node,
534
0
     (int (*)(intptr_t **, libcerror_error_t **)) &libpff_item_descriptor_free,
535
0
     NULL );
536
0
  }
537
0
  if( item_descriptor != NULL )
538
0
  {
539
0
    libpff_item_descriptor_free(
540
0
     &item_descriptor,
541
0
     NULL );
542
0
  }
543
0
  libcdata_list_empty(
544
0
   recovered_item_list,
545
0
   (int (*)(intptr_t **, libcerror_error_t **)) &libpff_item_tree_node_free_recovered,
546
0
   NULL );
547
548
0
  return( -1 );
549
0
}
550
551
/* Analyze if a specific descriptor data identifier is recoverable
552
 * Returns 1 if recoverable, 0 if not or -1 on error
553
 */
554
int libpff_recover_analyze_descriptor_data_identifier(
555
     libpff_io_handle_t *io_handle,
556
     libbfio_handle_t *file_io_handle,
557
     libpff_offsets_index_t *offsets_index,
558
     libpff_index_value_t *descriptors_index_value,
559
     int *data_identifier_value_index,
560
     libcerror_error_t **error )
561
0
{
562
0
  libcdata_tree_node_t *upper_node              = NULL;
563
0
  libpff_index_value_t *index_value             = NULL;
564
0
  libpff_index_value_t *lookup_index_value      = NULL;
565
0
  libpff_index_values_list_t *index_values_list = NULL;
566
0
  static char *function                         = "libpff_recover_analyze_descriptor_data_identifier";
567
0
  uint64_t lookup_identifier                    = 0;
568
0
  int index_value_iterator                      = 0;
569
0
  int number_of_index_values                    = 0;
570
0
  int result                                    = 0;
571
572
0
  if( offsets_index == NULL )
573
0
  {
574
0
    libcerror_error_set(
575
0
     error,
576
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
577
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
578
0
     "%s: invalid offsets index.",
579
0
     function );
580
581
0
    return( -1 );
582
0
  }
583
0
  if( descriptors_index_value == NULL )
584
0
  {
585
0
    libcerror_error_set(
586
0
     error,
587
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
588
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
589
0
     "%s: invalid descriptors index value.",
590
0
     function );
591
592
0
    return( -1 );
593
0
  }
594
0
  if( data_identifier_value_index == NULL )
595
0
  {
596
0
    libcerror_error_set(
597
0
     error,
598
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
599
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
600
0
     "%s: invalid data identifier value index.",
601
0
     function );
602
603
0
    return( -1 );
604
0
  }
605
0
  lookup_identifier = descriptors_index_value->data_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK;
606
607
0
  if( libpff_index_value_initialize(
608
0
       &lookup_index_value,
609
0
       error ) != 1 )
610
0
  {
611
0
    libcerror_error_set(
612
0
     error,
613
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
614
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
615
0
     "%s: unable to create lookup index value.",
616
0
     function );
617
618
0
    goto on_error;
619
0
  }
620
0
  lookup_index_value->identifier = lookup_identifier;
621
622
/* TODO have a compare function that directly uses the lookup_identifier not the lookup_index_value */
623
0
  result = libcdata_btree_get_value_by_value(
624
0
            offsets_index->recovered_index_values_tree,
625
0
            (intptr_t *) lookup_index_value,
626
0
            (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libpff_index_values_list_compare,
627
0
            &upper_node, 
628
0
            (intptr_t **) &index_values_list,
629
0
            error );
630
631
0
  if( result == -1 )
632
0
  {
633
0
    libcerror_error_set(
634
0
     error,
635
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
636
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
637
0
     "%s: unable to retrieve recovered offsets index value: %" PRIu64 " list.",
638
0
     function,
639
0
     lookup_identifier );
640
641
0
    goto on_error;
642
0
  }
643
0
  if( libpff_index_value_free(
644
0
       &lookup_index_value,
645
0
       error ) != 1 )
646
0
  {
647
0
    libcerror_error_set(
648
0
     error,
649
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
650
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
651
0
     "%s: unable to free lookup index value.",
652
0
     function,
653
0
     lookup_identifier );
654
655
0
    goto on_error;
656
0
  }
657
0
  if( result == 0 )
658
0
  {
659
0
    return( 0 );
660
0
  }
661
0
  if( libpff_index_values_list_number_of_values(
662
0
       index_values_list,
663
0
       &number_of_index_values,
664
0
       error ) != 1 )
665
0
  {
666
0
    libcerror_error_set(
667
0
     error,
668
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
669
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
670
0
     "%s: unable to retrieve number of recovered offsets index value: %" PRIu64 " list.",
671
0
     function,
672
0
     lookup_identifier );
673
674
0
    goto on_error;
675
0
  }
676
/* TODO handle if more than 1 offsets index value is recoverable */
677
678
0
  result = 0;
679
680
0
  for( index_value_iterator = 0;
681
0
       index_value_iterator < number_of_index_values;
682
0
       index_value_iterator++ )
683
0
  {
684
0
    if( libpff_index_values_list_get_value_by_index(
685
0
         index_values_list,
686
0
         index_value_iterator,
687
0
         &index_value,
688
0
         error ) != 1 )
689
0
    {
690
0
      libcerror_error_set(
691
0
       error,
692
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
693
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
694
0
       "%s: unable to retrieve recovered offsets index value: %d for data identifier: %" PRIu64 ".",
695
0
       function,
696
0
       index_value_iterator,
697
0
       lookup_identifier );
698
699
0
      goto on_error;
700
0
    }
701
    /* Check if a data block is recoverable
702
     */
703
0
    result = libpff_recover_analyze_data_block(
704
0
        io_handle,
705
0
        file_io_handle,
706
0
        (uint32_t) descriptors_index_value->identifier,
707
0
        index_value,
708
0
        error );
709
710
0
    if( result == -1 )
711
0
    {
712
0
      libcerror_error_set(
713
0
       error,
714
0
       LIBCERROR_ERROR_DOMAIN_IO,
715
0
       LIBCERROR_IO_ERROR_READ_FAILED,
716
0
       "%s: unable to recover data block: %" PRIu64 ".",
717
0
       function,
718
0
       descriptors_index_value->data_identifier );
719
720
#if defined( HAVE_DEBUG_OUTPUT )
721
      if( ( libcnotify_verbose != 0 )
722
       && ( error != NULL )
723
       && ( *error != NULL ) )
724
      {
725
        libcnotify_print_error_backtrace(
726
         *error );
727
      }
728
#endif
729
0
      libcerror_error_free(
730
0
       error );
731
732
/* TODO remove unreadable offset identifier from offsets_index->recovered_index_values_tree ? */
733
0
    }
734
0
    else if( result != 0 )
735
0
    {
736
0
      break;
737
0
    }
738
0
  }
739
0
  if( result != 0 )
740
0
  {
741
0
    *data_identifier_value_index = index_value_iterator;
742
0
  }
743
#if defined( HAVE_DEBUG_OUTPUT )
744
  else if( libcnotify_verbose != 0 )
745
  {
746
    libcnotify_printf(
747
     "%s: recovered offsets index value for data identifier: %" PRIu64 " not available.\n",
748
     function,
749
     lookup_identifier );
750
  }
751
#endif
752
0
  return( result );
753
754
0
on_error:
755
0
  if( lookup_index_value != NULL )
756
0
  {
757
0
    libpff_index_value_free(
758
0
     &lookup_index_value,
759
0
     NULL );
760
0
  }
761
0
  return( -1 );
762
0
}
763
764
/* Analyze if a specific descriptor local descriptors identifier is recoverable
765
 * Returns 1 if recoverable, 0 if not or -1 on error
766
 */
767
int libpff_recover_analyze_descriptor_local_descriptors_identifier(
768
     libpff_io_handle_t *io_handle,
769
     libbfio_handle_t *file_io_handle,
770
     libpff_offsets_index_t *offsets_index,
771
     libpff_index_value_t *descriptors_index_value,
772
     int *local_descriptors_identifier_value_index,
773
     libcerror_error_t **error )
774
0
{
775
0
  libcdata_tree_node_t *upper_node              = NULL;
776
0
  libpff_index_value_t *index_value             = NULL;
777
0
  libpff_index_value_t *lookup_index_value      = NULL;
778
0
  libpff_index_values_list_t *index_values_list = NULL;
779
0
  static char *function                         = "libpff_recover_analyze_descriptor_local_descriptors_identifier";
780
0
  uint64_t lookup_identifier                    = 0;
781
0
  int index_value_iterator                      = 0;
782
0
  int number_of_index_values                    = 0;
783
0
  int result                                    = 0;
784
785
0
  if( offsets_index == NULL )
786
0
  {
787
0
    libcerror_error_set(
788
0
     error,
789
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
790
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
791
0
     "%s: invalid offsets index.",
792
0
     function );
793
794
0
    return( -1 );
795
0
  }
796
0
  if( descriptors_index_value == NULL )
797
0
  {
798
0
    libcerror_error_set(
799
0
     error,
800
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
801
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
802
0
     "%s: invalid descriptors index value.",
803
0
     function );
804
805
0
    return( -1 );
806
0
  }
807
0
  if( local_descriptors_identifier_value_index == NULL )
808
0
  {
809
0
    libcerror_error_set(
810
0
     error,
811
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
812
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
813
0
     "%s: invalid local descriptors identifier value index.",
814
0
     function );
815
816
0
    return( -1 );
817
0
  }
818
  /* The local descriptors identifier is 0 if not set
819
   */
820
0
  if( descriptors_index_value->local_descriptors_identifier == 0 )
821
0
  {
822
0
    return( 1 );
823
0
  }
824
0
  lookup_identifier = descriptors_index_value->local_descriptors_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK;
825
826
0
  if( libpff_index_value_initialize(
827
0
       &lookup_index_value,
828
0
       error ) != 1 )
829
0
  {
830
0
    libcerror_error_set(
831
0
     error,
832
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
833
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
834
0
     "%s: unable to create lookup index value.",
835
0
     function );
836
837
0
    goto on_error;
838
0
  }
839
0
  lookup_index_value->identifier = lookup_identifier;
840
841
/* TODO have a compare function that directly uses the lookup_identifier not the lookup_index_value */
842
0
  result = libcdata_btree_get_value_by_value(
843
0
            offsets_index->recovered_index_values_tree,
844
0
            (intptr_t *) lookup_index_value,
845
0
            (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libpff_index_values_list_compare,
846
0
            &upper_node, 
847
0
            (intptr_t **) &index_values_list,
848
0
            error );
849
850
0
  if( result == -1 )
851
0
  {
852
0
    libcerror_error_set(
853
0
     error,
854
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
855
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
856
0
     "%s: unable to retrieve recovered offsets index value: %" PRIu64 " list.",
857
0
     function,
858
0
     lookup_identifier );
859
860
0
    goto on_error;
861
0
  }
862
0
  if( libpff_index_value_free(
863
0
       &lookup_index_value,
864
0
       error ) != 1 )
865
0
  {
866
0
    libcerror_error_set(
867
0
     error,
868
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
869
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
870
0
     "%s: unable to free lookup index value.",
871
0
     function,
872
0
     lookup_identifier );
873
874
0
    goto on_error;
875
0
  }
876
0
  if( result == 0 )
877
0
  {
878
0
    return( 0 );
879
0
  }
880
0
  if( libpff_index_values_list_number_of_values(
881
0
       index_values_list,
882
0
       &number_of_index_values,
883
0
       error ) != 1 )
884
0
  {
885
0
    libcerror_error_set(
886
0
     error,
887
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
888
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
889
0
     "%s: unable to retrieve number of recovered offsets index value: %" PRIu64 " list.",
890
0
     function,
891
0
     lookup_identifier );
892
893
0
    goto on_error;
894
0
  }
895
/* TODO handle if more than 1 offsets index value is recoverable */
896
897
0
  result = 0;
898
899
0
  for( index_value_iterator = 0;
900
0
       index_value_iterator < number_of_index_values;
901
0
       index_value_iterator++ )
902
0
  {
903
0
    if( libpff_index_values_list_get_value_by_index(
904
0
         index_values_list,
905
0
         index_value_iterator,
906
0
         &index_value,
907
0
         error ) != 1 )
908
0
    {
909
0
      libcerror_error_set(
910
0
       error,
911
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
912
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
913
0
       "%s: unable to retrieve recovered offsets index value: %d for data identifier: %" PRIu64 ".",
914
0
       function,
915
0
       index_value_iterator,
916
0
       lookup_identifier );
917
918
0
      goto on_error;
919
0
    }
920
    /* Check if local descriptors are recoverable
921
     */
922
0
    result = libpff_recover_analyze_local_descriptors(
923
0
              io_handle,
924
0
              file_io_handle,
925
0
              offsets_index,
926
0
              descriptors_index_value->local_descriptors_identifier,
927
0
              error );
928
929
0
    if( result == -1 )
930
0
    {
931
0
      libcerror_error_set(
932
0
       error,
933
0
       LIBCERROR_ERROR_DOMAIN_IO,
934
0
       LIBCERROR_IO_ERROR_READ_FAILED,
935
0
       "%s: unable to recover local descriptors: %" PRIu64 ".",
936
0
       function,
937
0
       descriptors_index_value->local_descriptors_identifier );
938
939
0
      goto on_error;
940
0
    }
941
0
    else if( result != 0 )
942
0
    {
943
0
      break;
944
0
    }
945
0
  }
946
0
  if( result != 0 )
947
0
  {
948
0
    *local_descriptors_identifier_value_index = index_value_iterator;
949
0
  }
950
#if defined( HAVE_DEBUG_OUTPUT )
951
  else if( libcnotify_verbose != 0 )
952
  {
953
    libcnotify_printf(
954
     "%s: recovered offsets index value for local descriptors identifier: %" PRIu64 " not available.\n",
955
     function,
956
     lookup_identifier );
957
  }
958
#endif
959
0
  return( result );
960
961
0
on_error:
962
0
  if( lookup_index_value != NULL )
963
0
  {
964
0
    libpff_index_value_free(
965
0
     &lookup_index_value,
966
0
     NULL );
967
0
  }
968
0
  return( -1 );
969
0
}
970
971
/* Analyze if a specific data block back pointer is recoverable
972
 * Returns 1 if recoverable, 0 if not or -1 on error
973
 */
974
int libpff_recover_analyze_data_block_back_pointer(
975
     libpff_offsets_index_t *offsets_index,
976
     uint64_t data_block_back_pointer,
977
     off64_t data_block_data_offset,
978
     size32_t data_block_data_size,
979
     libcerror_error_t **error )
980
0
{
981
0
  libcdata_tree_node_t *upper_node              = NULL;
982
0
  libpff_index_value_t *index_value             = NULL;
983
0
  libpff_index_value_t *lookup_index_value      = NULL;
984
0
  libpff_index_values_list_t *index_values_list = NULL;
985
0
  static char *function                         = "libpff_recover_analyze_data_block_back_pointer";
986
0
  uint64_t lookup_identifier                    = 0;
987
0
  int index_value_iterator                      = 0;
988
0
  int number_of_index_values                    = 0;
989
0
  int result                                    = 0;
990
991
0
  if( offsets_index == NULL )
992
0
  {
993
0
    libcerror_error_set(
994
0
     error,
995
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
996
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
997
0
     "%s: invalid offsets index.",
998
0
     function );
999
1000
0
    return( -1 );
1001
0
  }
1002
0
  lookup_identifier = data_block_back_pointer;
1003
1004
0
  if( libpff_index_value_initialize(
1005
0
       &lookup_index_value,
1006
0
       error ) != 1 )
1007
0
  {
1008
0
    libcerror_error_set(
1009
0
     error,
1010
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1011
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1012
0
     "%s: unable to create lookup index value.",
1013
0
     function );
1014
1015
0
    goto on_error;
1016
0
  }
1017
0
  lookup_index_value->identifier = lookup_identifier;
1018
1019
/* TODO have a compare function that directly uses the lookup_identifier not the lookup_index_value */
1020
0
  result = libcdata_btree_get_value_by_value(
1021
0
            offsets_index->recovered_index_values_tree,
1022
0
            (intptr_t *) lookup_index_value,
1023
0
            (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libpff_index_values_list_compare,
1024
0
            &upper_node, 
1025
0
            (intptr_t **) &index_values_list,
1026
0
            error );
1027
1028
0
  if( result == -1 )
1029
0
  {
1030
0
    libcerror_error_set(
1031
0
     error,
1032
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1033
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1034
0
     "%s: unable to retrieve recovered offsets index value: %" PRIu64 " list.",
1035
0
     function,
1036
0
     lookup_identifier );
1037
1038
0
    goto on_error;
1039
0
  }
1040
0
  if( libpff_index_value_free(
1041
0
       &lookup_index_value,
1042
0
       error ) != 1 )
1043
0
  {
1044
0
    libcerror_error_set(
1045
0
     error,
1046
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1047
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1048
0
     "%s: unable to free lookup index value.",
1049
0
     function,
1050
0
     lookup_identifier );
1051
1052
0
    goto on_error;
1053
0
  }
1054
0
  if( result == 0 )
1055
0
  {
1056
0
    return( 0 );
1057
0
  }
1058
0
  if( libpff_index_values_list_number_of_values(
1059
0
       index_values_list,
1060
0
       &number_of_index_values,
1061
0
       error ) != 1 )
1062
0
  {
1063
0
    libcerror_error_set(
1064
0
     error,
1065
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1066
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1067
0
     "%s: unable to retrieve number of recovered offsets index value: %" PRIu64 " list.",
1068
0
     function,
1069
0
     lookup_identifier );
1070
1071
0
    goto on_error;
1072
0
  }
1073
/* TODO handle if more than 1 offsets index value is recoverable */
1074
1075
0
  result = 0;
1076
1077
0
  for( index_value_iterator = 0;
1078
0
       index_value_iterator < number_of_index_values;
1079
0
       index_value_iterator++ )
1080
0
  {
1081
0
    if( libpff_index_values_list_get_value_by_index(
1082
0
         index_values_list,
1083
0
         index_value_iterator,
1084
0
         &index_value,
1085
0
         error ) != 1 )
1086
0
    {
1087
0
      libcerror_error_set(
1088
0
       error,
1089
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1090
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1091
0
       "%s: unable to retrieve recovered offsets index value: %d for data identifier: %" PRIu64 ".",
1092
0
       function,
1093
0
       index_value_iterator,
1094
0
       lookup_identifier );
1095
1096
0
      goto on_error;
1097
0
    }
1098
0
    if( ( data_block_data_offset == index_value->file_offset )
1099
0
     && ( data_block_data_size == index_value->data_size ) )
1100
0
    {
1101
0
      result = 1;
1102
0
    }
1103
0
    if( result != 0 )
1104
0
    {
1105
0
      break;
1106
0
    }
1107
0
  }
1108
0
  if( result != 0 )
1109
0
  {
1110
#if defined( HAVE_DEBUG_OUTPUT )
1111
    if( libcnotify_verbose != 0 )
1112
    {
1113
      libcnotify_printf(
1114
       "%s: recovered data block with identifier: %" PRIu64 " matches existing recovered item value.\n",
1115
       function,
1116
       lookup_identifier );
1117
    }
1118
#endif
1119
0
  }
1120
0
  return( result );
1121
1122
0
on_error:
1123
0
  if( lookup_index_value != NULL )
1124
0
  {
1125
0
    libpff_index_value_free(
1126
0
     &lookup_index_value,
1127
0
     NULL );
1128
0
  }
1129
0
  return( -1 );
1130
0
}
1131
1132
/* Analyze if a specific descriptors index value is recoverable
1133
 * Returns 1 if recoverable, 0 if not or -1 on error
1134
 */
1135
int libpff_recover_analyze_descriptors_index_value(
1136
     libpff_descriptors_index_t *descriptors_index,
1137
     libpff_io_handle_t *io_handle,
1138
     libbfio_handle_t *file_io_handle,
1139
     libpff_index_value_t *descriptors_index_value,
1140
     libcerror_error_t **error )
1141
0
{
1142
0
  libpff_index_value_t *existing_index_value = NULL;
1143
0
  static char *function                      = "libpff_recover_analyze_descriptors_index_value";
1144
0
  int result                                 = 0;
1145
1146
0
  if( descriptors_index == NULL )
1147
0
  {
1148
0
    libcerror_error_set(
1149
0
     error,
1150
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1151
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1152
0
     "%s: invalid descriptors index.",
1153
0
     function );
1154
1155
0
    return( -1 );
1156
0
  }
1157
0
  if( descriptors_index_value == NULL )
1158
0
  {
1159
0
    libcerror_error_set(
1160
0
     error,
1161
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1162
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1163
0
     "%s: invalid descriptors index value.",
1164
0
     function );
1165
1166
0
    return( -1 );
1167
0
  }
1168
#if defined( HAVE_DEBUG_OUTPUT )
1169
  if( libcnotify_verbose != 0 )
1170
  {
1171
    libcnotify_printf(
1172
     "%s: analyzing identifier: %" PRIu64 ", data: %" PRIu64 ", local descriptors: %" PRIu64 ", parent: %" PRIu32 "\n",
1173
     function,
1174
     descriptors_index_value->identifier,
1175
     descriptors_index_value->data_identifier,
1176
     descriptors_index_value->local_descriptors_identifier,
1177
     descriptors_index_value->parent_identifier );
1178
  }
1179
#endif
1180
  /* Check if the descriptors index value matches an existing index value
1181
   */
1182
0
  result = libpff_index_get_value_by_identifier(
1183
0
      descriptors_index->index,
1184
0
      io_handle,
1185
0
      file_io_handle,
1186
0
      descriptors_index_value->identifier,
1187
0
      &existing_index_value,
1188
0
      error );
1189
1190
0
  if( result == -1 )
1191
0
  {
1192
0
    libcerror_error_set(
1193
0
     error,
1194
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1195
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1196
0
     "%s: unable to retrieve descriptors index value: %" PRIu64 " from index.",
1197
0
     function,
1198
0
     descriptors_index_value->identifier );
1199
1200
0
    goto on_error;
1201
0
  }
1202
0
  else if( result != 0 )
1203
0
  {
1204
0
    if( existing_index_value == NULL )
1205
0
    {
1206
0
      libcerror_error_set(
1207
0
       error,
1208
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1209
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1210
0
       "%s: missing descriptors index value for identifier: %" PRIu64 ".",
1211
0
       function,
1212
0
       descriptors_index_value->identifier );
1213
1214
0
      goto on_error;
1215
0
    }
1216
0
    result = 0;
1217
1218
/* TODO what about parent changes ? */
1219
0
    if( ( descriptors_index_value->data_identifier == existing_index_value->data_identifier )
1220
0
     && ( descriptors_index_value->local_descriptors_identifier == existing_index_value->local_descriptors_identifier ) )
1221
0
    {
1222
#if defined( HAVE_DEBUG_OUTPUT )
1223
      if( libcnotify_verbose != 0 )
1224
      {
1225
        libcnotify_printf(
1226
         "%s: deleted descriptors index value: %" PRIu64 " matches existing item value.\n",
1227
         function,
1228
         descriptors_index_value->identifier );
1229
      }
1230
#endif
1231
0
      result = 1;
1232
0
    }
1233
0
    if( libpff_index_value_free(
1234
0
         &existing_index_value,
1235
0
         error ) != 1 )
1236
0
    {
1237
0
      libcerror_error_set(
1238
0
       error,
1239
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1240
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1241
0
       "%s: unable to free index value: %d.",
1242
0
       function,
1243
0
       descriptors_index_value->identifier );
1244
1245
0
      goto on_error;
1246
0
    }
1247
0
    if( result != 0 )
1248
0
    {
1249
0
      return( 0 );
1250
0
    }
1251
0
  }
1252
0
  result = libpff_recover_check_descriptors_index_for_recovered_value(
1253
0
      descriptors_index,
1254
0
      descriptors_index_value,
1255
0
      error );
1256
1257
0
  if( result == -1 )
1258
0
  {
1259
0
    libcerror_error_set(
1260
0
     error,
1261
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1262
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1263
0
     "%s: unable to determine if deleted descriptors index value: %" PRIu64 " was previously recovered.",
1264
0
     function,
1265
0
     descriptors_index_value->identifier );
1266
1267
0
    goto on_error;
1268
0
  }
1269
0
  else if( result != 0 )
1270
0
  {
1271
#if defined( HAVE_DEBUG_OUTPUT )
1272
    if( libcnotify_verbose != 0 )
1273
    {
1274
      libcnotify_printf(
1275
       "%s: deleted descriptors index value: %" PRIu64 " matches previous recovered index value.\n",
1276
       function,
1277
       descriptors_index_value->identifier );
1278
    }
1279
#endif
1280
0
    return( 0 );
1281
0
  }
1282
0
  return( 1 );
1283
1284
0
on_error:
1285
0
  if( existing_index_value != NULL )
1286
0
  {
1287
0
    libpff_index_value_free(
1288
0
     &existing_index_value,
1289
0
     NULL );
1290
0
  }
1291
0
  return( -1 );
1292
0
}
1293
1294
/* Checks if the specific descriptors index contains a specific recovered index value
1295
 * Returns 1 if exists, 0 if not or -1 on error
1296
 */
1297
int libpff_recover_check_descriptors_index_for_recovered_value(
1298
     libpff_descriptors_index_t *descriptors_index,
1299
     libpff_index_value_t *descriptors_index_value,
1300
     libcerror_error_t **error )
1301
0
{
1302
0
  libcdata_tree_node_t *upper_node              = NULL;
1303
0
  libpff_index_value_t *index_value             = NULL;
1304
0
  libpff_index_values_list_t *index_values_list = NULL;
1305
0
  static char *function                         = "libpff_recover_check_descriptors_index_for_recovered_value";
1306
0
  int index_value_iterator                      = 0;
1307
0
  int number_of_index_values                    = 0;
1308
0
  int result                                    = 0;
1309
1310
0
  if( descriptors_index == NULL )
1311
0
  {
1312
0
    libcerror_error_set(
1313
0
     error,
1314
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1315
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1316
0
     "%s: invalid descriptors index.",
1317
0
     function );
1318
1319
0
    return( -1 );
1320
0
  }
1321
0
  if( descriptors_index_value == NULL )
1322
0
  {
1323
0
    libcerror_error_set(
1324
0
     error,
1325
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1326
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1327
0
     "%s: invalid descriptors index value.",
1328
0
     function );
1329
1330
0
    return( -1 );
1331
0
  }
1332
0
  result = libcdata_btree_get_value_by_value(
1333
0
      descriptors_index->recovered_index_values_tree,
1334
0
      (intptr_t *) descriptors_index_value,
1335
0
      (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libpff_index_values_list_compare,
1336
0
      &upper_node,
1337
0
      (intptr_t **) &index_values_list,
1338
0
      error );
1339
1340
0
  if( result == -1 )
1341
0
  {
1342
0
    libcerror_error_set(
1343
0
     error,
1344
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1345
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1346
0
     "%s: unable to retrieve recovered descriptors index value: %" PRIu64 " list.",
1347
0
     function,
1348
0
     descriptors_index_value->identifier );
1349
1350
0
    return( -1 );
1351
0
  }
1352
0
  else if( result != 0 )
1353
0
  {
1354
0
    if( libpff_index_values_list_number_of_values(
1355
0
         index_values_list,
1356
0
         &number_of_index_values,
1357
0
         error ) != 1 )
1358
0
    {
1359
0
      libcerror_error_set(
1360
0
       error,
1361
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1362
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1363
0
       "%s: unable to retrieve number of recovered descriptors index values for identifier: %" PRIu64 ".",
1364
0
       function,
1365
0
       descriptors_index_value->identifier );
1366
1367
0
      return( -1 );
1368
0
    }
1369
0
    result = 0;
1370
1371
0
    for( index_value_iterator = 0;
1372
0
         index_value_iterator < number_of_index_values;
1373
0
         index_value_iterator++ )
1374
0
    {
1375
0
      if( libpff_index_values_list_get_value_by_index(
1376
0
           index_values_list,
1377
0
           index_value_iterator,
1378
0
           &index_value,
1379
0
           error ) != 1 )
1380
0
      {
1381
0
        libcerror_error_set(
1382
0
         error,
1383
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1384
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1385
0
         "%s: unable to retrieve recovered descriptors index value: %" PRIu64 " list element: %d.",
1386
0
         function,
1387
0
         descriptors_index_value->identifier,
1388
0
         index_value_iterator );
1389
1390
0
        return( -1 );
1391
0
      }
1392
0
      if( index_value == NULL )
1393
0
      {
1394
0
        libcerror_error_set(
1395
0
         error,
1396
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1397
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1398
0
         "%s: missing recovered descriptors index value: %" PRIu64 " list element: %d.",
1399
0
         function,
1400
0
         descriptors_index_value->identifier,
1401
0
         index_value_iterator );
1402
1403
0
        return( -1 );
1404
0
      }
1405
/* TODO what about parent changes ? */
1406
0
      if( ( descriptors_index_value->data_identifier == index_value->data_identifier )
1407
0
       && ( descriptors_index_value->local_descriptors_identifier == index_value->local_descriptors_identifier ) )
1408
0
      {
1409
0
        result = 1;
1410
1411
0
        break;
1412
0
      }
1413
0
    }
1414
0
  }
1415
0
  return( result );
1416
0
}
1417
1418
/* Recovers descriptors index values
1419
 * Returns 1 if successful or -1 on error
1420
 */
1421
int libpff_recover_descriptors_index_values(
1422
     libpff_descriptors_index_t *descriptors_index,
1423
     libpff_io_handle_t *io_handle,
1424
     libbfio_handle_t *file_io_handle,
1425
     off64_t node_offset,
1426
     uint64_t node_back_pointer,
1427
     int recursion_depth,
1428
     libcerror_error_t **error )
1429
0
{
1430
0
  libpff_index_node_t *index_node   = NULL;
1431
0
  libpff_index_value_t *index_value = NULL;
1432
0
  uint8_t *node_entry_data          = NULL;
1433
0
  static char *function             = "libpff_recover_descriptors_index_values";
1434
0
  size64_t node_data_size           = 0;
1435
0
  off64_t node_data_offset          = 0;
1436
0
  uint64_t sub_node_back_pointer    = 0;
1437
0
  uint64_t sub_node_offset          = 0;
1438
0
  uint16_t entry_index              = 0;
1439
0
  int result                        = 0;
1440
1441
0
  if( descriptors_index == NULL )
1442
0
  {
1443
0
    libcerror_error_set(
1444
0
     error,
1445
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1446
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1447
0
     "%s: invalid descriptors index.",
1448
0
     function );
1449
1450
0
    return( -1 );
1451
0
  }
1452
0
  if( descriptors_index->index == NULL )
1453
0
  {
1454
0
    libcerror_error_set(
1455
0
     error,
1456
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1457
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1458
0
     "%s: invalid descriptors index - missing index.",
1459
0
     function );
1460
1461
0
    return( -1 );
1462
0
  }
1463
0
  if( io_handle == NULL )
1464
0
  {
1465
0
    libcerror_error_set(
1466
0
     error,
1467
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1468
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1469
0
     "%s: invalid IO handle.",
1470
0
     function );
1471
1472
0
    return( -1 );
1473
0
  }
1474
0
  if( ( recursion_depth < 0 )
1475
0
   || ( recursion_depth > LIBPFF_MAXIMUM_ITEM_TREE_RECURSION_DEPTH ) )
1476
0
  {
1477
0
    libcerror_error_set(
1478
0
     error,
1479
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1480
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1481
0
     "%s: invalid recursion depth value out of bounds.",
1482
0
     function );
1483
1484
0
    return( -1 );
1485
0
  }
1486
0
  if( libpff_index_node_initialize(
1487
0
       &index_node,
1488
0
       error ) != 1 )
1489
0
  {
1490
0
    libcerror_error_set(
1491
0
     error,
1492
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1493
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1494
0
     "%s: unable to create descriptors index node.",
1495
0
     function );
1496
1497
0
    goto on_error;
1498
0
  }
1499
0
  if( libpff_index_node_read_file_io_handle(
1500
0
       index_node,
1501
0
       file_io_handle,
1502
0
       node_offset,
1503
0
       io_handle->file_type,
1504
0
       error ) != 1 )
1505
0
  {
1506
0
    libcerror_error_set(
1507
0
     error,
1508
0
     LIBCERROR_ERROR_DOMAIN_IO,
1509
0
     LIBCERROR_IO_ERROR_READ_FAILED,
1510
0
     "%s: unable to read descriptors index node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1511
0
     function,
1512
0
     node_offset,
1513
0
     node_offset );
1514
1515
0
    goto on_error;
1516
0
  }
1517
0
  if( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF )
1518
0
  {
1519
0
    for( entry_index = index_node->number_of_entries;
1520
0
         entry_index < index_node->maximum_number_of_entries;
1521
0
         entry_index++ )
1522
0
    {
1523
/* TODO add if( io_handle->abort != 0 ) */
1524
0
      if( libpff_index_node_get_entry_data(
1525
0
           index_node,
1526
0
           entry_index,
1527
0
           &node_entry_data,
1528
0
           error ) != 1 )
1529
0
      {
1530
0
        libcerror_error_set(
1531
0
         error,
1532
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1533
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1534
0
         "%s: unable to retrieve deleted node entry: %" PRIu16 " data.",
1535
0
         function,
1536
0
         entry_index );
1537
1538
0
        goto on_error;
1539
0
      }
1540
0
      if( node_entry_data == NULL )
1541
0
      {
1542
0
        libcerror_error_set(
1543
0
         error,
1544
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1545
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1546
0
         "%s: missing deleted node entry: %" PRIu16 " data.",
1547
0
         function,
1548
0
         entry_index );
1549
1550
0
        goto on_error;
1551
0
      }
1552
0
      if( libpff_index_value_initialize(
1553
0
           &index_value,
1554
0
           error ) != 1 )
1555
0
      {
1556
0
        libcerror_error_set(
1557
0
         error,
1558
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1559
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1560
0
         "%s: unable to create index value.",
1561
0
         function );
1562
1563
0
        goto on_error;
1564
0
      }
1565
0
      if( libpff_index_value_read_data(
1566
0
           index_value,
1567
0
           io_handle,
1568
0
           LIBPFF_INDEX_TYPE_DESCRIPTOR,
1569
0
           node_entry_data,
1570
0
           (size_t) index_node->entry_size,
1571
0
           error ) != 1 )
1572
0
      {
1573
0
        libcerror_error_set(
1574
0
         error,
1575
0
         LIBCERROR_ERROR_DOMAIN_IO,
1576
0
         LIBCERROR_IO_ERROR_READ_FAILED,
1577
0
         "%s: unable to read index value.",
1578
0
         function );
1579
1580
0
        goto on_error;
1581
0
      }
1582
0
      result = libpff_recover_analyze_descriptors_index_value(
1583
0
                descriptors_index,
1584
0
                io_handle,
1585
0
                file_io_handle,
1586
0
                index_value,
1587
0
                error );
1588
1589
0
      if( result == -1 )
1590
0
      {
1591
0
        libcerror_error_set(
1592
0
         error,
1593
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1594
0
         LIBCERROR_RUNTIME_ERROR_GENERIC,
1595
0
         "%s: unable to analyze deleted descriptors index value: %" PRIu16 ".",
1596
0
         function,
1597
0
         entry_index );
1598
1599
0
        goto on_error;
1600
0
      }
1601
0
      else if( result != 0 )
1602
0
      {
1603
        /* Add the recovered descriptors index values to the index tree
1604
         */
1605
#if defined( HAVE_DEBUG_OUTPUT )
1606
        if( libcnotify_verbose != 0 )
1607
        {
1608
          libcnotify_printf(
1609
           "%s: decriptor index value: %" PRIu16 " identifier: %" PRIu64 " is recoverable.\n",
1610
           function,
1611
           entry_index,
1612
           index_value->identifier );
1613
        }
1614
#endif
1615
0
        node_data_offset = node_offset + ( entry_index * index_node->entry_size );
1616
0
        node_data_size   = index_node->entry_size;
1617
1618
0
        if( libpff_descriptors_index_insert_recovered_index_value(
1619
0
             descriptors_index,
1620
0
             index_value,
1621
0
             error ) != 1 )
1622
0
        {
1623
0
          libcerror_error_set(
1624
0
           error,
1625
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1626
0
           LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1627
0
           "%s: unable to insert recovered descriptors index value: %" PRIu64 " list.",
1628
0
           function,
1629
0
           index_value->identifier );
1630
1631
0
          goto on_error;
1632
0
        }
1633
0
        index_value = NULL;
1634
0
      }
1635
0
      else
1636
0
      {
1637
0
        if( libpff_index_value_free(
1638
0
             &index_value,
1639
0
             error ) != 1 )
1640
0
        {
1641
0
          libcerror_error_set(
1642
0
           error,
1643
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1644
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1645
0
           "%s: unable to free index value.",
1646
0
           function );
1647
1648
0
          goto on_error;
1649
0
        }
1650
0
      }
1651
0
    }
1652
0
  }
1653
0
  else
1654
0
  {
1655
0
    if( node_back_pointer != index_node->back_pointer )
1656
0
    {
1657
0
      libcerror_error_set(
1658
0
       error,
1659
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1660
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1661
0
       "%s: back pointer mismatch (entry: %" PRIu64 ", node: %" PRIu64 ").",
1662
0
       function,
1663
0
       node_back_pointer,
1664
0
       index_node->back_pointer );
1665
1666
0
      goto on_error;
1667
0
    }
1668
0
    for( entry_index = 0;
1669
0
         entry_index < index_node->number_of_entries;
1670
0
         entry_index++ )
1671
0
    {
1672
/* TODO add if( io_handle->abort != 0 ) */
1673
0
      if( libpff_index_node_get_entry_data(
1674
0
           index_node,
1675
0
           entry_index,
1676
0
           &node_entry_data,
1677
0
           error ) != 1 )
1678
0
      {
1679
0
        libcerror_error_set(
1680
0
         error,
1681
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1682
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1683
0
         "%s: unable to retrieve node entry: %" PRIu16 " data.",
1684
0
         function,
1685
0
         entry_index );
1686
1687
0
        goto on_error;
1688
0
      }
1689
0
      if( node_entry_data == NULL )
1690
0
      {
1691
0
        libcerror_error_set(
1692
0
         error,
1693
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1694
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1695
0
         "%s: missing node entry: %" PRIu16 " data.",
1696
0
         function,
1697
0
         entry_index );
1698
1699
0
        goto on_error;
1700
0
      }
1701
0
      if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
1702
0
      {
1703
0
        byte_stream_copy_to_uint32_little_endian(
1704
0
         ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->file_offset,
1705
0
         sub_node_offset );
1706
1707
0
        byte_stream_copy_to_uint32_little_endian(
1708
0
         ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->back_pointer,
1709
0
         sub_node_back_pointer );
1710
0
      }
1711
0
      else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
1712
0
            || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
1713
0
      {
1714
0
        byte_stream_copy_to_uint64_little_endian(
1715
0
         ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->file_offset,
1716
0
         sub_node_offset );
1717
1718
0
        byte_stream_copy_to_uint64_little_endian(
1719
0
         ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->back_pointer,
1720
0
         sub_node_back_pointer );
1721
0
      }
1722
#if defined( HAVE_DEBUG_OUTPUT )
1723
      if( libcnotify_verbose != 0 )
1724
      {
1725
        libcnotify_printf(
1726
         "%s: node entry: %" PRIu16 " sub node offset\t: %" PRIi64 " (0x%08" PRIx64 ")\n",
1727
         function,
1728
         entry_index,
1729
         sub_node_offset,
1730
         sub_node_offset );
1731
      }
1732
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1733
1734
0
      if( libpff_recover_descriptors_index_values(
1735
0
           descriptors_index,
1736
0
           io_handle,
1737
0
           file_io_handle,
1738
0
           sub_node_offset,
1739
0
           sub_node_back_pointer,
1740
0
           recursion_depth + 1,
1741
0
           error ) != 1 )
1742
0
      {
1743
0
        libcerror_error_set(
1744
0
         error,
1745
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1746
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1747
0
         "%s: unable to analyze descriptors index node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1748
0
         function,
1749
0
         sub_node_offset,
1750
0
         sub_node_offset );
1751
1752
0
        goto on_error;
1753
0
      }
1754
0
    }
1755
0
  }
1756
0
  if( libpff_index_node_free(
1757
0
       &index_node,
1758
0
       error ) != 1 )
1759
0
  {
1760
0
    libcerror_error_set(
1761
0
     error,
1762
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1763
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1764
0
     "%s: unable to free index node.",
1765
0
     function );
1766
1767
0
    goto on_error;
1768
0
  }
1769
0
  return( 1 );
1770
1771
0
on_error:
1772
0
  if( index_value != NULL )
1773
0
  {
1774
0
    libpff_index_value_free(
1775
0
     &index_value,
1776
0
     NULL );
1777
0
  }
1778
0
  if( index_node != NULL )
1779
0
  {
1780
0
    libpff_index_node_free(
1781
0
     &index_node,
1782
0
     NULL );
1783
0
  }
1784
0
  return( -1 );
1785
0
}
1786
1787
/* Analyze if a specific offsets index value is recoverable
1788
 * Returns 1 if recoverable, 0 if not or -1 on error
1789
 */
1790
int libpff_recover_analyze_offsets_index_value(
1791
     libpff_offsets_index_t *offsets_index,
1792
     libpff_io_handle_t *io_handle,
1793
     libbfio_handle_t *file_io_handle,
1794
     libpff_index_value_t *offsets_index_value,
1795
     uint32_t maximum_data_block_data_size,
1796
     libcerror_error_t **error )
1797
0
{
1798
0
  libpff_index_value_t *existing_index_value = NULL;
1799
0
  static char *function                      = "libpff_recover_analyze_offsets_index_value";
1800
0
  int result                                 = 0;
1801
1802
0
  if( offsets_index == NULL )
1803
0
  {
1804
0
    libcerror_error_set(
1805
0
     error,
1806
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1807
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1808
0
     "%s: invalid offsets index.",
1809
0
     function );
1810
1811
0
    return( -1 );
1812
0
  }
1813
0
  if( offsets_index_value == NULL )
1814
0
  {
1815
0
    libcerror_error_set(
1816
0
     error,
1817
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1818
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1819
0
     "%s: invalid offsets index value.",
1820
0
     function );
1821
1822
0
    return( -1 );
1823
0
  }
1824
#if defined( HAVE_DEBUG_OUTPUT )
1825
  if( libcnotify_verbose != 0 )
1826
  {
1827
    libcnotify_printf(
1828
     "%s: analyzing identifier: %" PRIu64 " (%s) at offset: %" PRIi64 " of size: %" PRIu32 "\n",
1829
     function,
1830
     offsets_index_value->identifier,
1831
     ( ( offsets_index_value->identifier & LIBPFF_OFFSET_INDEX_IDENTIFIER_FLAG_INTERNAL ) ? "internal" : "external" ),
1832
     offsets_index_value->file_offset,
1833
     offsets_index_value->data_size );
1834
  }
1835
#endif
1836
  /* Ignore index values without a valid file offset
1837
   */
1838
0
  if( offsets_index_value->file_offset <= 0 )
1839
0
  {
1840
#if defined( HAVE_DEBUG_OUTPUT )
1841
    if( libcnotify_verbose != 0 )
1842
    {
1843
      libcnotify_printf(
1844
       "%s: deleted offsets index value: %" PRIu64 " has an invalid file offset: %" PRIi64 ".\n",
1845
       function,
1846
       offsets_index_value->identifier,
1847
       offsets_index_value->file_offset );
1848
    }
1849
#endif
1850
0
    return( 0 );
1851
0
  }
1852
  /* Ignore index values without a valid data size
1853
   */
1854
0
  if( ( offsets_index_value->data_size == 0 )
1855
0
   || ( (uint32_t) offsets_index_value->data_size > maximum_data_block_data_size ) )
1856
0
  {
1857
#if defined( HAVE_DEBUG_OUTPUT )
1858
    if( libcnotify_verbose != 0 )
1859
    {
1860
      libcnotify_printf(
1861
       "%s: deleted offsets index value: %" PRIu64 " has an invalid data size: %" PRIu32 ".\n",
1862
       function,
1863
       offsets_index_value->identifier,
1864
       offsets_index_value->data_size );
1865
    }
1866
#endif
1867
0
    return( 0 );
1868
0
  }
1869
  /* Check if the offsets index value matches an existing index value
1870
   */
1871
0
  result = libpff_index_get_value_by_identifier(
1872
0
      offsets_index->index,
1873
0
      io_handle,
1874
0
      file_io_handle,
1875
0
      offsets_index_value->identifier,
1876
0
      &existing_index_value,
1877
0
      error );
1878
1879
0
  if( result == -1 )
1880
0
  {
1881
0
    libcerror_error_set(
1882
0
     error,
1883
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1884
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1885
0
     "%s: unable to retrieve offsets index value for identifier: %" PRIu64 ".",
1886
0
     function,
1887
0
     offsets_index_value->identifier );
1888
1889
0
    goto on_error;
1890
0
  }
1891
0
  else if( result != 0 )
1892
0
  {
1893
0
    if( existing_index_value == NULL )
1894
0
    {
1895
0
      libcerror_error_set(
1896
0
       error,
1897
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1898
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1899
0
       "%s: missing offsets index value for identifier: %" PRIu64 ".",
1900
0
       function,
1901
0
       offsets_index_value->identifier );
1902
1903
0
      goto on_error;
1904
0
    }
1905
0
    result = 0;
1906
1907
0
    if( ( offsets_index_value->file_offset == existing_index_value->file_offset )
1908
0
     && ( offsets_index_value->data_size == existing_index_value->data_size ) )
1909
0
    {
1910
#if defined( HAVE_DEBUG_OUTPUT )
1911
      if( libcnotify_verbose != 0 )
1912
      {
1913
        libcnotify_printf(
1914
         "%s: deleted offsets index value: %" PRIu64 " matches existing item value.\n",
1915
         function,
1916
         offsets_index_value->identifier );
1917
      }
1918
#endif
1919
0
      result = 1;
1920
0
    }
1921
0
    if( libpff_index_value_free(
1922
0
         &existing_index_value,
1923
0
         error ) != 1 )
1924
0
    {
1925
0
      libcerror_error_set(
1926
0
       error,
1927
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1928
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1929
0
       "%s: unable to free index value: %d.",
1930
0
       function,
1931
0
       offsets_index_value->identifier );
1932
1933
0
      goto on_error;
1934
0
    }
1935
0
    if( result != 0 )
1936
0
    {
1937
0
      return( 0 );
1938
0
    }
1939
0
  }
1940
  /* Check if the offsets index value matches a previously recovered index value
1941
   */
1942
0
  result = libpff_recover_check_offsets_index_for_recovered_value(
1943
0
      offsets_index,
1944
0
      offsets_index_value,
1945
0
      error );
1946
1947
0
  if( result == -1 )
1948
0
  {
1949
0
    libcerror_error_set(
1950
0
     error,
1951
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1952
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1953
0
     "%s: unable to determine if deleted offsets index value: %" PRIu64 " was previously recovered.",
1954
0
     function,
1955
0
     offsets_index_value->identifier );
1956
1957
0
    goto on_error;
1958
0
  }
1959
0
  else if( result != 0 )
1960
0
  {
1961
#if defined( HAVE_DEBUG_OUTPUT )
1962
    if( libcnotify_verbose != 0 )
1963
    {
1964
      libcnotify_printf(
1965
       "%s: deleted offsets index value: %" PRIu64 " matches previous recovered index value.\n",
1966
       function,
1967
       offsets_index_value->identifier );
1968
    }
1969
#endif
1970
0
    return( 0 );
1971
0
  }
1972
0
  return( 1 );
1973
1974
0
on_error:
1975
0
  if( existing_index_value != NULL )
1976
0
  {
1977
0
    libpff_index_value_free(
1978
0
     &existing_index_value,
1979
0
     NULL );
1980
0
  }
1981
0
  return( -1 );
1982
0
}
1983
1984
/* Checks if the specific offsets index contains a specific recovered index value
1985
 * Returns 1 if exists, 0 if not or -1 on error
1986
 */
1987
int libpff_recover_check_offsets_index_for_recovered_value(
1988
     libpff_offsets_index_t *offsets_index,
1989
     libpff_index_value_t *offsets_index_value,
1990
     libcerror_error_t **error )
1991
0
{
1992
0
  libcdata_tree_node_t *upper_node              = NULL;
1993
0
  libpff_index_value_t *index_value             = NULL;
1994
0
  libpff_index_values_list_t *index_values_list = NULL;
1995
0
  static char *function                         = "libpff_recover_check_offsets_index_for_recovered_value";
1996
0
  int index_value_iterator                      = 0;
1997
0
  int number_of_index_values                    = 0;
1998
0
  int result                                    = 0;
1999
2000
0
  if( offsets_index == NULL )
2001
0
  {
2002
0
    libcerror_error_set(
2003
0
     error,
2004
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2005
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2006
0
     "%s: invalid offsets index.",
2007
0
     function );
2008
2009
0
    return( -1 );
2010
0
  }
2011
0
  if( offsets_index_value == NULL )
2012
0
  {
2013
0
    libcerror_error_set(
2014
0
     error,
2015
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2016
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2017
0
     "%s: invalid offsets index value.",
2018
0
     function );
2019
2020
0
    return( -1 );
2021
0
  }
2022
0
  result = libcdata_btree_get_value_by_value(
2023
0
      offsets_index->recovered_index_values_tree,
2024
0
      (intptr_t *) offsets_index_value,
2025
0
      (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libpff_index_values_list_compare,
2026
0
      &upper_node,
2027
0
      (intptr_t **) &index_values_list,
2028
0
      error );
2029
2030
0
  if( result == -1 )
2031
0
  {
2032
0
    libcerror_error_set(
2033
0
     error,
2034
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2035
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2036
0
     "%s: unable to retrieve recovered offsets index value: %" PRIu64 " list.",
2037
0
     function,
2038
0
     offsets_index_value->identifier );
2039
2040
0
    return( -1 );
2041
0
  }
2042
0
  else if( result != 0 )
2043
0
  {
2044
0
    if( libpff_index_values_list_number_of_values(
2045
0
         index_values_list,
2046
0
         &number_of_index_values,
2047
0
         error ) != 1 )
2048
0
    {
2049
0
      libcerror_error_set(
2050
0
       error,
2051
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2052
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2053
0
       "%s: unable to retrieve number of recovered offsets index values for identifier: %" PRIu64 ".",
2054
0
       function,
2055
0
       offsets_index_value->identifier );
2056
2057
0
      return( -1 );
2058
0
    }
2059
0
    result = 0;
2060
2061
0
    for( index_value_iterator = 0;
2062
0
         index_value_iterator < number_of_index_values;
2063
0
         index_value_iterator++ )
2064
0
    {
2065
0
      if( libpff_index_values_list_get_value_by_index(
2066
0
           index_values_list,
2067
0
           index_value_iterator,
2068
0
           &index_value,
2069
0
           error ) != 1 )
2070
0
      {
2071
0
        libcerror_error_set(
2072
0
         error,
2073
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2074
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2075
0
         "%s: unable to retrieve recovered offsets index value: %" PRIu64 " list element: %d.",
2076
0
         function,
2077
0
         offsets_index_value->identifier,
2078
0
         index_value_iterator );
2079
2080
0
        return( -1 );
2081
0
      }
2082
0
      if( index_value == NULL )
2083
0
      {
2084
0
        libcerror_error_set(
2085
0
         error,
2086
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2087
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2088
0
         "%s: missing recovered offsets index value: %" PRIu64 " list element: %d.",
2089
0
         function,
2090
0
         offsets_index_value->identifier,
2091
0
         index_value_iterator );
2092
2093
0
        return( -1 );
2094
0
      }
2095
0
      if( ( offsets_index_value->file_offset == index_value->file_offset )
2096
0
       && ( offsets_index_value->data_size == index_value->data_size ) )
2097
0
      {
2098
0
        result = 1;
2099
2100
0
        break;
2101
0
      }
2102
0
    }
2103
0
  }
2104
0
  return( result );
2105
0
}
2106
2107
/* Scans an offsets index node for recoverable index nodes
2108
 * Returns 1 if successful or -1 on error
2109
 */
2110
int libpff_recover_analyze_offsets_index_node(
2111
     libpff_offsets_index_t *offsets_index,
2112
     libpff_io_handle_t *io_handle,
2113
     libbfio_handle_t *file_io_handle,
2114
     off64_t node_offset,
2115
     uint64_t node_back_pointer,
2116
     uint32_t maximum_data_block_data_size,
2117
     int recursion_depth,
2118
     libcerror_error_t **error )
2119
0
{
2120
0
  libpff_index_node_t *index_node   = NULL;
2121
0
  libpff_index_value_t *index_value = NULL;
2122
0
  uint8_t *node_entry_data          = NULL;
2123
0
  static char *function             = "libpff_recover_analyze_offsets_index_node";
2124
0
  size64_t node_data_size           = 0;
2125
0
  off64_t node_data_offset          = 0;
2126
0
  uint64_t sub_node_back_pointer    = 0;
2127
0
  uint64_t sub_node_offset          = 0;
2128
0
  uint16_t entry_index              = 0;
2129
0
  int result                        = 0;
2130
2131
0
  if( offsets_index == NULL )
2132
0
  {
2133
0
    libcerror_error_set(
2134
0
     error,
2135
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2136
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2137
0
     "%s: invalid offsets index.",
2138
0
     function );
2139
2140
0
    return( -1 );
2141
0
  }
2142
0
  if( offsets_index->index == NULL )
2143
0
  {
2144
0
    libcerror_error_set(
2145
0
     error,
2146
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2147
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2148
0
     "%s: invalid offsets index - missing index.",
2149
0
     function );
2150
2151
0
    return( -1 );
2152
0
  }
2153
0
  if( io_handle == NULL )
2154
0
  {
2155
0
    libcerror_error_set(
2156
0
     error,
2157
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2158
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2159
0
     "%s: invalid IO handle.",
2160
0
     function );
2161
2162
0
    return( -1 );
2163
0
  }
2164
0
  if( ( recursion_depth < 0 )
2165
0
   || ( recursion_depth > LIBPFF_MAXIMUM_ITEM_TREE_RECURSION_DEPTH ) )
2166
0
  {
2167
0
    libcerror_error_set(
2168
0
     error,
2169
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2170
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
2171
0
     "%s: invalid recursion depth value out of bounds.",
2172
0
     function );
2173
2174
0
    return( -1 );
2175
0
  }
2176
0
  if( libpff_index_node_initialize(
2177
0
       &index_node,
2178
0
       error ) != 1 )
2179
0
  {
2180
0
    libcerror_error_set(
2181
0
     error,
2182
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2183
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2184
0
     "%s: unable to create offsets index node.",
2185
0
     function );
2186
2187
0
    goto on_error;
2188
0
  }
2189
0
  if( libpff_index_node_read_file_io_handle(
2190
0
       index_node,
2191
0
       file_io_handle,
2192
0
       node_offset,
2193
0
       io_handle->file_type,
2194
0
       error ) != 1 )
2195
0
  {
2196
0
    libcerror_error_set(
2197
0
     error,
2198
0
     LIBCERROR_ERROR_DOMAIN_IO,
2199
0
     LIBCERROR_IO_ERROR_READ_FAILED,
2200
0
     "%s: unable to read offsets index node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
2201
0
     function,
2202
0
     node_offset,
2203
0
     node_offset );
2204
2205
0
    goto on_error;
2206
0
  }
2207
0
  if( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF )
2208
0
  {
2209
0
    for( entry_index = index_node->number_of_entries;
2210
0
         entry_index < index_node->maximum_number_of_entries;
2211
0
         entry_index++ )
2212
0
    {
2213
/* TODO add if( io_handle->abort != 0 ) */
2214
0
      if( libpff_index_node_get_entry_data(
2215
0
           index_node,
2216
0
           entry_index,
2217
0
           &node_entry_data,
2218
0
           error ) != 1 )
2219
0
      {
2220
0
        libcerror_error_set(
2221
0
         error,
2222
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2223
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2224
0
         "%s: unable to retrieve deleted node entry: %" PRIu16 " data.",
2225
0
         function,
2226
0
         entry_index );
2227
2228
0
        goto on_error;
2229
0
      }
2230
0
      if( node_entry_data == NULL )
2231
0
      {
2232
0
        libcerror_error_set(
2233
0
         error,
2234
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2235
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2236
0
         "%s: missing deleted node entry: %" PRIu16 " data.",
2237
0
         function,
2238
0
         entry_index );
2239
2240
0
        goto on_error;
2241
0
      }
2242
0
      if( libpff_index_value_initialize(
2243
0
           &index_value,
2244
0
           error ) != 1 )
2245
0
      {
2246
0
        libcerror_error_set(
2247
0
         error,
2248
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2249
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2250
0
         "%s: unable to create index value.",
2251
0
         function );
2252
2253
0
        goto on_error;
2254
0
      }
2255
0
      if( libpff_index_value_read_data(
2256
0
           index_value,
2257
0
           io_handle,
2258
0
           LIBPFF_INDEX_TYPE_OFFSET,
2259
0
           node_entry_data,
2260
0
           (size_t) index_node->entry_size,
2261
0
           error ) != 1 )
2262
0
      {
2263
0
        libcerror_error_set(
2264
0
         error,
2265
0
         LIBCERROR_ERROR_DOMAIN_IO,
2266
0
         LIBCERROR_IO_ERROR_READ_FAILED,
2267
0
         "%s: unable to read index value.",
2268
0
         function );
2269
2270
0
        goto on_error;
2271
0
      }
2272
0
      result = libpff_recover_analyze_offsets_index_value(
2273
0
                offsets_index,
2274
0
                io_handle,
2275
0
                file_io_handle,
2276
0
                index_value,
2277
0
                maximum_data_block_data_size,
2278
0
                error );
2279
2280
0
      if( result == -1 )
2281
0
      {
2282
0
        libcerror_error_set(
2283
0
         error,
2284
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2285
0
         LIBCERROR_RUNTIME_ERROR_GENERIC,
2286
0
         "%s: unable to analyze deleted offsets index value: %" PRIu16 ".",
2287
0
         function,
2288
0
         entry_index );
2289
2290
0
        goto on_error;
2291
0
      }
2292
0
      else if( result != 0 )
2293
0
      {
2294
        /* Add the recovered offsets index values to the index tree
2295
         */
2296
#if defined( HAVE_DEBUG_OUTPUT )
2297
        if( libcnotify_verbose != 0 )
2298
        {
2299
          libcnotify_printf(
2300
           "%s: offsets index value: %" PRIu16 " identifier: %" PRIu64 " is recoverable.\n",
2301
           function,
2302
           entry_index,
2303
           index_value->identifier );
2304
        }
2305
#endif
2306
0
        node_data_offset = node_offset + ( entry_index * index_node->entry_size );
2307
0
        node_data_size   = index_node->entry_size;
2308
2309
0
        if( libpff_offsets_index_insert_recovered_index_value(
2310
0
             offsets_index,
2311
0
             index_value,
2312
0
             error ) != 1 )
2313
0
        {
2314
0
          libcerror_error_set(
2315
0
           error,
2316
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2317
0
           LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2318
0
           "%s: unable to insert recovered offsets index value: %" PRIu64 " list.",
2319
0
           function,
2320
0
           index_value->identifier );
2321
2322
0
          goto on_error;
2323
0
        }
2324
0
        index_value = NULL;
2325
0
      }
2326
0
      else
2327
0
      {
2328
0
        if( libpff_index_value_free(
2329
0
             &index_value,
2330
0
             error ) != 1 )
2331
0
        {
2332
0
          libcerror_error_set(
2333
0
           error,
2334
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2335
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2336
0
           "%s: unable to free index value.",
2337
0
           function );
2338
2339
0
          goto on_error;
2340
0
        }
2341
0
      }
2342
0
    }
2343
0
  }
2344
0
  else
2345
0
  {
2346
0
    if( node_back_pointer != index_node->back_pointer )
2347
0
    {
2348
0
      libcerror_error_set(
2349
0
       error,
2350
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2351
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2352
0
       "%s: back pointer mismatch (entry: %" PRIu64 ", node: %" PRIu64 ").",
2353
0
       function,
2354
0
       node_back_pointer,
2355
0
       index_node->back_pointer );
2356
2357
0
      goto on_error;
2358
0
    }
2359
0
    for( entry_index = 0;
2360
0
         entry_index < index_node->number_of_entries;
2361
0
         entry_index++ )
2362
0
    {
2363
/* TODO add if( io_handle->abort != 0 ) */
2364
0
      if( libpff_index_node_get_entry_data(
2365
0
           index_node,
2366
0
           entry_index,
2367
0
           &node_entry_data,
2368
0
           error ) != 1 )
2369
0
      {
2370
0
        libcerror_error_set(
2371
0
         error,
2372
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2373
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2374
0
         "%s: unable to retrieve node entry: %" PRIu16 " data.",
2375
0
         function,
2376
0
         entry_index );
2377
2378
0
        goto on_error;
2379
0
      }
2380
0
      if( node_entry_data == NULL )
2381
0
      {
2382
0
        libcerror_error_set(
2383
0
         error,
2384
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2385
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2386
0
         "%s: missing node entry: %" PRIu16 " data.",
2387
0
         function,
2388
0
         entry_index );
2389
2390
0
        goto on_error;
2391
0
      }
2392
0
      if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
2393
0
      {
2394
0
        byte_stream_copy_to_uint32_little_endian(
2395
0
         ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->file_offset,
2396
0
         sub_node_offset );
2397
2398
0
        byte_stream_copy_to_uint32_little_endian(
2399
0
         ( (pff_index_node_branch_entry_32bit_t *) node_entry_data )->back_pointer,
2400
0
         sub_node_back_pointer );
2401
0
      }
2402
0
      else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
2403
0
            || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
2404
0
      {
2405
0
        byte_stream_copy_to_uint64_little_endian(
2406
0
         ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->file_offset,
2407
0
         sub_node_offset );
2408
2409
0
        byte_stream_copy_to_uint64_little_endian(
2410
0
         ( (pff_index_node_branch_entry_64bit_t *) node_entry_data )->back_pointer,
2411
0
         sub_node_back_pointer );
2412
0
      }
2413
#if defined( HAVE_DEBUG_OUTPUT )
2414
      if( libcnotify_verbose != 0 )
2415
      {
2416
        libcnotify_printf(
2417
         "%s: node entry: %" PRIu16 " sub node offset\t: %" PRIi64 " (0x%08" PRIx64 ")\n",
2418
         function,
2419
         entry_index,
2420
         sub_node_offset,
2421
         sub_node_offset );
2422
      }
2423
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
2424
2425
0
      if( libpff_recover_analyze_offsets_index_node(
2426
0
           offsets_index,
2427
0
           io_handle,
2428
0
           file_io_handle,
2429
0
           sub_node_offset,
2430
0
           sub_node_back_pointer,
2431
0
           maximum_data_block_data_size,
2432
0
           recursion_depth + 1,
2433
0
           error ) != 1 )
2434
0
      {
2435
0
        libcerror_error_set(
2436
0
         error,
2437
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2438
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2439
0
         "%s: unable to analyze offsets index node at offset: %" PRIi64 " (0x%08" PRIx64 ").",
2440
0
         function,
2441
0
         sub_node_offset,
2442
0
         sub_node_offset );
2443
2444
0
        goto on_error;
2445
0
      }
2446
0
    }
2447
0
  }
2448
0
  if( libpff_index_node_free(
2449
0
       &index_node,
2450
0
       error ) != 1 )
2451
0
  {
2452
0
    libcerror_error_set(
2453
0
     error,
2454
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2455
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2456
0
     "%s: unable to free index node.",
2457
0
     function );
2458
2459
0
    goto on_error;
2460
0
  }
2461
0
  return( 1 );
2462
2463
0
on_error:
2464
0
  if( index_value != NULL )
2465
0
  {
2466
0
    libpff_index_value_free(
2467
0
     &index_value,
2468
0
     NULL );
2469
0
  }
2470
0
  if( index_node != NULL )
2471
0
  {
2472
0
    libpff_index_node_free(
2473
0
     &index_node,
2474
0
     NULL );
2475
0
  }
2476
0
  return( -1 );
2477
0
}
2478
2479
/* Scans for recoverable data blocks
2480
 * Returns 1 if successful or -1 on error
2481
 */
2482
int libpff_recover_data_blocks(
2483
     libpff_io_handle_t *io_handle,
2484
     libbfio_handle_t *file_io_handle,
2485
     libpff_descriptors_index_t *descriptors_index,
2486
     libpff_offsets_index_t *offsets_index,
2487
     libcdata_range_list_t *unallocated_data_block_list,
2488
     libcdata_range_list_t *unallocated_page_block_list,
2489
     uint8_t recovery_flags,
2490
     libcerror_error_t **error )
2491
0
{
2492
0
  uint8_t *block_buffer                   = NULL;
2493
0
  uint8_t *data_block_footer              = NULL;
2494
0
  intptr_t *value                         = NULL;
2495
0
  static char *function                   = "libpff_recover_data_blocks";
2496
0
  off64_t block_buffer_data_offset        = 0;
2497
0
  off64_t block_offset                    = 0;
2498
0
  off64_t data_block_offset               = 0;
2499
0
  off64_t page_block_offset               = 0;
2500
0
  size64_t block_size                     = 0;
2501
0
  size64_t data_block_size                = 0;
2502
0
  size64_t page_block_size                = 0;
2503
0
  size_t block_buffer_offset              = 0;
2504
0
  size_t block_buffer_size_available      = 0;
2505
0
  size_t data_block_data_offset           = 0;
2506
0
  size_t read_size                        = 0;
2507
0
  ssize_t read_count                      = 0;
2508
0
  uint64_t data_block_back_pointer        = 0;
2509
0
  uint32_t data_block_calculated_checksum = 0;
2510
0
  uint32_t data_block_stored_checksum     = 0;
2511
0
  uint32_t maximum_data_block_size        = 0;
2512
0
  uint16_t data_block_data_size           = 0;
2513
0
  uint16_t format_data_block_size         = 0;
2514
0
  uint16_t format_page_block_size         = 0;
2515
0
  uint16_t scan_block_size                = 0;
2516
0
  uint8_t supported_recovery_flags        = 0;
2517
0
  int number_of_unallocated_data_blocks   = 0;
2518
0
  int number_of_unallocated_page_blocks   = 0;
2519
0
  int result                              = 0;
2520
0
  int unallocated_data_block_index        = 0;
2521
0
  int unallocated_page_block_index        = 0;
2522
2523
0
  if( io_handle == NULL )
2524
0
  {
2525
0
    libcerror_error_set(
2526
0
     error,
2527
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2528
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2529
0
     "%s: invalid IO handle.",
2530
0
     function );
2531
2532
0
    return( -1 );
2533
0
  }
2534
0
  if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT )
2535
0
   && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT )
2536
0
   && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
2537
0
  {
2538
0
    libcerror_error_set(
2539
0
     error,
2540
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2541
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2542
0
     "%s: unsupported file type.",
2543
0
     function );
2544
2545
0
    return( -1 );
2546
0
  }
2547
0
  if( ( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
2548
0
   || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) )
2549
0
  {
2550
0
    format_data_block_size  = 64;
2551
0
    format_page_block_size  = 512;
2552
0
  }
2553
0
  else
2554
0
  {
2555
0
    format_data_block_size  = 512;
2556
0
    format_page_block_size  = 4096;
2557
0
  }
2558
0
  if( ( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
2559
0
   || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) )
2560
0
  {
2561
0
    maximum_data_block_size = 8192;
2562
0
  }
2563
0
  else
2564
0
  {
2565
/* TODO: this value is currently assumed based on the 512 x 8 = 4k page */
2566
0
    maximum_data_block_size = 65536;
2567
0
  }
2568
0
  supported_recovery_flags = LIBPFF_RECOVERY_FLAG_IGNORE_ALLOCATION_DATA
2569
0
                           | LIBPFF_RECOVERY_FLAG_SCAN_FOR_FRAGMENTS;
2570
2571
0
  if( ( recovery_flags & ~( supported_recovery_flags ) ) != 0 )
2572
0
  {
2573
0
    libcerror_error_set(
2574
0
     error,
2575
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2576
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2577
0
     "%s: unsupported recovery flags.",
2578
0
     function );
2579
2580
0
    return( -1 );
2581
0
  }
2582
  /* Scan the unallocated page block list or all blocks for index nodes
2583
   */
2584
0
  if( ( recovery_flags & LIBPFF_RECOVERY_FLAG_IGNORE_ALLOCATION_DATA ) == 0 )
2585
0
  {
2586
0
    if( libcdata_range_list_get_number_of_elements(
2587
0
         unallocated_data_block_list,
2588
0
         &number_of_unallocated_data_blocks,
2589
0
         error ) != 1 )
2590
0
    {
2591
0
      libcerror_error_set(
2592
0
       error,
2593
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2594
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2595
0
       "%s: unable to retrieve number of unallocated data blocks.",
2596
0
       function );
2597
2598
0
      goto on_error;
2599
0
    }
2600
0
    if( ( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
2601
0
     || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) )
2602
0
    {
2603
0
      if( libcdata_range_list_get_number_of_elements(
2604
0
           unallocated_page_block_list,
2605
0
           &number_of_unallocated_page_blocks,
2606
0
           error ) != 1 )
2607
0
      {
2608
0
        libcerror_error_set(
2609
0
         error,
2610
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2611
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2612
0
         "%s: unable to retrieve number of unallocated page blocks.",
2613
0
         function );
2614
2615
0
        goto on_error;
2616
0
      }
2617
0
    }
2618
0
    else
2619
0
    {
2620
0
      number_of_unallocated_page_blocks = 0;
2621
0
    }
2622
0
  }
2623
0
  if( ( recovery_flags & LIBPFF_RECOVERY_FLAG_SCAN_FOR_FRAGMENTS ) == 0 )
2624
0
  {
2625
0
    scan_block_size = format_page_block_size;
2626
0
  }
2627
0
  else
2628
0
  {
2629
0
    scan_block_size = format_data_block_size;
2630
0
  }
2631
0
  block_buffer = (uint8_t *) memory_allocate(
2632
0
                              sizeof( uint8_t ) * ( maximum_data_block_size * 2 ) );
2633
2634
0
  if( block_buffer == NULL )
2635
0
  {
2636
0
    libcerror_error_set(
2637
0
     error,
2638
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
2639
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
2640
0
     "%s: unable to create block buffer.",
2641
0
     function );
2642
2643
0
    goto on_error;
2644
0
  }
2645
0
  if( ( number_of_unallocated_data_blocks > 0 )
2646
0
   || ( number_of_unallocated_page_blocks > 0 )
2647
0
   || ( ( recovery_flags & LIBPFF_RECOVERY_FLAG_IGNORE_ALLOCATION_DATA ) != 0 ) )
2648
0
  {
2649
0
    block_offset      = 0;
2650
0
    data_block_offset = -1;
2651
0
    page_block_offset = -1;
2652
2653
0
    while( block_offset < (off64_t) io_handle->file_size )
2654
0
    {
2655
0
      if( io_handle->abort != 0 )
2656
0
      {
2657
0
        goto on_error;
2658
0
      }
2659
0
      if( ( recovery_flags & LIBPFF_RECOVERY_FLAG_IGNORE_ALLOCATION_DATA ) == 0 )
2660
0
      {
2661
0
        if( data_block_offset < block_offset )
2662
0
        {
2663
0
          if( unallocated_data_block_index < number_of_unallocated_data_blocks )
2664
0
          {
2665
0
            if( libcdata_range_list_get_range_by_index(
2666
0
                 unallocated_data_block_list,
2667
0
                 unallocated_data_block_index,
2668
0
                 (uint64_t *) &data_block_offset,
2669
0
                 (uint64_t *) &data_block_size,
2670
0
                 &value,
2671
0
                 error ) != 1 )
2672
0
            {
2673
0
              libcerror_error_set(
2674
0
               error,
2675
0
               LIBCERROR_ERROR_DOMAIN_RUNTIME,
2676
0
               LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2677
0
               "%s: unable to retrieve unallocated data block: %d.",
2678
0
               function,
2679
0
               unallocated_data_block_index );
2680
2681
0
              goto on_error;
2682
0
            }
2683
0
            unallocated_data_block_index++;
2684
0
          }
2685
0
          else
2686
0
          {
2687
0
            data_block_offset = (off64_t) io_handle->file_size;
2688
0
            data_block_size   = 0;
2689
0
          }
2690
0
        }
2691
0
        if( page_block_offset < block_offset )
2692
0
        {
2693
0
          if( unallocated_page_block_index < number_of_unallocated_page_blocks )
2694
0
          {
2695
0
            if( libcdata_range_list_get_range_by_index(
2696
0
                 unallocated_page_block_list,
2697
0
                 unallocated_page_block_index,
2698
0
                 (uint64_t *) &page_block_offset,
2699
0
                 (uint64_t *) &page_block_size,
2700
0
                 &value,
2701
0
                 error ) != 1 )
2702
0
            {
2703
0
              libcerror_error_set(
2704
0
               error,
2705
0
               LIBCERROR_ERROR_DOMAIN_RUNTIME,
2706
0
               LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2707
0
               "%s: unable to retrieve unallocated page block: %d.",
2708
0
               function,
2709
0
               unallocated_page_block_index );
2710
2711
0
              goto on_error;
2712
0
            }
2713
0
            unallocated_page_block_index++;
2714
0
          }
2715
0
          else
2716
0
          {
2717
0
            page_block_offset = (off64_t) io_handle->file_size;
2718
0
            page_block_size   = 0;
2719
0
          }
2720
0
        }
2721
0
      }
2722
0
      if( ( recovery_flags & LIBPFF_RECOVERY_FLAG_IGNORE_ALLOCATION_DATA ) == 0 )
2723
0
      {
2724
0
        if( ( data_block_offset >= (off64_t) io_handle->file_size )
2725
0
         && ( page_block_offset >= (off64_t) io_handle->file_size ) )
2726
0
        {
2727
0
          break;
2728
0
        }
2729
        /* Process the smallest offset
2730
         */
2731
0
        else if( ( data_block_offset < page_block_offset )
2732
0
              && ( data_block_size > scan_block_size ) )
2733
0
        {
2734
0
          block_offset = data_block_offset;
2735
0
          block_size   = data_block_size;
2736
0
        }
2737
0
        else if( ( page_block_offset < data_block_offset )
2738
0
              && ( page_block_size > scan_block_size ) )
2739
0
        {
2740
0
          block_offset = page_block_offset;
2741
0
          block_size   = page_block_size;
2742
0
        }
2743
        /* Process the largest range
2744
         */
2745
0
        else if( data_block_size > page_block_size )
2746
0
        {
2747
0
          block_offset = data_block_offset;
2748
0
          block_size   = data_block_size;
2749
0
        }
2750
0
        else
2751
0
        {
2752
0
          block_offset = page_block_offset;
2753
0
          block_size   = page_block_size;
2754
0
        }
2755
0
      }
2756
0
      else
2757
0
      {
2758
0
        block_size = scan_block_size;
2759
0
      }
2760
0
      if( ( block_offset % scan_block_size ) != 0 )
2761
0
      {
2762
0
        block_offset  = ( ( block_offset / scan_block_size ) + 1 ) * scan_block_size;
2763
0
        block_size   -= block_size % scan_block_size;
2764
0
      }
2765
0
      if( block_size < scan_block_size )
2766
0
      {
2767
0
        block_offset += block_size;
2768
2769
0
        continue;
2770
0
      }
2771
0
      while( block_size >= scan_block_size )
2772
0
      {
2773
        /* The index nodes have a fixed block size and stored block size aligned
2774
         */
2775
0
        if( ( block_size >= format_page_block_size )
2776
0
         && ( ( block_offset % format_page_block_size ) == 0 ) )
2777
0
        {
2778
          /* Scan for index values in the index node
2779
           */
2780
0
          result = libpff_recover_index_values(
2781
0
              io_handle,
2782
0
              file_io_handle,
2783
0
              descriptors_index,
2784
0
              offsets_index,
2785
0
              unallocated_data_block_list,
2786
0
              block_offset,
2787
0
              recovery_flags,
2788
0
              error );
2789
2790
0
          if( result == -1 )
2791
0
          {
2792
0
            libcerror_error_set(
2793
0
             error,
2794
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
2795
0
             LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2796
0
             "%s: unable to recover index node at offset: %" PRIi64 ".\n",
2797
0
             function,
2798
0
             block_offset );
2799
2800
0
            goto on_error;
2801
0
          }
2802
0
          else if( result == 1 )
2803
0
          {
2804
0
            block_offset += format_page_block_size;
2805
0
            block_size   -= format_page_block_size;
2806
2807
0
            continue;
2808
0
          }
2809
0
        }
2810
0
        if( ( recovery_flags & LIBPFF_RECOVERY_FLAG_SCAN_FOR_FRAGMENTS ) == 0 )
2811
0
        {
2812
0
          block_offset += scan_block_size;
2813
0
          block_size   -= scan_block_size;
2814
2815
0
          continue;
2816
0
        }
2817
/* TODO optimize by minimizing amount of reads */
2818
0
        if( block_buffer_size_available == 0 )
2819
0
        {
2820
0
          block_buffer_data_offset = block_offset;
2821
2822
0
          if( block_buffer_offset > 0 )
2823
0
          {
2824
/* TODO optimize by copying the needed data to the front of the buffer */
2825
0
            block_buffer_data_offset -= format_data_block_size;
2826
0
            block_buffer_offset       = maximum_data_block_size - format_data_block_size;
2827
0
          }
2828
0
          read_size = (size_t) block_size;
2829
2830
0
          if( read_size > (size_t) maximum_data_block_size )
2831
0
          {
2832
0
            read_size = (size_t) maximum_data_block_size;
2833
0
          }
2834
#if defined( HAVE_DEBUG_OUTPUT )
2835
          if( libcnotify_verbose != 0 )
2836
          {
2837
            libcnotify_printf(
2838
             "%s: reading data block at offset: %" PRIi64 " (0x%08" PRIx64 ") of size: %" PRIzd "\n",
2839
             function,
2840
             block_buffer_data_offset,
2841
             block_buffer_data_offset,
2842
             read_size );
2843
          }
2844
#endif
2845
0
          read_count = libbfio_handle_read_buffer_at_offset(
2846
0
                  file_io_handle,
2847
0
                  &( block_buffer[ block_buffer_offset ] ),
2848
0
                  read_size,
2849
0
                  block_buffer_data_offset,
2850
0
                  error );
2851
2852
0
          if( read_count != (ssize_t) read_size )
2853
0
          {
2854
0
            libcerror_error_set(
2855
0
             error,
2856
0
             LIBCERROR_ERROR_DOMAIN_IO,
2857
0
             LIBCERROR_IO_ERROR_READ_FAILED,
2858
0
             "%s: unable to read data block at offset: %" PRIi64 " (0x%08" PRIx64 ").",
2859
0
             function,
2860
0
             block_buffer_data_offset,
2861
0
             block_buffer_data_offset );
2862
2863
0
            goto on_error;
2864
0
          }
2865
0
          block_buffer_size_available = read_size;
2866
0
        }
2867
0
        if( block_buffer_size_available >= format_data_block_size )
2868
0
        {
2869
          /* Scan the block for a data block footer
2870
           */
2871
0
          data_block_footer = &( block_buffer[ block_buffer_offset ] );
2872
2873
0
          if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
2874
0
          {
2875
0
            data_block_footer += format_data_block_size - sizeof( pff_block_footer_32bit_t );
2876
2877
0
            byte_stream_copy_to_uint16_little_endian(
2878
0
             ( (pff_block_footer_32bit_t *) data_block_footer )->data_size,
2879
0
             data_block_data_size );
2880
0
            byte_stream_copy_to_uint32_little_endian(
2881
0
             ( (pff_block_footer_32bit_t *) data_block_footer )->back_pointer,
2882
0
             data_block_back_pointer );
2883
0
            byte_stream_copy_to_uint32_little_endian(
2884
0
             ( (pff_block_footer_32bit_t *) data_block_footer )->checksum,
2885
0
             data_block_stored_checksum );
2886
0
          }
2887
0
          else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
2888
0
          {
2889
0
            data_block_footer += format_data_block_size - sizeof( pff_block_footer_64bit_t );
2890
2891
0
            byte_stream_copy_to_uint16_little_endian(
2892
0
             ( (pff_block_footer_64bit_t *) data_block_footer )->data_size,
2893
0
             data_block_data_size );
2894
0
            byte_stream_copy_to_uint32_little_endian(
2895
0
             ( (pff_block_footer_64bit_t *) data_block_footer )->checksum,
2896
0
             data_block_stored_checksum );
2897
0
            byte_stream_copy_to_uint64_little_endian(
2898
0
             ( (pff_block_footer_64bit_t *) data_block_footer )->back_pointer,
2899
0
             data_block_back_pointer );
2900
0
          }
2901
0
          else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE )
2902
0
          {
2903
0
            data_block_footer += format_data_block_size - sizeof( pff_block_footer_64bit_4k_page_t );
2904
2905
0
            byte_stream_copy_to_uint16_little_endian(
2906
0
             ( (pff_block_footer_64bit_4k_page_t *) data_block_footer )->data_size,
2907
0
             data_block_data_size );
2908
0
            byte_stream_copy_to_uint32_little_endian(
2909
0
             ( (pff_block_footer_64bit_4k_page_t *) data_block_footer )->checksum,
2910
0
             data_block_stored_checksum );
2911
0
            byte_stream_copy_to_uint64_little_endian(
2912
0
             ( (pff_block_footer_64bit_4k_page_t *) data_block_footer )->back_pointer,
2913
0
             data_block_back_pointer );
2914
0
          }
2915
          /* Check if back pointer itself is not empty but the upper 32-bit are
2916
           */
2917
0
          if( ( data_block_back_pointer != 0 )
2918
0
           && ( ( data_block_back_pointer >> 32 ) == 0 ) )
2919
0
          {
2920
0
            data_block_data_offset = block_buffer_offset - ( ( data_block_data_size / format_data_block_size ) * format_data_block_size );
2921
2922
0
            if( (size_t) data_block_data_size < read_size )
2923
0
            {
2924
0
              result = libpff_recover_analyze_data_block_back_pointer(
2925
0
                        offsets_index,
2926
0
                        data_block_back_pointer,
2927
0
                        (off64_t) block_buffer_data_offset + data_block_data_offset,
2928
0
                        (size32_t) data_block_data_size,
2929
0
                        error );
2930
2931
0
              if( result == -1 )
2932
0
              {
2933
0
                libcerror_error_set(
2934
0
                 error,
2935
0
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2936
0
                 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2937
0
                 "%s: unable to recovere data block: %" PRIu64 ".",
2938
0
                 function,
2939
0
                 data_block_back_pointer );
2940
2941
0
                goto on_error;
2942
0
              }
2943
0
              else if( result != 0 )
2944
0
              {
2945
0
                block_offset += format_data_block_size;
2946
0
                block_size   -= format_data_block_size;
2947
2948
/* TODO reset block_buffer_offset and block_buffer_size_available ? */
2949
2950
0
                continue;
2951
0
              }
2952
0
              if( data_block_stored_checksum != 0 )
2953
0
              {
2954
0
                if( libpff_checksum_calculate_weak_crc32(
2955
0
                     &data_block_calculated_checksum,
2956
0
                     &( block_buffer[ data_block_data_offset ] ),
2957
0
                     data_block_data_size,
2958
0
                     0,
2959
0
                     error ) != 1 )
2960
0
                {
2961
0
                  libcerror_error_set(
2962
0
                   error,
2963
0
                   LIBCERROR_ERROR_DOMAIN_RUNTIME,
2964
0
                   LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2965
0
                   "%s: unable to calculate weak CRC-32.",
2966
0
                   function );
2967
2968
0
                  goto on_error;
2969
0
                }
2970
0
                if( data_block_stored_checksum != data_block_calculated_checksum )
2971
0
                {
2972
#if defined( HAVE_DEBUG_OUTPUT )
2973
                  if( libcnotify_verbose != 0 )
2974
                  {
2975
                    libcnotify_printf(
2976
                     "%s: mismatch in data block: %" PRIu64 " checksum ( %" PRIu32 " != %" PRIu32 " ).\n",
2977
                     function,
2978
                     data_block_back_pointer,
2979
                     data_block_stored_checksum,
2980
                     data_block_calculated_checksum );
2981
                  }
2982
#endif
2983
0
                  block_offset += format_data_block_size;
2984
0
                  block_size   -= format_data_block_size;
2985
2986
0
                  continue;
2987
0
                }
2988
0
              }
2989
/* TODO consider data block as fragment */
2990
2991
0
              data_block_data_size = ( ( data_block_data_size / format_data_block_size ) + 1 ) * format_data_block_size;
2992
2993
#if defined( HAVE_DEBUG_OUTPUT )
2994
              if( libcnotify_verbose != 0 )
2995
              {
2996
                libcnotify_printf(
2997
                 "%s: data block back pointer: 0x%08" PRIx64 "\n",
2998
                 function,
2999
                 data_block_back_pointer );
3000
3001
                libcnotify_printf(
3002
                 "%s: data block data at offset: %" PRIi64 " (0x%08" PRIx64 ") of size: %" PRIzd "\n",
3003
                 function,
3004
                 block_buffer_data_offset + data_block_data_offset,
3005
                 block_buffer_data_offset + data_block_data_offset,
3006
                 data_block_data_size );
3007
                libcnotify_print_data(
3008
                 &( block_buffer[ data_block_data_offset ] ),
3009
                 data_block_data_size,
3010
                 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
3011
              }
3012
#endif
3013
0
            }
3014
0
          }
3015
0
          block_buffer_offset         += format_data_block_size;
3016
0
          block_buffer_size_available -= format_data_block_size;
3017
0
        }
3018
0
        else
3019
0
        {
3020
0
          block_buffer_offset         = 0;
3021
0
          block_buffer_size_available = 0;
3022
0
        }
3023
0
        block_offset += scan_block_size;
3024
0
        block_size   -= scan_block_size;
3025
0
      }
3026
0
    }
3027
0
  }
3028
0
  memory_free(
3029
0
   block_buffer );
3030
3031
0
  return( 1 );
3032
3033
0
on_error:
3034
0
  if( block_buffer != NULL )
3035
0
  {
3036
0
    memory_free(
3037
0
     block_buffer );
3038
0
  }
3039
0
  return( -1 );
3040
0
}
3041
3042
/* Scans for recoverable index values in an index node
3043
 * Returns 1 if successful, returns 0 if no valid index node could be found or -1 on error
3044
 */
3045
int libpff_recover_index_values(
3046
     libpff_io_handle_t *io_handle,
3047
     libbfio_handle_t *file_io_handle,
3048
     libpff_descriptors_index_t *descriptors_index,
3049
     libpff_offsets_index_t *offsets_index,
3050
     libcdata_range_list_t *unallocated_data_block_list,
3051
     size64_t node_offset,
3052
     uint8_t recovery_flags,
3053
     libcerror_error_t **error )
3054
0
{
3055
0
  libpff_index_node_t *index_node       = NULL;
3056
0
  libpff_index_value_t *index_value     = NULL;
3057
0
  uint8_t *node_entry_data              = NULL;
3058
0
  static char *function                 = "libpff_recover_index_values";
3059
0
  const char *index_string              = NULL;
3060
0
  off64_t index_value_file_offset       = 0;
3061
0
  uint64_t index_value_identifier       = 0;
3062
0
        uint32_t maximum_data_block_data_size = 0;
3063
0
  uint16_t index_value_data_size        = 0;
3064
0
  uint8_t entry_index                   = 0;
3065
0
  int recoverable                       = 0;
3066
0
  int result                            = 0;
3067
3068
0
  if( io_handle == NULL )
3069
0
  {
3070
0
    libcerror_error_set(
3071
0
     error,
3072
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3073
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3074
0
     "%s: invalid IO handle.",
3075
0
     function );
3076
3077
0
    return( -1 );
3078
0
  }
3079
0
  if( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT )
3080
0
   && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT )
3081
0
   && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
3082
0
  {
3083
0
    libcerror_error_set(
3084
0
     error,
3085
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3086
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
3087
0
     "%s: unsupported file type.",
3088
0
     function );
3089
3090
0
    return( -1 );
3091
0
  }
3092
0
  if( descriptors_index == NULL )
3093
0
  {
3094
0
    libcerror_error_set(
3095
0
     error,
3096
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3097
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3098
0
     "%s: invalid descriptors index.",
3099
0
     function );
3100
3101
0
    return( -1 );
3102
0
  }
3103
0
  if( offsets_index == NULL )
3104
0
  {
3105
0
    libcerror_error_set(
3106
0
     error,
3107
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3108
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3109
0
     "%s: invalid offsets index.",
3110
0
     function );
3111
3112
0
    return( -1 );
3113
0
  }
3114
0
  if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
3115
0
  {
3116
0
    maximum_data_block_data_size = 8192 - 12;
3117
0
  }
3118
0
  else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
3119
0
  {
3120
0
    maximum_data_block_data_size = 8192 - 16;
3121
0
  }
3122
0
  else
3123
0
  {
3124
/* TODO: this value is currently assumed based on the 512 x 8 = 4k page */
3125
0
    maximum_data_block_data_size = 65536 - 24;
3126
0
  }
3127
0
  if( libpff_index_node_initialize(
3128
0
       &index_node,
3129
0
       error ) != 1 )
3130
0
  {
3131
0
    libcerror_error_set(
3132
0
     error,
3133
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3134
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3135
0
     "%s: unable to create index node.",
3136
0
     function );
3137
3138
0
    goto on_error;
3139
0
  }
3140
0
  if( libpff_index_node_read_file_io_handle(
3141
0
       index_node,
3142
0
       file_io_handle,
3143
0
       node_offset,
3144
0
       io_handle->file_type,
3145
0
       error ) != 1 )
3146
0
  {
3147
#if defined( HAVE_DEBUG_OUTPUT )
3148
    if( ( libcnotify_verbose != 0 )
3149
     && ( error != NULL )
3150
     && ( *error != NULL ) )
3151
    {
3152
      libcnotify_print_error_backtrace(
3153
       *error );
3154
    }
3155
#endif
3156
0
    libcerror_error_free(
3157
0
     error );
3158
3159
0
    libpff_index_node_free(
3160
0
     &index_node,
3161
0
     NULL );
3162
3163
0
    return( 0 );
3164
0
  }
3165
0
  if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
3166
0
  {
3167
0
    index_string = "descriptors";
3168
0
  }
3169
0
  else if( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
3170
0
  {
3171
0
    index_string = "offsets";
3172
0
  }
3173
0
  if( ( index_node->type != LIBPFF_INDEX_TYPE_DESCRIPTOR )
3174
0
   && ( index_node->type != LIBPFF_INDEX_TYPE_OFFSET ) )
3175
0
  {
3176
#if defined( HAVE_DEBUG_OUTPUT )
3177
    if( libcnotify_verbose != 0 )
3178
    {
3179
      libcnotify_printf(
3180
       "%s: unsupported index type: 0x%02" PRIx8 ".\n",
3181
       function,
3182
       index_node->type );
3183
    }
3184
#endif
3185
0
  }
3186
0
  else if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF )
3187
0
  {
3188
#if defined( HAVE_DEBUG_OUTPUT )
3189
    if( libcnotify_verbose != 0 )
3190
    {
3191
      libcnotify_printf(
3192
       "%s: skipping %s index branch node at level: %" PRIu8 ".\n",
3193
       function,
3194
       index_string,
3195
       index_node->level );
3196
    }
3197
#endif
3198
0
  }
3199
0
  else
3200
0
  {
3201
    /* Check if the index leaf entries are recoverable
3202
     */
3203
0
    for( entry_index = 0;
3204
0
         entry_index < index_node->maximum_number_of_entries;
3205
0
         entry_index++ )
3206
0
    {
3207
0
      if( libpff_index_node_get_entry_data(
3208
0
           index_node,
3209
0
           entry_index,
3210
0
           &node_entry_data,
3211
0
           error ) != 1 )
3212
0
      {
3213
0
        libcerror_error_set(
3214
0
         error,
3215
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3216
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3217
0
         "%s: unable to retrieve node entry: %" PRIu8 " data.",
3218
0
         function,
3219
0
         entry_index );
3220
3221
0
        goto on_error;
3222
0
      }
3223
0
      if( node_entry_data == NULL )
3224
0
      {
3225
0
        libcerror_error_set(
3226
0
         error,
3227
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3228
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3229
0
         "%s: missing node entry: %" PRIu8 " data.",
3230
0
         function,
3231
0
         entry_index );
3232
3233
0
        goto on_error;
3234
0
      }
3235
#if defined( HAVE_DEBUG_OUTPUT )
3236
      if( libcnotify_verbose != 0 )
3237
      {
3238
        libcnotify_printf(
3239
         "%s: analyzing %s index entry: %" PRIu8 ".\n",
3240
         function,
3241
         index_string,
3242
         entry_index );
3243
      }
3244
#endif
3245
0
      if( libpff_index_value_initialize(
3246
0
           &index_value,
3247
0
           error ) != 1 )
3248
0
      {
3249
0
        libcerror_error_set(
3250
0
         error,
3251
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3252
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3253
0
         "%s: unable to create %s index value.",
3254
0
         function,
3255
0
         index_string );
3256
3257
0
        goto on_error;
3258
0
      }
3259
0
      if( libpff_index_value_read_data(
3260
0
           index_value,
3261
0
           io_handle,
3262
0
           index_node->type,
3263
0
           node_entry_data,
3264
0
           (size_t) index_node->entry_size,
3265
0
           error ) != 1 )
3266
0
      {
3267
0
        libcerror_error_set(
3268
0
         error,
3269
0
         LIBCERROR_ERROR_DOMAIN_IO,
3270
0
         LIBCERROR_IO_ERROR_READ_FAILED,
3271
0
         "%s: unable to read %s index value.",
3272
0
         function,
3273
0
         index_string );
3274
3275
0
        goto on_error;
3276
0
      }
3277
0
      recoverable = 1;
3278
3279
      /* Ignore index values without an identifier
3280
       */
3281
0
      if( index_value->identifier == 0 )
3282
0
      {
3283
#if defined( HAVE_DEBUG_OUTPUT )
3284
        if( libcnotify_verbose != 0 )
3285
        {
3286
          libcnotify_printf(
3287
           "%s: %s index entry: %" PRIu8 " has an empty identifier.\n",
3288
           function,
3289
           index_string,
3290
           entry_index );
3291
        }
3292
#endif
3293
0
        recoverable = 0;
3294
0
      }
3295
0
      else if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
3296
0
      {
3297
        /* Ignore descriptors index values without a data identifier
3298
         */
3299
0
        if( index_value->data_identifier == 0 )
3300
0
        {
3301
#if defined( HAVE_DEBUG_OUTPUT )
3302
          if( libcnotify_verbose != 0 )
3303
          {
3304
            libcnotify_printf(
3305
             "%s: %s index entry: %" PRIu8 " identifier: %" PRIu64 " has an empty data identifier.\n",
3306
             function,
3307
             index_string,
3308
             entry_index,
3309
             index_value->identifier );
3310
          }
3311
#endif
3312
0
          recoverable = 0;
3313
0
        }
3314
0
      }
3315
0
      else if( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
3316
0
      {
3317
        /* Ignore index values without a valid file offset
3318
         */
3319
0
        if( index_value->file_offset <= 0 )
3320
0
        {
3321
#if defined( HAVE_DEBUG_OUTPUT )
3322
          if( libcnotify_verbose != 0 )
3323
          {
3324
            libcnotify_printf(
3325
             "%s: %s index entry: %" PRIu8 " identifier: %" PRIu64 " has an invalid file offset: %" PRIi64 " (0x%" PRIx64 ").\n",
3326
             function,
3327
             index_string,
3328
             entry_index,
3329
             index_value->identifier,
3330
             index_value->file_offset,
3331
             index_value->file_offset );
3332
          }
3333
#endif
3334
0
          recoverable = 0;
3335
0
        }
3336
        /* Ignore index values without a valid data size
3337
         */
3338
0
        else if( ( index_value->data_size == 0 )
3339
0
              || ( (uint32_t) index_value->data_size > maximum_data_block_data_size ) )
3340
0
        {
3341
#if defined( HAVE_DEBUG_OUTPUT )
3342
          if( libcnotify_verbose != 0 )
3343
          {
3344
            libcnotify_printf(
3345
             "%s: %s index entry: %" PRIu8 " identifier: %" PRIu64 " has an invalid data size: %" PRIu16 ".\n",
3346
             function,
3347
             index_string,
3348
             entry_index,
3349
             index_value->identifier,
3350
             index_value->data_size );
3351
          }
3352
#endif
3353
0
          recoverable = 0;
3354
0
        }
3355
0
      }
3356
0
      if( recoverable != 0 )
3357
0
      {
3358
0
        if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
3359
0
        {
3360
0
          result = libpff_recover_analyze_descriptors_index_value(
3361
0
              descriptors_index,
3362
0
              io_handle,
3363
0
              file_io_handle,
3364
0
              index_value,
3365
0
              error );
3366
0
        }
3367
0
        else if( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
3368
0
        {
3369
0
          result = libpff_recover_analyze_offsets_index_value(
3370
0
              offsets_index,
3371
0
              io_handle,
3372
0
              file_io_handle,
3373
0
              index_value,
3374
0
              maximum_data_block_data_size,
3375
0
              error );
3376
0
        }
3377
0
        if( result == -1 )
3378
0
        {
3379
0
          libcerror_error_set(
3380
0
           error,
3381
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
3382
0
           LIBCERROR_RUNTIME_ERROR_GENERIC,
3383
0
           "%s: unable to analyze deleted %d index value: %" PRIu64 ".",
3384
0
           function,
3385
0
           index_string,
3386
0
           index_value->identifier );
3387
3388
0
          goto on_error;
3389
0
        }
3390
0
        recoverable = result;
3391
0
      }
3392
0
      if( recoverable != 0 )
3393
0
      {
3394
        /* Check if the offsets index value is unallocated according to the
3395
         * unallocated data block list
3396
         */
3397
0
        if( ( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
3398
0
         && ( ( recovery_flags & LIBPFF_RECOVERY_FLAG_IGNORE_ALLOCATION_DATA ) == 0 ) )
3399
0
        {
3400
0
          result = libcdata_range_list_range_is_present(
3401
0
              unallocated_data_block_list,
3402
0
              (uint64_t) index_value_file_offset,
3403
0
              (uint64_t) index_value_data_size,
3404
0
              error );
3405
3406
0
          if( result == -1 )
3407
0
          {
3408
0
            libcerror_error_set(
3409
0
             error,
3410
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
3411
0
             LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3412
0
             "%s: error determining if offset range is unallocated.",
3413
0
             function );
3414
3415
0
            goto on_error;
3416
0
          }
3417
0
          else if( result == 0 )
3418
0
          {
3419
#if defined( HAVE_DEBUG_OUTPUT )
3420
            if( libcnotify_verbose != 0 )
3421
            {
3422
              libcnotify_printf(
3423
               "%s: %s index entry: %" PRIu8 " identifier: %" PRIu64 " refers to allocated range: 0x%08" PRIx64 " - 0x%08" PRIx64 " (%" PRIu64 ").\n",
3424
               function,
3425
               index_string,
3426
               entry_index,
3427
               index_value_identifier,
3428
               index_value_file_offset,
3429
               index_value_file_offset + index_value_data_size,
3430
               index_value_data_size );
3431
            }
3432
#endif
3433
0
            recoverable = 0;
3434
0
          }
3435
#if defined( HAVE_DEBUG_OUTPUT )
3436
          else if( libcnotify_verbose != 0 )
3437
          {
3438
            libcnotify_printf(
3439
             "%s: %s index entry: %" PRIu8 " identifier: %" PRIu64 " refers to unallocated range: 0x%08" PRIx64 " - 0x%08" PRIx64 " (%" PRIu64 ").\n",
3440
             function,
3441
             index_string,
3442
             entry_index,
3443
             index_value_identifier,
3444
             index_value_file_offset,
3445
             index_value_file_offset + index_value_data_size,
3446
             index_value_data_size );
3447
          }
3448
#endif
3449
0
        }
3450
0
      }
3451
0
      if( recoverable != 0 )
3452
0
      {
3453
        /* Move the recovered node to the index
3454
         */
3455
#if defined( HAVE_DEBUG_OUTPUT )
3456
        if( libcnotify_verbose != 0 )
3457
        {
3458
          libcnotify_printf(
3459
           "%s: %s index entry: %" PRIu8 " identifier: %" PRIu64 " is recoverable.\n",
3460
           function,
3461
           index_string,
3462
           entry_index,
3463
           index_value_identifier );
3464
        }
3465
#endif
3466
0
        if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR )
3467
0
        {
3468
0
          result = libpff_descriptors_index_insert_recovered_index_value(
3469
0
                    descriptors_index,
3470
0
                    index_value,
3471
0
                    error );
3472
0
        }
3473
0
        else if( index_node->type == LIBPFF_INDEX_TYPE_OFFSET )
3474
0
        {
3475
0
          result = libpff_offsets_index_insert_recovered_index_value(
3476
0
                    offsets_index,
3477
0
                    index_value,
3478
0
                    error );
3479
0
        }
3480
0
        if( result != 1 )
3481
0
        {
3482
0
          libcerror_error_set(
3483
0
           error,
3484
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
3485
0
           LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
3486
0
           "%s: unable to insert recovered %s index value: %" PRIu64 " list.",
3487
0
           function,
3488
0
           index_string,
3489
0
           index_value_identifier );
3490
3491
0
          goto on_error;
3492
0
        }
3493
0
        index_value = NULL;
3494
0
      }
3495
0
      else
3496
0
      {
3497
0
        if( libpff_index_value_free(
3498
0
             &index_value,
3499
0
             error ) != 1 )
3500
0
        {
3501
0
          libcerror_error_set(
3502
0
           error,
3503
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
3504
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
3505
0
           "%s: unable to free index value.",
3506
0
           function );
3507
3508
0
          goto on_error;
3509
0
        }
3510
0
      }
3511
0
      node_offset += index_node->entry_size;
3512
0
    }
3513
0
  }
3514
0
  if( libpff_index_node_free(
3515
0
       &index_node,
3516
0
       error ) != 1 )
3517
0
  {
3518
0
    libcerror_error_set(
3519
0
     error,
3520
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3521
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
3522
0
     "%s: unable to free index node.",
3523
0
     function );
3524
3525
0
    goto on_error;
3526
0
  }
3527
#if defined( HAVE_DEBUG_OUTPUT )
3528
  if( libcnotify_verbose != 0 )
3529
  {
3530
    libcnotify_printf(
3531
     "\n" );
3532
  }
3533
#endif
3534
0
  return( 1 );
3535
3536
0
on_error:
3537
0
  if( index_value != NULL )
3538
0
  {
3539
0
    libpff_index_value_free(
3540
0
     &index_value,
3541
0
     NULL );
3542
0
  }
3543
0
  if( index_node != NULL )
3544
0
  {
3545
0
    libpff_index_node_free(
3546
0
     &index_node,
3547
0
     NULL );
3548
0
  }
3549
0
  return( -1 );
3550
0
}
3551
3552
/* Analyze if specific data block is recoverable
3553
 * Returns 1 if recoverable, 0 if not or -1 on error
3554
 */
3555
int libpff_recover_analyze_data_block(
3556
     libpff_io_handle_t *io_handle,
3557
     libbfio_handle_t *file_io_handle,
3558
     uint32_t descriptor_identifier,
3559
     libpff_index_value_t *offsets_index_value,
3560
     libcerror_error_t **error )
3561
0
{
3562
0
  libpff_data_block_t *data_block = NULL;
3563
0
  static char *function           = "libpff_recover_analyze_data_block";
3564
0
  int result                      = 0;
3565
3566
0
  if( offsets_index_value == NULL )
3567
0
  {
3568
0
    libcerror_error_set(
3569
0
     error,
3570
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3571
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3572
0
     "%s: invalid offsets index value.",
3573
0
     function );
3574
3575
0
    return( -1 );
3576
0
  }
3577
  /* Check if the data block is readable
3578
   */
3579
0
  if( libpff_data_block_initialize(
3580
0
       &data_block,
3581
0
       io_handle,
3582
0
       descriptor_identifier,
3583
0
       offsets_index_value->identifier,
3584
0
       error ) != 1 )
3585
0
  {
3586
0
    libcerror_error_set(
3587
0
     error,
3588
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3589
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3590
0
     "%s: unable to create data block.",
3591
0
     function );
3592
3593
0
    goto on_error;
3594
0
  }
3595
#if defined( HAVE_DEBUG_OUTPUT )
3596
  if( libcnotify_verbose != 0 )
3597
  {
3598
    libcnotify_printf(
3599
     "%s: attempting to read data block at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
3600
     function,
3601
     offsets_index_value->file_offset,
3602
     offsets_index_value->file_offset );
3603
  }
3604
#endif
3605
0
  result = libpff_data_block_read_file_io_handle(
3606
0
      data_block,
3607
0
      file_io_handle,
3608
0
      offsets_index_value->file_offset,
3609
0
      offsets_index_value->data_size,
3610
0
      io_handle->file_type,
3611
0
      error );
3612
3613
0
  if( result != 1 )
3614
0
  {
3615
0
    libcerror_error_set(
3616
0
     error,
3617
0
     LIBCERROR_ERROR_DOMAIN_IO,
3618
0
     LIBCERROR_IO_ERROR_READ_FAILED,
3619
0
     "%s: unable to read data block.",
3620
0
     function );
3621
#if defined( HAVE_DEBUG_OUTPUT )
3622
    if( ( libcnotify_verbose != 0 )
3623
     && ( error != NULL )
3624
     && ( *error != NULL ) )
3625
    {
3626
      libcnotify_print_error_backtrace(
3627
       *error );
3628
    }
3629
#endif
3630
0
    libcerror_error_free(
3631
0
     error );
3632
3633
/* TODO delete unreadable offset identifier in offsets_index->recovered_index_tree */
3634
0
  }
3635
0
  if( libpff_data_block_free(
3636
0
       &data_block,
3637
0
       error ) != 1 )
3638
0
  {
3639
0
    libcerror_error_set(
3640
0
     error,
3641
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3642
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
3643
0
     "%s: unable to free recovered data block.",
3644
0
     function );
3645
3646
0
    goto on_error;
3647
0
  }
3648
/* TODO validate the block data ? */
3649
3650
0
  return( 1 );
3651
3652
0
on_error:
3653
0
  if( data_block != NULL )
3654
0
  {
3655
0
    libpff_data_block_free(
3656
0
     &data_block,
3657
0
     NULL );
3658
0
  }
3659
0
  return( -1 );
3660
0
}
3661
3662
/* Analyze if specific local descriptors are recoverable
3663
 * Returns 1 if recoverable, 0 if not or -1 on error
3664
 */
3665
int libpff_recover_analyze_local_descriptors(
3666
     libpff_io_handle_t *io_handle,
3667
     libbfio_handle_t *file_io_handle,
3668
     libpff_offsets_index_t *offsets_index,
3669
     uint64_t local_descriptors_identifier,
3670
     libcerror_error_t **error )
3671
0
{
3672
0
  libpff_index_value_t *offsets_index_value                    = NULL;
3673
0
  libpff_local_descriptors_node_t *local_descriptors_node      = NULL;
3674
0
  uint8_t *node_entry_data                                     = NULL;
3675
0
  static char *function                                        = "libpff_recover_analyze_local_descriptors";
3676
0
  uint64_t local_descriptor_value_data_identifier              = 0;
3677
0
  uint64_t local_descriptor_value_identifier                   = 0;
3678
0
  uint64_t local_descriptor_value_local_descriptors_identifier = 0;
3679
0
  uint64_t local_descriptor_value_sub_node_identifier          = 0;
3680
0
  uint16_t entry_index                                         = 0;
3681
0
  int result                                                   = 1;
3682
3683
0
  if( io_handle == NULL )
3684
0
  {
3685
0
    libcerror_error_set(
3686
0
     error,
3687
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3688
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3689
0
     "%s: invalid IO handle.",
3690
0
     function );
3691
3692
0
    return( -1 );
3693
0
  }
3694
0
  if( libpff_offsets_index_get_index_value_by_identifier(
3695
0
       offsets_index,
3696
0
       io_handle,
3697
0
       file_io_handle,
3698
0
       local_descriptors_identifier,
3699
0
       1,
3700
0
       0,
3701
0
       &offsets_index_value,
3702
0
       error ) != 1 )
3703
0
  {
3704
#if defined( HAVE_DEBUG_OUTPUT )
3705
    if( ( libcnotify_verbose != 0 )
3706
     && ( error != NULL )
3707
     && ( *error != NULL ) )
3708
    {
3709
      libcnotify_print_error_backtrace(
3710
       *error );
3711
    }
3712
#endif
3713
0
    libcerror_error_free(
3714
0
     error );
3715
3716
0
    return( 0 );
3717
0
  }
3718
0
  if( offsets_index_value == NULL )
3719
0
  {
3720
0
    libcerror_error_set(
3721
0
     error,
3722
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3723
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3724
0
     "%s: missing offsets index value.",
3725
0
     function );
3726
3727
0
    return( -1 );
3728
0
  }
3729
#if defined( HAVE_DEBUG_OUTPUT )
3730
  if( libcnotify_verbose != 0 )
3731
  {
3732
    libcnotify_printf(
3733
     "%s: local descriptors node identifier: %" PRIu64 " (%s) at offset: %" PRIi64 " of size: %" PRIu32 "\n",
3734
     function,
3735
     offsets_index_value->identifier,
3736
     ( ( offsets_index_value->identifier & LIBPFF_OFFSET_INDEX_IDENTIFIER_FLAG_INTERNAL ) ? "internal" : "external" ),
3737
     offsets_index_value->file_offset,
3738
     offsets_index_value->data_size );
3739
  }
3740
#endif
3741
0
  if( libpff_local_descriptors_node_initialize(
3742
0
       &local_descriptors_node,
3743
0
       error ) != 1 )
3744
0
  {
3745
0
    libcerror_error_set(
3746
0
     error,
3747
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3748
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3749
0
     "%s: unable to create local descriptors node.",
3750
0
     function );
3751
3752
0
    return( -1 );
3753
0
  }
3754
0
  if( libpff_local_descriptors_node_read_file_io_handle(
3755
0
       local_descriptors_node,
3756
0
       io_handle,
3757
0
       file_io_handle,
3758
0
       0 /* TODO descriptor identifier */,
3759
0
       offsets_index_value->identifier,
3760
0
       offsets_index_value->file_offset,
3761
0
       offsets_index_value->data_size,
3762
0
       error ) != 1 )
3763
0
  {
3764
#if defined( HAVE_DEBUG_OUTPUT )
3765
    if( ( libcnotify_verbose != 0 )
3766
     && ( error != NULL )
3767
     && ( *error != NULL ) )
3768
    {
3769
      libcnotify_print_error_backtrace(
3770
       *error );
3771
    }
3772
#endif
3773
0
    libcerror_error_free(
3774
0
     error );
3775
3776
0
    libpff_local_descriptors_node_free(
3777
0
     &local_descriptors_node,
3778
0
     NULL );
3779
3780
0
    return( 0 );
3781
0
  }
3782
0
  for( entry_index = 0;
3783
0
       entry_index < local_descriptors_node->number_of_entries;
3784
0
       entry_index++ )
3785
0
  {
3786
0
    if( libpff_local_descriptors_node_get_entry_data(
3787
0
         local_descriptors_node,
3788
0
         entry_index,
3789
0
         &node_entry_data,
3790
0
         error ) != 1 )
3791
0
    {
3792
0
      libcerror_error_set(
3793
0
       error,
3794
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3795
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3796
0
       "%s: unable to retrieve node entry: %" PRIu16 " data.",
3797
0
       function,
3798
0
       entry_index );
3799
3800
0
      return( -1 );
3801
0
    }
3802
0
    if( node_entry_data == NULL )
3803
0
    {
3804
0
      libcerror_error_set(
3805
0
       error,
3806
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3807
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3808
0
       "%s: missing node entry: %" PRIu16 " data.",
3809
0
       function,
3810
0
       entry_index );
3811
3812
0
      return( -1 );
3813
0
    }
3814
0
    if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
3815
0
    {
3816
0
      byte_stream_copy_to_uint32_little_endian(
3817
0
       node_entry_data,
3818
0
       local_descriptor_value_identifier );
3819
3820
0
      node_entry_data += 4;
3821
0
    }
3822
0
    else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
3823
0
          || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
3824
0
    {
3825
0
      byte_stream_copy_to_uint64_little_endian(
3826
0
       node_entry_data,
3827
0
       local_descriptor_value_identifier );
3828
3829
0
      node_entry_data += 8;
3830
0
    }
3831
    /* Ignore the upper 32-bit of local descriptor identifiers
3832
     */
3833
0
    local_descriptor_value_identifier &= 0xffffffffUL;
3834
3835
    /* Ignore local descriptor values without a data identifier
3836
     */
3837
0
    if( local_descriptor_value_identifier == 0 )
3838
0
    {
3839
#if defined( HAVE_DEBUG_OUTPUT )
3840
      if( libcnotify_verbose != 0 )
3841
      {
3842
        libcnotify_printf(
3843
         "%s: local descriptor entry: %" PRIu8 " identifier: %" PRIu64 " has an empty identifier.\n",
3844
         function,
3845
         entry_index,
3846
         local_descriptor_value_identifier );
3847
      }
3848
#endif
3849
0
      result = 0;
3850
3851
0
      break;
3852
0
    }
3853
0
    if( local_descriptors_node->level == LIBPFF_LOCAL_DESCRIPTOR_NODE_LEVEL_LEAF )
3854
0
    {
3855
0
      if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
3856
0
      {
3857
0
        byte_stream_copy_to_uint32_little_endian(
3858
0
         node_entry_data,
3859
0
         local_descriptor_value_data_identifier );
3860
3861
0
        node_entry_data += 4;
3862
3863
0
        byte_stream_copy_to_uint32_little_endian(
3864
0
         node_entry_data,
3865
0
         local_descriptor_value_local_descriptors_identifier );
3866
3867
0
        node_entry_data += 4;
3868
0
      }
3869
0
      else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
3870
0
            || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
3871
0
      {
3872
0
        byte_stream_copy_to_uint64_little_endian(
3873
0
         node_entry_data,
3874
0
         local_descriptor_value_data_identifier );
3875
3876
0
        node_entry_data += 8;
3877
3878
0
        byte_stream_copy_to_uint64_little_endian(
3879
0
         node_entry_data,
3880
0
         local_descriptor_value_local_descriptors_identifier );
3881
3882
0
        node_entry_data += 8;
3883
0
      }
3884
      /* Ignore local descriptor values without a data identifier
3885
       */
3886
0
      if( local_descriptor_value_data_identifier == 0 )
3887
0
      {
3888
#if defined( HAVE_DEBUG_OUTPUT )
3889
        if( libcnotify_verbose != 0 )
3890
        {
3891
          libcnotify_printf(
3892
           "%s: local descriptor entry: %" PRIu8 " identifier: %" PRIu64 " has an empty data identifier.\n",
3893
           function,
3894
           entry_index,
3895
           local_descriptor_value_identifier );
3896
        }
3897
#endif
3898
0
        result = 0;
3899
3900
0
        break;
3901
0
      }
3902
0
    }
3903
0
    else
3904
0
    {
3905
0
      if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT )
3906
0
      {
3907
0
        byte_stream_copy_to_uint32_little_endian(
3908
0
         node_entry_data,
3909
0
         local_descriptor_value_sub_node_identifier );
3910
3911
0
        node_entry_data += 4;
3912
0
      }
3913
0
      else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT )
3914
0
            || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) )
3915
0
      {
3916
0
        byte_stream_copy_to_uint64_little_endian(
3917
0
         node_entry_data,
3918
0
         local_descriptor_value_sub_node_identifier );
3919
3920
0
        node_entry_data += 8;
3921
0
      }
3922
      /* Ignore local descriptor values without a sub node identifier
3923
       */
3924
0
      if( local_descriptor_value_sub_node_identifier == 0 )
3925
0
      {
3926
#if defined( HAVE_DEBUG_OUTPUT )
3927
        if( libcnotify_verbose != 0 )
3928
        {
3929
          libcnotify_printf(
3930
           "%s: local descriptor entry: %" PRIu8 " identifier: %" PRIu64 " has an empty sub node identifier.\n",
3931
           function,
3932
           entry_index,
3933
           local_descriptor_value_identifier );
3934
        }
3935
#endif
3936
0
        result = 0;
3937
3938
0
        break;
3939
0
      }
3940
0
      result = libpff_recover_analyze_local_descriptors(
3941
0
          io_handle,
3942
0
          file_io_handle,
3943
0
          offsets_index,
3944
0
          local_descriptor_value_sub_node_identifier,
3945
0
          error );
3946
3947
0
      if( result == -1 )
3948
0
      {
3949
0
        libcerror_error_set(
3950
0
         error,
3951
0
         LIBCERROR_ERROR_DOMAIN_IO,
3952
0
         LIBCERROR_IO_ERROR_READ_FAILED,
3953
0
         "%s: unable to recover local descriptors: %" PRIu64 ".",
3954
0
         function,
3955
0
         local_descriptor_value_sub_node_identifier );
3956
3957
0
        libpff_local_descriptors_node_free(
3958
0
         &local_descriptors_node,
3959
0
         NULL );
3960
3961
0
        return( -1 );
3962
0
      }
3963
0
      else if( result == 0 )
3964
0
      {
3965
0
        break;
3966
0
      }
3967
0
    }
3968
0
  }
3969
0
  if( libpff_local_descriptors_node_free(
3970
0
       &local_descriptors_node,
3971
0
       error ) != 1 )
3972
0
  {
3973
0
    libcerror_error_set(
3974
0
     error,
3975
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3976
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
3977
0
     "%s: unable to free local descriptors node.",
3978
0
     function );
3979
3980
0
    return( -1 );
3981
0
  }
3982
#if defined( HAVE_DEBUG_OUTPUT )
3983
  if( libcnotify_verbose != 0 )
3984
  {
3985
    libcnotify_printf(
3986
     "\n" );
3987
  }
3988
#endif
3989
0
  return( result );
3990
0
}
3991