Coverage Report

Created: 2023-06-07 06:53

/src/libfsext/libfsext/libfsext_extents.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Extents functions
3
 *
4
 * Copyright (C) 2010-2023, 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 <memory.h>
24
#include <types.h>
25
26
#include "libfsext_definitions.h"
27
#include "libfsext_extent.h"
28
#include "libfsext_extent_index.h"
29
#include "libfsext_extents.h"
30
#include "libfsext_extents_footer.h"
31
#include "libfsext_extents_header.h"
32
#include "libfsext_io_handle.h"
33
#include "libfsext_libbfio.h"
34
#include "libfsext_libcdata.h"
35
#include "libfsext_libcerror.h"
36
#include "libfsext_libcnotify.h"
37
38
/* Retrieves the last extent
39
 * Returns 1 if successful or -1 on error
40
 */
41
int libfsext_extents_get_last_extent(
42
     libcdata_array_t *extents_array,
43
     libfsext_extent_t **last_extent,
44
     libcerror_error_t **error )
45
7.74k
{
46
7.74k
  static char *function = "libfsext_extents_get_last_extent";
47
7.74k
  int number_of_extents = 0;
48
49
7.74k
  if( last_extent == NULL )
50
0
  {
51
0
    libcerror_error_set(
52
0
     error,
53
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
54
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
55
0
     "%s: invalid last extent.",
56
0
     function );
57
58
0
    return( -1 );
59
0
  }
60
7.74k
  if( libcdata_array_get_number_of_entries(
61
7.74k
       extents_array,
62
7.74k
       &number_of_extents,
63
7.74k
       error ) != 1 )
64
0
  {
65
0
    libcerror_error_set(
66
0
     error,
67
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
68
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
69
0
     "%s: unable to retrieve number of extents.",
70
0
     function );
71
72
0
    return( -1 );
73
0
  }
74
7.74k
  if( number_of_extents == 0 )
75
1.85k
  {
76
1.85k
    *last_extent = NULL;
77
1.85k
  }
78
5.89k
  else if( libcdata_array_get_entry_by_index(
79
5.89k
            extents_array,
80
5.89k
            number_of_extents - 1,
81
5.89k
            (intptr_t **) last_extent,
82
5.89k
            error ) != 1 )
83
0
  {
84
0
    libcerror_error_set(
85
0
     error,
86
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
87
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
88
0
     "%s: unable to retrieve extent: %d.",
89
0
     function,
90
0
     number_of_extents - 1 );
91
92
0
    return( -1 );
93
0
  }
94
7.74k
  return( 1 );
95
7.74k
}
96
97
/* Reads the inode data reference
98
 * Returns 1 if successful or -1 on error
99
 */
100
int libfsext_extents_read_inode_data_reference(
101
     libcdata_array_t *extents_array,
102
     libfsext_io_handle_t *io_handle,
103
     libbfio_handle_t *file_io_handle,
104
     uint64_t number_of_blocks,
105
     const uint8_t *data,
106
     size_t data_size,
107
     libcerror_error_t **error )
108
900
{
109
900
  libfsext_extent_t *last_extent   = NULL;
110
900
  libfsext_extent_t *sparse_extent = NULL;
111
900
  static char *function            = "libfsext_extents_read_inode_data_reference";
112
900
  uint32_t logical_block_number    = 0;
113
900
  int entry_index                  = 0;
114
115
900
  if( libfsext_extents_read_data(
116
900
       extents_array,
117
900
       io_handle,
118
900
       file_io_handle,
119
900
       number_of_blocks,
120
900
       data,
121
900
       data_size,
122
900
       6,
123
900
       error ) == -1 )
124
340
  {
125
340
    libcerror_error_set(
126
340
     error,
127
340
     LIBCERROR_ERROR_DOMAIN_IO,
128
340
     LIBCERROR_IO_ERROR_READ_FAILED,
129
340
     "%s: unable to read extents data.",
130
340
     function );
131
132
340
    goto on_error;
133
340
  }
134
560
  if( libfsext_extents_get_last_extent(
135
560
       extents_array,
136
560
       &last_extent,
137
560
       error ) != 1 )
138
0
  {
139
0
    libcerror_error_set(
140
0
     error,
141
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
142
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
143
0
     "%s: unable to retrieve last extent.",
144
0
     function );
145
146
0
    goto on_error;
147
0
  }
148
560
  if( last_extent != NULL )
149
543
  {
150
543
    logical_block_number = last_extent->logical_block_number + last_extent->number_of_blocks;
151
543
  }
152
560
  if( logical_block_number < number_of_blocks )
153
243
  {
154
243
    if( ( last_extent == NULL )
155
243
     || ( ( last_extent->range_flags & LIBFSEXT_EXTENT_FLAG_IS_SPARSE ) == 0 ) )
156
107
    {
157
107
      if( libfsext_extent_initialize(
158
107
           &sparse_extent,
159
107
           error ) != 1 )
160
0
      {
161
0
        libcerror_error_set(
162
0
         error,
163
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
164
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
165
0
         "%s: unable to create sparse extent.",
166
0
         function );
167
168
0
        goto on_error;
169
0
      }
170
107
      sparse_extent->logical_block_number = logical_block_number;
171
107
      sparse_extent->range_flags          = LIBFSEXT_EXTENT_FLAG_IS_SPARSE;
172
173
107
      if( libcdata_array_append_entry(
174
107
           extents_array,
175
107
           &entry_index,
176
107
           (intptr_t *) sparse_extent,
177
107
           error ) != 1 )
178
0
      {
179
0
        libcerror_error_set(
180
0
         error,
181
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
182
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
183
0
         "%s: unable to append sparse extent to array.",
184
0
         function );
185
186
0
        goto on_error;
187
0
      }
188
107
      last_extent   = sparse_extent;
189
107
      sparse_extent = NULL;
190
107
    }
191
243
    last_extent->number_of_blocks += number_of_blocks - logical_block_number;
192
193
#if defined( HAVE_DEBUG_OUTPUT )
194
    if( libcnotify_verbose != 0 )
195
    {
196
      libcnotify_printf(
197
       "%s: logical block number\t: %" PRIu64 "\n",
198
       function,
199
       last_extent->logical_block_number );
200
201
      libcnotify_printf(
202
       "%s: physical block number\t: %" PRIu64 "\n",
203
       function,
204
       last_extent->physical_block_number );
205
206
      libcnotify_printf(
207
       "%s: number of blocks\t\t: %" PRIu64 "\n",
208
       function,
209
       last_extent->number_of_blocks );
210
211
      libcnotify_printf(
212
       "\n" );
213
    }
214
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
215
243
  }
216
560
  return( 1 );
217
218
340
on_error:
219
340
  if( sparse_extent != NULL )
220
0
  {
221
0
    libfsext_extent_free(
222
0
     &sparse_extent,
223
0
     NULL );
224
0
  }
225
340
  libcdata_array_empty(
226
340
   extents_array,
227
340
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsext_extent_free,
228
340
   NULL );
229
230
340
  return( -1 );
231
560
}
232
233
/* Reads the extents data
234
 * Returns 1 if successful or -1 on error
235
 */
236
int libfsext_extents_read_data(
237
     libcdata_array_t *extents_array,
238
     libfsext_io_handle_t *io_handle,
239
     libbfio_handle_t *file_io_handle,
240
     uint64_t number_of_blocks,
241
     const uint8_t *data,
242
     size_t data_size,
243
     uint16_t parent_depth,
244
     libcerror_error_t **error )
245
7.27k
{
246
7.27k
  libfsext_extent_t *extent                 = NULL;
247
7.27k
  libfsext_extent_t *last_extent            = NULL;
248
7.27k
  libfsext_extent_t *sparse_extent          = NULL;
249
7.27k
  libfsext_extent_index_t *extent_index     = NULL;
250
7.27k
  libfsext_extents_footer_t *extents_footer = NULL;
251
7.27k
  libfsext_extents_header_t *extents_header = NULL;
252
7.27k
  static char *function                     = "libfsext_extents_read_data";
253
7.27k
  size_t data_offset                        = 0;
254
7.27k
  off64_t extents_block_offset              = 0;
255
7.27k
  uint32_t extent_descriptor_index          = 0;
256
7.27k
  uint32_t logical_block_number             = 0;
257
7.27k
  int entry_index                           = 0;
258
259
7.27k
  if( io_handle == NULL )
260
0
  {
261
0
    libcerror_error_set(
262
0
     error,
263
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
264
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
265
0
     "%s: invalid IO handle.",
266
0
     function );
267
268
0
    return( -1 );
269
0
  }
270
7.27k
  if( io_handle->block_size == 0 )
271
0
  {
272
0
    libcerror_error_set(
273
0
     error,
274
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
275
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
276
0
     "%s: invalid IO handle - block size value out of bounds.",
277
0
     function );
278
279
0
    return( -1 );
280
0
  }
281
7.27k
  if( data == NULL )
282
0
  {
283
0
    libcerror_error_set(
284
0
     error,
285
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
286
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
287
0
     "%s: invalid data.",
288
0
     function );
289
290
0
    return( -1 );
291
0
  }
292
7.27k
  if( ( data_size < 12 )
293
7.27k
   || ( data_size > (size_t) SSIZE_MAX ) )
294
0
  {
295
0
    libcerror_error_set(
296
0
     error,
297
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
298
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
299
0
     "%s: invalid data size value out of bounds.",
300
0
     function );
301
302
0
    return( -1 );
303
0
  }
304
7.27k
  if( libfsext_extents_header_initialize(
305
7.27k
       &extents_header,
306
7.27k
       error ) != 1 )
307
0
  {
308
0
    libcerror_error_set(
309
0
     error,
310
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
311
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
312
0
     "%s: unable to create extents header.",
313
0
     function );
314
315
0
    goto on_error;
316
0
  }
317
7.27k
  if( libfsext_extents_header_read_data(
318
7.27k
       extents_header,
319
7.27k
       data,
320
7.27k
       12,
321
7.27k
       error ) == -1 )
322
80
  {
323
80
    libcerror_error_set(
324
80
     error,
325
80
     LIBCERROR_ERROR_DOMAIN_IO,
326
80
     LIBCERROR_IO_ERROR_READ_FAILED,
327
80
     "%s: unable to read extents header.",
328
80
     function );
329
330
80
    goto on_error;
331
80
  }
332
7.19k
  data_offset = 12;
333
334
7.19k
  if( extents_header->depth >= parent_depth )
335
7
  {
336
7
    libcerror_error_set(
337
7
     error,
338
7
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
339
7
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
340
7
     "%s: invalid depth value out of bounds.",
341
7
     function );
342
343
7
    goto on_error;
344
7
  }
345
7.18k
  if( extents_header->number_of_extents > ( ( data_size - data_offset ) / 12 ) )
346
3
  {
347
3
    libcerror_error_set(
348
3
     error,
349
3
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
350
3
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
351
3
     "%s: invalid number of extents value out of bounds.",
352
3
     function );
353
354
3
    goto on_error;
355
3
  }
356
7.18k
  if( libfsext_extents_get_last_extent(
357
7.18k
       extents_array,
358
7.18k
       &last_extent,
359
7.18k
       error ) != 1 )
360
0
  {
361
0
    libcerror_error_set(
362
0
     error,
363
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
364
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
365
0
     "%s: unable to retrieve last extent.",
366
0
     function );
367
368
0
    goto on_error;
369
0
  }
370
7.18k
  if( last_extent != NULL )
371
5.34k
  {
372
#if defined( HAVE_DEBUG_OUTPUT )
373
    if( libcnotify_verbose != 0 )
374
    {
375
      libcnotify_printf(
376
       "%s: logical block number\t\t\t: %" PRIu64 "\n",
377
       function,
378
       last_extent->logical_block_number );
379
380
      libcnotify_printf(
381
       "%s: physical block number\t\t\t: %" PRIu64 "\n",
382
       function,
383
       last_extent->physical_block_number );
384
385
      libcnotify_printf(
386
       "%s: number of blocks\t\t\t: %" PRIu64 "\n",
387
       function,
388
       last_extent->number_of_blocks );
389
390
      libcnotify_printf(
391
       "\n" );
392
    }
393
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
394
395
5.34k
    logical_block_number = last_extent->logical_block_number + last_extent->number_of_blocks;
396
5.34k
  }
397
7.18k
  for( extent_descriptor_index = 0;
398
2.04M
       extent_descriptor_index < extents_header->number_of_extents;
399
2.03M
       extent_descriptor_index++ )
400
2.03M
  {
401
2.03M
    if( data_offset > ( data_size - 12 ) )
402
0
    {
403
0
      libcerror_error_set(
404
0
       error,
405
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
406
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
407
0
       "%s: invalid data size value out of bounds.",
408
0
       function );
409
410
0
      goto on_error;
411
0
    }
412
2.03M
    if( extents_header->depth == 0 )
413
2.02M
    {
414
2.02M
      if( libfsext_extent_initialize(
415
2.02M
           &extent,
416
2.02M
           error ) != 1 )
417
0
      {
418
0
        libcerror_error_set(
419
0
         error,
420
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
421
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
422
0
         "%s: unable to create extent.",
423
0
         function );
424
425
0
        goto on_error;
426
0
      }
427
2.02M
      if( libfsext_extent_read_data(
428
2.02M
           extent,
429
2.02M
           &( data[ data_offset ] ),
430
2.02M
           12,
431
2.02M
           error ) == -1 )
432
0
      {
433
0
        libcerror_error_set(
434
0
         error,
435
0
         LIBCERROR_ERROR_DOMAIN_IO,
436
0
         LIBCERROR_IO_ERROR_READ_FAILED,
437
0
         "%s: unable to read extent.",
438
0
         function );
439
440
0
        goto on_error;
441
0
      }
442
2.02M
      data_offset += 12;
443
444
2.02M
      if( extent->number_of_blocks == 0 )
445
1.07M
      {
446
1.07M
        if( libfsext_extent_free(
447
1.07M
             &extent,
448
1.07M
             error ) != 1 )
449
0
        {
450
0
          libcerror_error_set(
451
0
           error,
452
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
453
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
454
0
           "%s: unable to free extent.",
455
0
           function );
456
457
0
          goto on_error;
458
0
        }
459
1.07M
        continue;
460
1.07M
      }
461
955k
      if( extent->logical_block_number > logical_block_number )
462
531k
      {
463
531k
        if( libfsext_extent_initialize(
464
531k
             &sparse_extent,
465
531k
             error ) != 1 )
466
0
        {
467
0
          libcerror_error_set(
468
0
           error,
469
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
470
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
471
0
           "%s: unable to create sparse extent.",
472
0
           function );
473
474
0
          goto on_error;
475
0
        }
476
531k
        sparse_extent->logical_block_number = logical_block_number;
477
531k
        sparse_extent->number_of_blocks     = extent->logical_block_number - logical_block_number;
478
531k
        sparse_extent->range_flags          = LIBFSEXT_EXTENT_FLAG_IS_SPARSE;
479
480
531k
        if( libcdata_array_append_entry(
481
531k
             extents_array,
482
531k
             &entry_index,
483
531k
             (intptr_t *) sparse_extent,
484
531k
             error ) != 1 )
485
0
        {
486
0
          libcerror_error_set(
487
0
           error,
488
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
489
0
           LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
490
0
           "%s: unable to append sparse extent to array.",
491
0
           function );
492
493
0
          goto on_error;
494
0
        }
495
531k
        sparse_extent = NULL;
496
531k
      }
497
955k
      logical_block_number = extent->logical_block_number + extent->number_of_blocks;
498
499
955k
      if( libcdata_array_append_entry(
500
955k
           extents_array,
501
955k
           &entry_index,
502
955k
           (intptr_t *) extent,
503
955k
           error ) != 1 )
504
0
      {
505
0
        libcerror_error_set(
506
0
         error,
507
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
508
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
509
0
         "%s: unable to append data extent to array.",
510
0
         function );
511
512
0
        goto on_error;
513
0
      }
514
955k
      extent = NULL;
515
955k
    }
516
6.62k
    else
517
6.62k
    {
518
6.62k
      if( libfsext_extent_index_initialize(
519
6.62k
           &extent_index,
520
6.62k
           error ) != 1 )
521
0
      {
522
0
        libcerror_error_set(
523
0
         error,
524
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
525
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
526
0
         "%s: unable to create extent index.",
527
0
         function );
528
529
0
        goto on_error;
530
0
      }
531
6.62k
      if( libfsext_extent_index_read_data(
532
6.62k
           extent_index,
533
6.62k
           &( data[ data_offset ] ),
534
6.62k
           12,
535
6.62k
           error ) == -1 )
536
0
      {
537
0
        libcerror_error_set(
538
0
         error,
539
0
         LIBCERROR_ERROR_DOMAIN_IO,
540
0
         LIBCERROR_IO_ERROR_READ_FAILED,
541
0
         "%s: unable to read extent index.",
542
0
         function );
543
544
0
        goto on_error;
545
0
      }
546
6.62k
      data_offset += 12;
547
548
6.62k
      if( extent_index->physical_block_number > ( (uint64_t) INT64_MAX / io_handle->block_size ) )
549
95
      {
550
95
        libcerror_error_set(
551
95
         error,
552
95
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
553
95
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
554
95
         "%s: invalid extent index - physical block number value out of bounds.",
555
95
         function );
556
557
95
        goto on_error;
558
95
      }
559
6.52k
      extents_block_offset = (off64_t) extent_index->physical_block_number * io_handle->block_size;
560
561
6.52k
      if( libfsext_extents_read_file_io_handle(
562
6.52k
           extents_array,
563
6.52k
           io_handle,
564
6.52k
           file_io_handle,
565
6.52k
           number_of_blocks,
566
6.52k
           extents_block_offset,
567
6.52k
           extents_header->depth,
568
6.52k
           error ) == -1 )
569
224
      {
570
224
        libcerror_error_set(
571
224
         error,
572
224
         LIBCERROR_ERROR_DOMAIN_IO,
573
224
         LIBCERROR_IO_ERROR_READ_FAILED,
574
224
         "%s: unable to read extents at depth: %" PRIu16 ".",
575
224
         function,
576
224
         extents_header->depth - 1 );
577
578
224
        goto on_error;
579
224
      }
580
6.30k
      if( libfsext_extent_index_free(
581
6.30k
           &extent_index,
582
6.30k
           error ) != 1 )
583
0
      {
584
0
        libcerror_error_set(
585
0
         error,
586
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
587
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
588
0
         "%s: unable to free extent index.",
589
0
         function );
590
591
0
        goto on_error;
592
0
      }
593
6.30k
    }
594
2.03M
  }
595
6.86k
  if( libfsext_extents_header_free(
596
6.86k
       &extents_header,
597
6.86k
       error ) != 1 )
598
0
  {
599
0
    libcerror_error_set(
600
0
     error,
601
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
602
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
603
0
     "%s: unable to free extents header.",
604
0
     function );
605
606
0
    goto on_error;
607
0
  }
608
6.86k
  if( data_offset <= ( data_size - 4 ) )
609
6.40k
  {
610
    /* Note that the extents in the inode->data_reference do not have an extents footer
611
     */
612
6.40k
    if( libfsext_extents_footer_initialize(
613
6.40k
         &extents_footer,
614
6.40k
         error ) != 1 )
615
0
    {
616
0
      libcerror_error_set(
617
0
       error,
618
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
619
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
620
0
       "%s: unable to create extents footer.",
621
0
       function );
622
623
0
      goto on_error;
624
0
    }
625
6.40k
    if( libfsext_extents_footer_read_data(
626
6.40k
         extents_footer,
627
6.40k
         &( data[ data_offset ] ),
628
6.40k
         4,
629
6.40k
         error ) == -1 )
630
0
    {
631
0
      libcerror_error_set(
632
0
       error,
633
0
       LIBCERROR_ERROR_DOMAIN_IO,
634
0
       LIBCERROR_IO_ERROR_READ_FAILED,
635
0
       "%s: unable to read extents footer.",
636
0
       function );
637
638
0
      goto on_error;
639
0
    }
640
6.40k
    if( libfsext_extents_footer_free(
641
6.40k
         &extents_footer,
642
6.40k
         error ) != 1 )
643
0
    {
644
0
      libcerror_error_set(
645
0
       error,
646
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
647
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
648
0
       "%s: unable to free extents footer.",
649
0
       function );
650
651
0
      goto on_error;
652
0
    }
653
6.40k
  }
654
6.86k
  return( 1 );
655
656
409
on_error:
657
409
  if( extents_footer != NULL )
658
0
  {
659
0
    libfsext_extents_footer_free(
660
0
     &extents_footer,
661
0
     NULL );
662
0
  }
663
409
  if( extent_index != NULL )
664
319
  {
665
319
    libfsext_extent_index_free(
666
319
     &extent_index,
667
319
     NULL );
668
319
  }
669
409
  if( sparse_extent != NULL )
670
0
  {
671
0
    libfsext_extent_free(
672
0
     &sparse_extent,
673
0
     NULL );
674
0
  }
675
409
  if( extent != NULL )
676
0
  {
677
0
    libfsext_extent_free(
678
0
     &extent,
679
0
     NULL );
680
0
  }
681
409
  if( extents_header != NULL )
682
409
  {
683
409
    libfsext_extents_header_free(
684
409
     &extents_header,
685
409
     NULL );
686
409
  }
687
409
  return( -1 );
688
6.86k
}
689
690
/* Reads the extents data
691
 * Returns 1 if successful or -1 on error
692
 */
693
int libfsext_extents_read_file_io_handle(
694
     libcdata_array_t *extents_array,
695
     libfsext_io_handle_t *io_handle,
696
     libbfio_handle_t *file_io_handle,
697
     uint64_t number_of_blocks,
698
     off64_t file_offset,
699
     uint16_t parent_depth,
700
     libcerror_error_t **error )
701
6.52k
{
702
6.52k
  uint8_t *data         = NULL;
703
6.52k
  static char *function = "libfsext_extents_read_file_io_handle";
704
6.52k
  ssize_t read_count    = 0;
705
706
6.52k
  if( io_handle == NULL )
707
0
  {
708
0
    libcerror_error_set(
709
0
     error,
710
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
711
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
712
0
     "%s: invalid IO handle.",
713
0
     function );
714
715
0
    return( -1 );
716
0
  }
717
6.52k
  if( ( io_handle->block_size == 0 )
718
6.52k
   || ( io_handle->block_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
719
0
  {
720
0
    libcerror_error_set(
721
0
     error,
722
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
723
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
724
0
     "%s: invalid IO handle - block size value out of bounds.",
725
0
     function );
726
727
0
    return( -1 );
728
0
  }
729
6.52k
  data = (uint8_t *) memory_allocate(
730
6.52k
                      sizeof( uint8_t ) * (size_t) io_handle->block_size );
731
732
6.52k
  if( data == NULL )
733
0
  {
734
0
    libcerror_error_set(
735
0
     error,
736
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
737
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
738
0
     "%s: unable to create extents data.",
739
0
     function );
740
741
0
    goto on_error;
742
0
  }
743
#if defined( HAVE_DEBUG_OUTPUT )
744
  if( libcnotify_verbose != 0 )
745
  {
746
    libcnotify_printf(
747
     "%s: reading extents data of size: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
748
     function,
749
     io_handle->block_size,
750
     file_offset,
751
     file_offset );
752
  }
753
#endif
754
6.52k
  read_count = libbfio_handle_read_buffer_at_offset(
755
6.52k
                file_io_handle,
756
6.52k
                data,
757
6.52k
                (size_t) io_handle->block_size,
758
6.52k
                file_offset,
759
6.52k
                error );
760
761
6.52k
  if( read_count != (ssize_t) io_handle->block_size )
762
155
  {
763
155
    libcerror_error_set(
764
155
     error,
765
155
     LIBCERROR_ERROR_DOMAIN_IO,
766
155
     LIBCERROR_IO_ERROR_READ_FAILED,
767
155
     "%s: unable to read extents data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
768
155
     function,
769
155
     file_offset,
770
155
     file_offset );
771
772
155
    goto on_error;
773
155
  }
774
6.37k
  if( libfsext_extents_read_data(
775
6.37k
       extents_array,
776
6.37k
       io_handle,
777
6.37k
       file_io_handle,
778
6.37k
       number_of_blocks,
779
6.37k
       data,
780
6.37k
       (size_t) io_handle->block_size,
781
6.37k
       parent_depth,
782
6.37k
       error ) != 1 )
783
69
  {
784
69
    libcerror_error_set(
785
69
     error,
786
69
     LIBCERROR_ERROR_DOMAIN_IO,
787
69
     LIBCERROR_IO_ERROR_READ_FAILED,
788
69
     "%s: unable to read extents data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
789
69
     function,
790
69
     file_offset,
791
69
     file_offset );
792
793
69
    goto on_error;
794
69
  }
795
6.30k
  memory_free(
796
6.30k
   data );
797
798
6.30k
  return( 1 );
799
800
224
on_error:
801
224
  if( data != NULL )
802
224
  {
803
224
    memory_free(
804
224
     data );
805
224
  }
806
224
  return( -1 );
807
6.37k
}
808