Coverage Report

Created: 2025-09-05 06:58

/src/libfsntfs/libfsntfs/libfsntfs_bitmap_values.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Bitmap attribute ($BITMAP) 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 "libfsntfs_bitmap_values.h"
27
#include "libfsntfs_cluster_block.h"
28
#include "libfsntfs_cluster_block_vector.h"
29
#include "libfsntfs_definitions.h"
30
#include "libfsntfs_libbfio.h"
31
#include "libfsntfs_libcdata.h"
32
#include "libfsntfs_libcerror.h"
33
#include "libfsntfs_libcnotify.h"
34
#include "libfsntfs_libfcache.h"
35
#include "libfsntfs_libfdata.h"
36
37
/* Creates bitmap values
38
 * Make sure the value bitmap_values is referencing, is set to NULL
39
 * Returns 1 if successful or -1 on error
40
 */
41
int libfsntfs_bitmap_values_initialize(
42
     libfsntfs_bitmap_values_t **bitmap_values,
43
     libcerror_error_t **error )
44
999
{
45
999
  static char *function = "libfsntfs_bitmap_values_initialize";
46
47
999
  if( bitmap_values == NULL )
48
0
  {
49
0
    libcerror_error_set(
50
0
     error,
51
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
52
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
53
0
     "%s: invalid bitmap values.",
54
0
     function );
55
56
0
    return( -1 );
57
0
  }
58
999
  if( *bitmap_values != NULL )
59
0
  {
60
0
    libcerror_error_set(
61
0
     error,
62
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
63
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
64
0
     "%s: invalid bitmap values value already set.",
65
0
     function );
66
67
0
    return( -1 );
68
0
  }
69
999
  *bitmap_values = memory_allocate_structure(
70
999
                    libfsntfs_bitmap_values_t );
71
72
999
  if( *bitmap_values == NULL )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
77
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
78
0
     "%s: unable to create bitmap values.",
79
0
     function );
80
81
0
    goto on_error;
82
0
  }
83
999
  if( memory_set(
84
999
       *bitmap_values,
85
999
       0,
86
999
       sizeof( libfsntfs_bitmap_values_t ) ) == NULL )
87
0
  {
88
0
    libcerror_error_set(
89
0
     error,
90
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
91
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
92
0
     "%s: unable to clear bitmap values.",
93
0
     function );
94
95
0
    memory_free(
96
0
     *bitmap_values );
97
98
0
    *bitmap_values = NULL;
99
100
0
    return( -1 );
101
0
  }
102
999
  if( libcdata_range_list_initialize(
103
999
       &( ( *bitmap_values )->allocated_block_list ),
104
999
       error ) != 1 )
105
0
  {
106
0
    libcerror_error_set(
107
0
     error,
108
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
109
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
110
0
     "%s: unable to create allocated block list.",
111
0
     function );
112
113
0
    goto on_error;
114
0
  }
115
999
  return( 1 );
116
117
0
on_error:
118
0
  if( *bitmap_values != NULL )
119
0
  {
120
0
    memory_free(
121
0
     *bitmap_values );
122
123
0
    *bitmap_values = NULL;
124
0
  }
125
0
  return( -1 );
126
999
}
127
128
/* Frees bitmap values
129
 * Returns 1 if successful or -1 on error
130
 */
131
int libfsntfs_bitmap_values_free(
132
     libfsntfs_bitmap_values_t **bitmap_values,
133
     libcerror_error_t **error )
134
999
{
135
999
  static char *function = "libfsntfs_bitmap_values_free";
136
999
  int result            = 1;
137
138
999
  if( bitmap_values == NULL )
139
0
  {
140
0
    libcerror_error_set(
141
0
     error,
142
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
143
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
144
0
     "%s: invalid bitmap values.",
145
0
     function );
146
147
0
    return( -1 );
148
0
  }
149
999
  if( *bitmap_values != NULL )
150
999
  {
151
999
    if( libcdata_range_list_free(
152
999
         &( ( *bitmap_values )->allocated_block_list ),
153
999
         NULL,
154
999
         error ) != 1 )
155
0
    {
156
0
      libcerror_error_set(
157
0
       error,
158
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
159
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
160
0
       "%s: unable to free allocated data block list.",
161
0
       function );
162
163
0
      result = -1;
164
0
    }
165
999
    memory_free(
166
999
     *bitmap_values );
167
168
999
    *bitmap_values = NULL;
169
999
  }
170
999
  return( result );
171
999
}
172
173
/* Reads the bitmap values
174
 * Returns 1 if successful or -1 on error
175
 */
176
int libfsntfs_bitmap_values_read_data(
177
     libfsntfs_bitmap_values_t *bitmap_values,
178
     const uint8_t *data,
179
     size_t data_size,
180
     size_t element_data_size,
181
     off64_t *base_offset,
182
     libcerror_error_t **error )
183
44.6k
{
184
44.6k
  static char *function             = "libfsntfs_bitmap_values_read_data";
185
44.6k
  size64_t allocated_range_size     = 0;
186
44.6k
  size_t data_offset                = 0;
187
44.6k
  off64_t allocated_range_offset    = 0;
188
44.6k
  off64_t safe_base_offset          = 0;
189
44.6k
  uint8_t bit_index                 = 0;
190
44.6k
  uint8_t byte_value                = 0;
191
44.6k
  uint8_t in_allocated_range        = 0;
192
44.6k
  int allocated_element_index       = 0;
193
44.6k
  int first_allocated_element_index = 0;
194
44.6k
  int result                        = 0;
195
196
44.6k
  if( bitmap_values == NULL )
197
0
  {
198
0
    libcerror_error_set(
199
0
     error,
200
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
201
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
202
0
     "%s: invalid bitmap values.",
203
0
     function );
204
205
0
    return( -1 );
206
0
  }
207
44.6k
  if( data == NULL )
208
2
  {
209
2
    libcerror_error_set(
210
2
     error,
211
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
212
2
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
213
2
     "%s: invalid data.",
214
2
     function );
215
216
2
    return( -1 );
217
2
  }
218
44.6k
  if( data_size > (size_t) SSIZE_MAX )
219
0
  {
220
0
    libcerror_error_set(
221
0
     error,
222
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
223
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
224
0
     "%s: invalid data size value out of bounds.",
225
0
     function );
226
227
0
    return( -1 );
228
0
  }
229
44.6k
  if( base_offset == NULL )
230
0
  {
231
0
    libcerror_error_set(
232
0
     error,
233
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
234
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
235
0
     "%s: invalid base offset.",
236
0
     function );
237
238
0
    return( -1 );
239
0
  }
240
44.6k
  safe_base_offset = *base_offset;
241
242
#if defined( HAVE_DEBUG_OUTPUT )
243
  if( libcnotify_verbose != 0 )
244
  {
245
    libcnotify_printf(
246
     "%s: bitmap data:\n",
247
     function );
248
    libcnotify_print_data(
249
     data,
250
     data_size,
251
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
252
  }
253
#endif
254
11.5M
  while( data_offset < data_size )
255
11.4M
  {
256
11.4M
    byte_value = data[ data_offset ];
257
258
11.4M
    data_offset++;
259
260
11.4M
    for( bit_index = 0;
261
103M
         bit_index < 8;
262
91.7M
         bit_index++ )
263
91.7M
    {
264
91.7M
      if( in_allocated_range == 0 )
265
48.2M
      {
266
48.2M
        if( ( byte_value & 0x01 ) != 0 )
267
24.1M
        {
268
24.1M
          in_allocated_range            = 1;
269
24.1M
          first_allocated_element_index = allocated_element_index;
270
24.1M
        }
271
48.2M
      }
272
43.4M
      else if( ( byte_value & 0x01 ) == 0 )
273
24.1M
      {
274
24.1M
        allocated_range_offset = safe_base_offset + ( (off64_t) first_allocated_element_index * element_data_size );
275
24.1M
        allocated_range_size   = ( (size64_t) allocated_element_index - first_allocated_element_index ) * element_data_size;
276
277
#if defined( HAVE_DEBUG_OUTPUT )
278
        if( libcnotify_verbose != 0 )
279
        {
280
          if( first_allocated_element_index == ( allocated_element_index - 1 ) )
281
          {
282
            libcnotify_printf(
283
             "%s: allocated element\t\t\t: %d\n",
284
             function,
285
             first_allocated_element_index );
286
          }
287
          else
288
          {
289
            libcnotify_printf(
290
             "%s: allocated elements\t\t\t: %d - %d\n",
291
             function,
292
             first_allocated_element_index,
293
             allocated_element_index - 1 );
294
          }
295
          libcnotify_printf(
296
           "%s: allocated block range\t\t: 0x%" PRIx64 " - 0x%" PRIx64 "\n",
297
           function,
298
           allocated_range_offset,
299
           allocated_range_offset + allocated_range_size );
300
        }
301
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
302
303
24.1M
        result = libcdata_range_list_insert_range(
304
24.1M
                  bitmap_values->allocated_block_list,
305
24.1M
                  allocated_range_offset,
306
24.1M
                  allocated_range_size,
307
24.1M
                  NULL,
308
24.1M
                  NULL,
309
24.1M
                  NULL,
310
24.1M
                  error );
311
312
24.1M
        if( result == -1 )
313
0
        {
314
0
          libcerror_error_set(
315
0
           error,
316
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
317
0
           LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
318
0
           "%s: unable to append allocated block range to list.",
319
0
           function );
320
321
0
          return( -1 );
322
0
        }
323
24.1M
        in_allocated_range = 0;
324
24.1M
      }
325
91.7M
      byte_value >>= 1;
326
327
91.7M
      allocated_element_index++;
328
91.7M
    }
329
11.4M
  }
330
44.6k
  if( in_allocated_range != 0 )
331
30.2k
  {
332
30.2k
    allocated_range_offset = safe_base_offset + ( (off64_t) first_allocated_element_index * element_data_size );
333
30.2k
    allocated_range_size   = ( (size64_t) allocated_element_index - first_allocated_element_index ) * element_data_size;
334
335
#if defined( HAVE_DEBUG_OUTPUT )
336
    if( libcnotify_verbose != 0 )
337
    {
338
      if( first_allocated_element_index == ( allocated_element_index - 1 ) )
339
      {
340
        libcnotify_printf(
341
         "%s: allocated element\t\t\t: %d\n",
342
         function,
343
         first_allocated_element_index );
344
      }
345
      else
346
      {
347
        libcnotify_printf(
348
         "%s: allocated elements\t\t\t: %d - %d\n",
349
         function,
350
         first_allocated_element_index,
351
         allocated_element_index - 1 );
352
      }
353
      libcnotify_printf(
354
       "%s: allocated block range\t\t: 0x%" PRIx64 " - 0x%" PRIx64 "\n",
355
       function,
356
       allocated_range_offset,
357
       allocated_range_offset + allocated_range_size );
358
    }
359
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
360
361
30.2k
    result = libcdata_range_list_insert_range(
362
30.2k
              bitmap_values->allocated_block_list,
363
30.2k
              allocated_range_offset,
364
30.2k
              allocated_range_size,
365
30.2k
              NULL,
366
30.2k
              NULL,
367
30.2k
              NULL,
368
30.2k
              error );
369
370
30.2k
    if( result == -1 )
371
0
    {
372
0
      libcerror_error_set(
373
0
       error,
374
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
375
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
376
0
       "%s: unable to append allocated block range to list.",
377
0
       function );
378
379
0
      return( -1 );
380
0
    }
381
30.2k
  }
382
#if defined( HAVE_DEBUG_OUTPUT )
383
  if( libcnotify_verbose != 0 )
384
  {
385
    libcnotify_printf(
386
     "\n" );
387
  }
388
#endif
389
44.6k
  *base_offset = safe_base_offset + ( (off64_t) allocated_element_index * element_data_size );
390
391
44.6k
  return( 1 );
392
44.6k
}
393
394
/* Reads the bitmap values from an MFT attribute
395
 * Returns 1 if successful or -1 on error
396
 */
397
int libfsntfs_bitmap_values_read_from_mft_attribute(
398
     libfsntfs_bitmap_values_t *bitmap_values,
399
     libfsntfs_mft_attribute_t *mft_attribute,
400
     libfsntfs_io_handle_t *io_handle,
401
     libbfio_handle_t *file_io_handle,
402
     size_t element_data_size,
403
     uint8_t flags,
404
     libcerror_error_t **error )
405
999
{
406
999
  libfcache_cache_t *cluster_block_cache   = NULL;
407
999
  libfdata_vector_t *cluster_block_vector  = NULL;
408
999
  libfsntfs_cluster_block_t *cluster_block = NULL;
409
999
  uint8_t *data                            = NULL;
410
999
  static char *function                    = "libfsntfs_bitmap_values_read_from_mft_attribute";
411
999
  size64_t segment_size                    = 0;
412
999
  size_t data_size                         = 0;
413
999
  off64_t base_offset                      = 0;
414
999
  off64_t segment_offset                   = 0;
415
999
  uint32_t attribute_type                  = 0;
416
999
  uint32_t segment_flags                   = 0;
417
999
  int cluster_block_index                  = 0;
418
999
  int number_of_cluster_blocks             = 0;
419
999
  int number_of_segments                   = 0;
420
999
  int result                               = 0;
421
999
  int segment_file_index                   = 0;
422
999
  int segment_index                        = 0;
423
424
999
  if( bitmap_values == NULL )
425
0
  {
426
0
    libcerror_error_set(
427
0
     error,
428
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
429
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
430
0
     "%s: invalid bitmap values.",
431
0
     function );
432
433
0
    return( -1 );
434
0
  }
435
999
  if( io_handle == NULL )
436
0
  {
437
0
    libcerror_error_set(
438
0
     error,
439
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
440
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
441
0
     "%s: invalid IO handle.",
442
0
     function );
443
444
0
    return( -1 );
445
0
  }
446
999
  if( io_handle->cluster_block_size == 0 )
447
0
  {
448
0
    libcerror_error_set(
449
0
     error,
450
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
451
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
452
0
     "%s: invalid IO handle - cluster block size value out of bounds.",
453
0
     function );
454
455
0
    return( -1 );
456
0
  }
457
999
  if( libfsntfs_mft_attribute_get_type(
458
999
       mft_attribute,
459
999
       &attribute_type,
460
999
       error ) != 1 )
461
0
  {
462
0
    libcerror_error_set(
463
0
     error,
464
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
465
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
466
0
     "%s: unable to retrieve type from attribute.",
467
0
     function );
468
469
0
    goto on_error;
470
0
  }
471
999
  if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_BITMAP )
472
0
  {
473
0
    libcerror_error_set(
474
0
     error,
475
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
476
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
477
0
     "%s: unsupported attribute type.",
478
0
     function );
479
480
0
    goto on_error;
481
0
  }
482
999
  result = libfsntfs_mft_attribute_data_is_resident(
483
999
            mft_attribute,
484
999
            error );
485
486
999
  if( result == -1 )
487
0
  {
488
0
    libcerror_error_set(
489
0
     error,
490
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
491
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
492
0
     "%s: unable to determine if attribute data is resident.",
493
0
     function );
494
495
0
    goto on_error;
496
0
  }
497
999
  else if( result != 0 )
498
330
  {
499
330
    if( libfsntfs_mft_attribute_get_resident_data(
500
330
         mft_attribute,
501
330
         &data,
502
330
         &data_size,
503
330
         error ) != 1 )
504
0
    {
505
0
      libcerror_error_set(
506
0
       error,
507
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
508
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
509
0
       "%s: unable to retrieve resident data from attribute.",
510
0
       function );
511
512
0
      goto on_error;
513
0
    }
514
330
    if( libfsntfs_bitmap_values_read_data(
515
330
         bitmap_values,
516
330
         data,
517
330
         data_size,
518
330
         element_data_size,
519
330
         &base_offset,
520
330
         error ) != 1 )
521
2
    {
522
2
      libcerror_error_set(
523
2
       error,
524
2
       LIBCERROR_ERROR_DOMAIN_IO,
525
2
       LIBCERROR_IO_ERROR_READ_FAILED,
526
2
       "%s: unable to read bitmap values.",
527
2
       function );
528
529
2
      goto on_error;
530
2
    }
531
330
  }
532
669
  else if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) == 0 )
533
669
  {
534
669
    if( libfsntfs_cluster_block_vector_initialize(
535
669
         &cluster_block_vector,
536
669
         io_handle,
537
669
         mft_attribute,
538
669
         error ) != 1 )
539
403
    {
540
403
      libcerror_error_set(
541
403
       error,
542
403
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
543
403
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
544
403
       "%s: unable to create cluster block vector.",
545
403
       function );
546
547
403
      goto on_error;
548
403
    }
549
266
    if( libfcache_cache_initialize(
550
266
         &cluster_block_cache,
551
266
         1,
552
266
         error ) != 1 )
553
0
    {
554
0
      libcerror_error_set(
555
0
       error,
556
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
557
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
558
0
       "%s: unable to create cluster block cache.",
559
0
       function );
560
561
0
      goto on_error;
562
0
    }
563
266
    if( libfdata_vector_get_number_of_elements(
564
266
         cluster_block_vector,
565
266
         &number_of_cluster_blocks,
566
266
         error ) != 1 )
567
15
    {
568
15
      libcerror_error_set(
569
15
       error,
570
15
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
571
15
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
572
15
       "%s: unable to retrieve number of cluster blocks.",
573
15
       function );
574
575
15
      goto on_error;
576
15
    }
577
251
    if( libfdata_vector_get_number_of_segments(
578
251
         cluster_block_vector,
579
251
         &number_of_segments,
580
251
         error ) != 1 )
581
0
    {
582
0
      libcerror_error_set(
583
0
       error,
584
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
585
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
586
0
       "%s: unable to retrieve number of cluster block vector segments.",
587
0
       function );
588
589
0
      goto on_error;
590
0
    }
591
251
    for( segment_index = 0;
592
402
         segment_index < number_of_segments;
593
251
         segment_index++ )
594
381
    {
595
381
      if( libfdata_vector_get_segment_by_index(
596
381
           cluster_block_vector,
597
381
           segment_index,
598
381
           &segment_file_index,
599
381
           &segment_offset,
600
381
           &segment_size,
601
381
           &segment_flags,
602
381
           error ) != 1 )
603
0
      {
604
0
        libcerror_error_set(
605
0
         error,
606
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
607
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
608
0
         "%s: unable to retrieve cluster block vector segment: %d.",
609
0
         function,
610
0
         segment_index );
611
612
0
        goto on_error;
613
0
      }
614
381
      if( ( segment_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 )
615
70
      {
616
70
        cluster_block_index += segment_size / io_handle->cluster_block_size;
617
618
70
        continue;
619
70
      }
620
44.6k
      while( segment_size > 0 )
621
44.5k
      {
622
44.5k
        if( cluster_block_index >= number_of_cluster_blocks )
623
0
        {
624
0
          break;
625
0
        }
626
44.5k
        if( libfdata_vector_get_element_value_by_index(
627
44.5k
             cluster_block_vector,
628
44.5k
             (intptr_t *) file_io_handle,
629
44.5k
             (libfdata_cache_t *) cluster_block_cache,
630
44.5k
             cluster_block_index,
631
44.5k
             (intptr_t **) &cluster_block,
632
44.5k
             0,
633
44.5k
             error ) != 1 )
634
183
        {
635
183
          libcerror_error_set(
636
183
           error,
637
183
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
638
183
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
639
183
           "%s: unable to retrieve cluster block: %d from vector.",
640
183
           function,
641
183
           cluster_block_index );
642
643
183
          goto on_error;
644
183
        }
645
44.3k
        if( cluster_block == NULL )
646
0
        {
647
0
          libcerror_error_set(
648
0
           error,
649
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
650
0
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
651
0
           "%s: missing cluster block: %d.",
652
0
           function,
653
0
           cluster_block_index );
654
655
0
          goto on_error;
656
0
        }
657
44.3k
        if( libfsntfs_bitmap_values_read_data(
658
44.3k
             bitmap_values,
659
44.3k
             cluster_block->data,
660
44.3k
             cluster_block->data_size,
661
44.3k
             element_data_size,
662
44.3k
             &base_offset,
663
44.3k
             error ) != 1 )
664
0
        {
665
0
          libcerror_error_set(
666
0
           error,
667
0
           LIBCERROR_ERROR_DOMAIN_IO,
668
0
           LIBCERROR_IO_ERROR_READ_FAILED,
669
0
           "%s: unable to read bitmap values.",
670
0
           function );
671
672
0
          goto on_error;
673
0
        }
674
44.3k
        segment_size -= io_handle->cluster_block_size;
675
676
44.3k
        cluster_block_index++;
677
44.3k
      }
678
128
      if( cluster_block_index >= number_of_cluster_blocks )
679
47
      {
680
47
        break;
681
47
      }
682
128
    }
683
68
    if( libfdata_vector_free(
684
68
         &cluster_block_vector,
685
68
         error ) != 1 )
686
0
    {
687
0
      libcerror_error_set(
688
0
       error,
689
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
690
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
691
0
       "%s: unable to free cluster block vector.",
692
0
       function );
693
694
0
      goto on_error;
695
0
    }
696
68
    if( libfcache_cache_free(
697
68
         &cluster_block_cache,
698
68
         error ) != 1 )
699
0
    {
700
0
      libcerror_error_set(
701
0
       error,
702
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
703
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
704
0
       "%s: unable to free cluster block cache.",
705
0
       function );
706
707
0
      goto on_error;
708
0
    }
709
68
  }
710
396
  return( 1 );
711
712
603
on_error:
713
603
  if( cluster_block_cache != NULL )
714
198
  {
715
198
    libfcache_cache_free(
716
198
     &cluster_block_cache,
717
198
     NULL );
718
198
  }
719
603
  if( cluster_block_vector != NULL )
720
198
  {
721
198
    libfdata_vector_free(
722
198
     &cluster_block_vector,
723
198
     NULL );
724
198
  }
725
603
  return( -1 );
726
999
}
727