Coverage Report

Created: 2025-06-13 07:22

/src/libfsext/libfsext/libfsext_extents.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Extents functions
3
 *
4
 * Copyright (C) 2010-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 <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.92k
{
46
7.92k
  static char *function = "libfsext_extents_get_last_extent";
47
7.92k
  int number_of_extents = 0;
48
49
7.92k
  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.92k
  if( libcdata_array_get_number_of_entries(
61
7.92k
       extents_array,
62
7.92k
       &number_of_extents,
63
7.92k
       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.92k
  if( number_of_extents == 0 )
75
1.83k
  {
76
1.83k
    *last_extent = NULL;
77
1.83k
  }
78
6.09k
  else if( libcdata_array_get_entry_by_index(
79
6.09k
            extents_array,
80
6.09k
            number_of_extents - 1,
81
6.09k
            (intptr_t **) last_extent,
82
6.09k
            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.92k
  return( 1 );
95
7.92k
}
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
905
{
109
905
  libfsext_extent_t *last_extent   = NULL;
110
905
  libfsext_extent_t *sparse_extent = NULL;
111
905
  static char *function            = "libfsext_extents_read_inode_data_reference";
112
905
  uint32_t logical_block_number    = 0;
113
905
  int entry_index                  = 0;
114
115
905
  if( libfsext_extents_read_data(
116
905
       extents_array,
117
905
       io_handle,
118
905
       file_io_handle,
119
905
       number_of_blocks,
120
905
       data,
121
905
       data_size,
122
905
       6,
123
905
       error ) == -1 )
124
308
  {
125
308
    libcerror_error_set(
126
308
     error,
127
308
     LIBCERROR_ERROR_DOMAIN_IO,
128
308
     LIBCERROR_IO_ERROR_READ_FAILED,
129
308
     "%s: unable to read extents data.",
130
308
     function );
131
132
308
    goto on_error;
133
308
  }
134
597
  if( libfsext_extents_get_last_extent(
135
597
       extents_array,
136
597
       &last_extent,
137
597
       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
597
  if( last_extent != NULL )
149
588
  {
150
588
    logical_block_number = last_extent->logical_block_number + last_extent->number_of_blocks;
151
588
  }
152
597
  if( logical_block_number < number_of_blocks )
153
269
  {
154
269
    if( ( last_extent == NULL )
155
269
     || ( ( last_extent->range_flags & LIBFSEXT_EXTENT_FLAG_IS_SPARSE ) == 0 ) )
156
133
    {
157
133
      if( libfsext_extent_initialize(
158
133
           &sparse_extent,
159
133
           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
133
      sparse_extent->logical_block_number = logical_block_number;
171
133
      sparse_extent->range_flags          = LIBFSEXT_EXTENT_FLAG_IS_SPARSE;
172
173
133
      if( libcdata_array_append_entry(
174
133
           extents_array,
175
133
           &entry_index,
176
133
           (intptr_t *) sparse_extent,
177
133
           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
133
      last_extent   = sparse_extent;
189
133
      sparse_extent = NULL;
190
133
    }
191
269
    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
269
  }
216
597
  return( 1 );
217
218
308
on_error:
219
308
  if( sparse_extent != NULL )
220
0
  {
221
0
    libfsext_extent_free(
222
0
     &sparse_extent,
223
0
     NULL );
224
0
  }
225
308
  libcdata_array_empty(
226
308
   extents_array,
227
308
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsext_extent_free,
228
308
   NULL );
229
230
308
  return( -1 );
231
597
}
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.39k
{
246
7.39k
  libfsext_extent_t *extent                 = NULL;
247
7.39k
  libfsext_extent_t *last_extent            = NULL;
248
7.39k
  libfsext_extent_t *sparse_extent          = NULL;
249
7.39k
  libfsext_extent_index_t *extent_index     = NULL;
250
7.39k
  libfsext_extents_footer_t *extents_footer = NULL;
251
7.39k
  libfsext_extents_header_t *extents_header = NULL;
252
7.39k
  static char *function                     = "libfsext_extents_read_data";
253
7.39k
  size_t data_offset                        = 0;
254
7.39k
  off64_t extents_block_offset              = 0;
255
7.39k
  uint32_t extent_descriptor_index          = 0;
256
7.39k
  uint32_t logical_block_number             = 0;
257
7.39k
  int entry_index                           = 0;
258
259
7.39k
  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.39k
  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.39k
  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.39k
  if( ( data_size < 12 )
293
7.39k
   || ( 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.39k
  if( libfsext_extents_header_initialize(
305
7.39k
       &extents_header,
306
7.39k
       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.39k
  if( libfsext_extents_header_read_data(
318
7.39k
       extents_header,
319
7.39k
       data,
320
7.39k
       12,
321
7.39k
       error ) == -1 )
322
61
  {
323
61
    libcerror_error_set(
324
61
     error,
325
61
     LIBCERROR_ERROR_DOMAIN_IO,
326
61
     LIBCERROR_IO_ERROR_READ_FAILED,
327
61
     "%s: unable to read extents header.",
328
61
     function );
329
330
61
    goto on_error;
331
61
  }
332
7.33k
  data_offset = 12;
333
334
7.33k
  if( extents_header->depth >= parent_depth )
335
6
  {
336
6
    libcerror_error_set(
337
6
     error,
338
6
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
339
6
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
340
6
     "%s: invalid depth value out of bounds.",
341
6
     function );
342
343
6
    goto on_error;
344
6
  }
345
7.33k
  if( extents_header->number_of_extents > ( ( data_size - data_offset ) / 12 ) )
346
2
  {
347
2
    libcerror_error_set(
348
2
     error,
349
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
350
2
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
351
2
     "%s: invalid number of extents value out of bounds.",
352
2
     function );
353
354
2
    goto on_error;
355
2
  }
356
7.32k
  if( libfsext_extents_get_last_extent(
357
7.32k
       extents_array,
358
7.32k
       &last_extent,
359
7.32k
       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.32k
  if( last_extent != NULL )
371
5.50k
  {
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.50k
    logical_block_number = last_extent->logical_block_number + last_extent->number_of_blocks;
396
5.50k
  }
397
7.32k
  for( extent_descriptor_index = 0;
398
2.11M
       extent_descriptor_index < extents_header->number_of_extents;
399
2.10M
       extent_descriptor_index++ )
400
2.10M
  {
401
2.10M
    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.10M
    if( extents_header->depth == 0 )
413
2.10M
    {
414
2.10M
      if( libfsext_extent_initialize(
415
2.10M
           &extent,
416
2.10M
           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.10M
      if( libfsext_extent_read_data(
428
2.10M
           extent,
429
2.10M
           &( data[ data_offset ] ),
430
2.10M
           12,
431
2.10M
           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.10M
      data_offset += 12;
443
444
2.10M
      if( extent->number_of_blocks == 0 )
445
1.06M
      {
446
1.06M
        if( libfsext_extent_free(
447
1.06M
             &extent,
448
1.06M
             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.06M
        continue;
460
1.06M
      }
461
1.03M
      if( extent->logical_block_number > logical_block_number )
462
597k
      {
463
597k
        if( libfsext_extent_initialize(
464
597k
             &sparse_extent,
465
597k
             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
597k
        sparse_extent->logical_block_number = logical_block_number;
477
597k
        sparse_extent->number_of_blocks     = extent->logical_block_number - logical_block_number;
478
597k
        sparse_extent->range_flags          = LIBFSEXT_EXTENT_FLAG_IS_SPARSE;
479
480
597k
        if( libcdata_array_append_entry(
481
597k
             extents_array,
482
597k
             &entry_index,
483
597k
             (intptr_t *) sparse_extent,
484
597k
             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
597k
        sparse_extent = NULL;
496
597k
      }
497
1.03M
      logical_block_number = extent->logical_block_number + extent->number_of_blocks;
498
499
1.03M
      if( libcdata_array_append_entry(
500
1.03M
           extents_array,
501
1.03M
           &entry_index,
502
1.03M
           (intptr_t *) extent,
503
1.03M
           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
1.03M
      extent = NULL;
515
1.03M
    }
516
6.73k
    else
517
6.73k
    {
518
6.73k
      if( libfsext_extent_index_initialize(
519
6.73k
           &extent_index,
520
6.73k
           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.73k
      if( libfsext_extent_index_read_data(
532
6.73k
           extent_index,
533
6.73k
           &( data[ data_offset ] ),
534
6.73k
           12,
535
6.73k
           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.73k
      data_offset += 12;
547
548
6.73k
      if( extent_index->physical_block_number > ( (uint64_t) INT64_MAX / io_handle->block_size ) )
549
90
      {
550
90
        libcerror_error_set(
551
90
         error,
552
90
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
553
90
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
554
90
         "%s: invalid extent index - physical block number value out of bounds.",
555
90
         function );
556
557
90
        goto on_error;
558
90
      }
559
6.64k
      extents_block_offset = (off64_t) extent_index->physical_block_number * io_handle->block_size;
560
561
6.64k
      if( libfsext_extents_read_file_io_handle(
562
6.64k
           extents_array,
563
6.64k
           io_handle,
564
6.64k
           file_io_handle,
565
6.64k
           number_of_blocks,
566
6.64k
           extents_block_offset,
567
6.64k
           extents_header->depth,
568
6.64k
           error ) == -1 )
569
210
      {
570
210
        libcerror_error_set(
571
210
         error,
572
210
         LIBCERROR_ERROR_DOMAIN_IO,
573
210
         LIBCERROR_IO_ERROR_READ_FAILED,
574
210
         "%s: unable to read extents at depth: %" PRIu16 ".",
575
210
         function,
576
210
         extents_header->depth - 1 );
577
578
210
        goto on_error;
579
210
      }
580
6.43k
      if( libfsext_extent_index_free(
581
6.43k
           &extent_index,
582
6.43k
           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.43k
    }
594
2.10M
  }
595
7.02k
  if( libfsext_extents_header_free(
596
7.02k
       &extents_header,
597
7.02k
       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
7.02k
  if( data_offset <= ( data_size - 4 ) )
609
6.57k
  {
610
    /* Note that the extents in the inode->data_reference do not have an extents footer
611
     */
612
6.57k
    if( libfsext_extents_footer_initialize(
613
6.57k
         &extents_footer,
614
6.57k
         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.57k
    if( libfsext_extents_footer_read_data(
626
6.57k
         extents_footer,
627
6.57k
         &( data[ data_offset ] ),
628
6.57k
         4,
629
6.57k
         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.57k
    if( libfsext_extents_footer_free(
641
6.57k
         &extents_footer,
642
6.57k
         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.57k
  }
654
7.02k
  return( 1 );
655
656
369
on_error:
657
369
  if( extents_footer != NULL )
658
0
  {
659
0
    libfsext_extents_footer_free(
660
0
     &extents_footer,
661
0
     NULL );
662
0
  }
663
369
  if( extent_index != NULL )
664
300
  {
665
300
    libfsext_extent_index_free(
666
300
     &extent_index,
667
300
     NULL );
668
300
  }
669
369
  if( sparse_extent != NULL )
670
0
  {
671
0
    libfsext_extent_free(
672
0
     &sparse_extent,
673
0
     NULL );
674
0
  }
675
369
  if( extent != NULL )
676
0
  {
677
0
    libfsext_extent_free(
678
0
     &extent,
679
0
     NULL );
680
0
  }
681
369
  if( extents_header != NULL )
682
369
  {
683
369
    libfsext_extents_header_free(
684
369
     &extents_header,
685
369
     NULL );
686
369
  }
687
369
  return( -1 );
688
7.02k
}
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.64k
{
702
6.64k
  uint8_t *data         = NULL;
703
6.64k
  static char *function = "libfsext_extents_read_file_io_handle";
704
6.64k
  ssize_t read_count    = 0;
705
706
6.64k
  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.64k
  if( ( io_handle->block_size == 0 )
718
6.64k
   || ( 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.64k
  data = (uint8_t *) memory_allocate(
730
6.64k
                      sizeof( uint8_t ) * (size_t) io_handle->block_size );
731
732
6.64k
  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.64k
  read_count = libbfio_handle_read_buffer_at_offset(
755
6.64k
                file_io_handle,
756
6.64k
                data,
757
6.64k
                (size_t) io_handle->block_size,
758
6.64k
                file_offset,
759
6.64k
                error );
760
761
6.64k
  if( read_count != (ssize_t) io_handle->block_size )
762
149
  {
763
149
    libcerror_error_set(
764
149
     error,
765
149
     LIBCERROR_ERROR_DOMAIN_IO,
766
149
     LIBCERROR_IO_ERROR_READ_FAILED,
767
149
     "%s: unable to read extents data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
768
149
     function,
769
149
     file_offset,
770
149
     file_offset );
771
772
149
    goto on_error;
773
149
  }
774
6.49k
  if( libfsext_extents_read_data(
775
6.49k
       extents_array,
776
6.49k
       io_handle,
777
6.49k
       file_io_handle,
778
6.49k
       number_of_blocks,
779
6.49k
       data,
780
6.49k
       (size_t) io_handle->block_size,
781
6.49k
       parent_depth,
782
6.49k
       error ) != 1 )
783
61
  {
784
61
    libcerror_error_set(
785
61
     error,
786
61
     LIBCERROR_ERROR_DOMAIN_IO,
787
61
     LIBCERROR_IO_ERROR_READ_FAILED,
788
61
     "%s: unable to read extents data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
789
61
     function,
790
61
     file_offset,
791
61
     file_offset );
792
793
61
    goto on_error;
794
61
  }
795
6.43k
  memory_free(
796
6.43k
   data );
797
798
6.43k
  return( 1 );
799
800
210
on_error:
801
210
  if( data != NULL )
802
210
  {
803
210
    memory_free(
804
210
     data );
805
210
  }
806
210
  return( -1 );
807
6.49k
}
808