Coverage Report

Created: 2025-07-04 07:01

/src/libvhdi/libvhdi/libvhdi_block_allocation_table.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Block allocation table functions
3
 *
4
 * Copyright (C) 2012-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 "libvhdi_block_allocation_table.h"
28
#include "libvhdi_block_descriptor.h"
29
#include "libvhdi_definitions.h"
30
#include "libvhdi_libbfio.h"
31
#include "libvhdi_libcerror.h"
32
#include "libvhdi_libcnotify.h"
33
#include "libvhdi_libfdata.h"
34
#include "libvhdi_unused.h"
35
36
/* Creates a block allocation table
37
 * Make sure the value block_allocation_table is referencing, is set to NULL
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libvhdi_block_allocation_table_initialize(
41
     libvhdi_block_allocation_table_t **block_allocation_table,
42
     uint32_t number_of_entries,
43
     libcerror_error_t **error )
44
98
{
45
98
  static char *function = "libvhdi_block_allocation_table_initialize";
46
47
98
  if( block_allocation_table == 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 block allocation table.",
54
0
     function );
55
56
0
    return( -1 );
57
0
  }
58
98
  if( *block_allocation_table != 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 block allocation table value already set.",
65
0
     function );
66
67
0
    return( -1 );
68
0
  }
69
98
  if( number_of_entries == 0 )
70
1
  {
71
1
    libcerror_error_set(
72
1
     error,
73
1
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
74
1
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
75
1
     "%s: invalid number of entries: %" PRIu32 " value out of bounds.",
76
1
     function,
77
1
     number_of_entries );
78
79
1
    return( -1 );
80
1
  }
81
97
  *block_allocation_table = memory_allocate_structure(
82
97
                             libvhdi_block_allocation_table_t );
83
84
97
  if( *block_allocation_table == NULL )
85
0
  {
86
0
    libcerror_error_set(
87
0
     error,
88
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
89
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
90
0
     "%s: unable to create block allocation table.",
91
0
     function );
92
93
0
    goto on_error;
94
0
  }
95
97
  if( memory_set(
96
97
       *block_allocation_table,
97
97
       0,
98
97
       sizeof( libvhdi_block_allocation_table_t ) ) == NULL )
99
0
  {
100
0
    libcerror_error_set(
101
0
     error,
102
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
103
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
104
0
     "%s: unable to clear block allocation table.",
105
0
     function );
106
107
0
    memory_free(
108
0
     *block_allocation_table );
109
110
0
    *block_allocation_table = NULL;
111
112
0
    return( -1 );
113
0
  }
114
97
  ( *block_allocation_table )->number_of_entries = number_of_entries;
115
116
97
  return( 1 );
117
118
0
on_error:
119
0
  if( *block_allocation_table != NULL )
120
0
  {
121
0
    memory_free(
122
0
     *block_allocation_table );
123
124
0
    *block_allocation_table = NULL;
125
0
  }
126
0
  return( -1 );
127
97
}
128
129
/* Frees a block allocation table
130
 * Returns 1 if successful or -1 on error
131
 */
132
int libvhdi_block_allocation_table_free(
133
     libvhdi_block_allocation_table_t **block_allocation_table,
134
     libcerror_error_t **error )
135
97
{
136
97
  static char *function = "libvhdi_block_allocation_table_free";
137
138
97
  if( block_allocation_table == 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 block allocation table.",
145
0
     function );
146
147
0
    return( -1 );
148
0
  }
149
97
  if( *block_allocation_table != NULL )
150
97
  {
151
97
    memory_free(
152
97
     *block_allocation_table );
153
154
97
    *block_allocation_table = NULL;
155
97
  }
156
97
  return( 1 );
157
97
}
158
159
/* Reads the block allocation table
160
 * Returns 1 if successful or -1 on error
161
 */
162
int libvhdi_block_allocation_table_read_file_io_handle(
163
     libvhdi_block_allocation_table_t *block_allocation_table,
164
     libbfio_handle_t *file_io_handle,
165
     int file_type,
166
     uint32_t disk_type,
167
     off64_t file_offset,
168
     uint32_t block_size,
169
     uint32_t bytes_per_sector,
170
     libcerror_error_t **error )
171
97
{
172
97
  static char *function                        = "libvhdi_block_allocation_table_read_file_io_handle";
173
97
  uint64_t entries_per_chunk                   = 0;
174
97
  uint32_t sector_bitmap_size                  = 0;
175
176
#if defined( HAVE_DEBUG_OUTPUT )
177
  uint8_t empty_table_entry_data[ 8 ] = {
178
    0, 0, 0, 0, 0, 0, 0, 0 };
179
180
  libvhdi_block_descriptor_t *block_descriptor = NULL;
181
  uint8_t *data                                = NULL;
182
  size_t data_offset                           = 0;
183
  size_t read_size                             = 0;
184
  ssize_t read_count                           = 0;
185
  uint64_t table_entries_size                  = 0;
186
#endif
187
188
97
  if( block_allocation_table == NULL )
189
0
  {
190
0
    libcerror_error_set(
191
0
     error,
192
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
193
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
194
0
     "%s: invalid block allocation table.",
195
0
     function );
196
197
0
    return( -1 );
198
0
  }
199
97
  if( ( file_type != LIBVHDI_FILE_TYPE_VHD )
200
97
   && ( file_type != LIBVHDI_FILE_TYPE_VHDX ) )
201
0
  {
202
0
    libcerror_error_set(
203
0
     error,
204
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
205
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
206
0
     "%s: unsupported file type.",
207
0
     function );
208
209
0
    return( -1 );
210
0
  }
211
97
  if( block_size == 0 )
212
0
  {
213
0
    libcerror_error_set(
214
0
     error,
215
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
216
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
217
0
     "%s: invalid number of block size: %" PRIu32 " value out of bounds.",
218
0
     function,
219
0
     block_size );
220
221
0
    return( -1 );
222
0
  }
223
97
  if( ( bytes_per_sector != 512 )
224
97
   && ( bytes_per_sector != 4096 ) )
225
0
  {
226
0
    libcerror_error_set(
227
0
     error,
228
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
229
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
230
0
     "%s: unsupported bytes per sector.",
231
0
     function );
232
233
0
    return( -1 );
234
0
  }
235
97
  block_allocation_table->file_type        = file_type;
236
97
  block_allocation_table->disk_type        = disk_type;
237
97
  block_allocation_table->file_offset      = file_offset;
238
97
  block_allocation_table->block_size       = block_size;
239
97
  block_allocation_table->bytes_per_sector = bytes_per_sector;
240
241
97
  if( file_type == LIBVHDI_FILE_TYPE_VHD )
242
97
  {
243
97
    sector_bitmap_size = block_size / ( 512 * 8 );
244
245
97
    if( ( sector_bitmap_size % 512 ) != 0 )
246
80
    {
247
80
      sector_bitmap_size /= 512;
248
80
      sector_bitmap_size += 1;
249
80
      sector_bitmap_size *= 512;
250
80
    }
251
97
    block_allocation_table->sector_bitmap_size = sector_bitmap_size;
252
97
  }
253
0
  else if( file_type == LIBVHDI_FILE_TYPE_VHDX )
254
0
  {
255
0
    entries_per_chunk = ( ( (uint64_t) 1UL << 23 ) * bytes_per_sector ) / block_size;
256
257
#if defined( HAVE_DEBUG_OUTPUT )
258
    if( libcnotify_verbose != 0 )
259
    {
260
      libcnotify_printf(
261
       "%s: bytes per sector\t: %" PRIu32 "\n",
262
       function,
263
       bytes_per_sector );
264
265
      libcnotify_printf(
266
       "%s: entries per chunk\t: %" PRIu64 "\n",
267
       function,
268
       entries_per_chunk );
269
    }
270
#endif
271
0
    if( ( 1048576 % entries_per_chunk ) != 0 )
272
0
    {
273
0
      libcerror_error_set(
274
0
       error,
275
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
276
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
277
0
       "%s: unsupported entries per chunk.",
278
0
       function );
279
280
0
      return( -1 );
281
0
    }
282
0
    block_allocation_table->entries_per_chunk  = (uint32_t) entries_per_chunk;
283
0
    block_allocation_table->sector_bitmap_size = 1048576 / entries_per_chunk;
284
0
  }
285
#if defined( HAVE_DEBUG_OUTPUT )
286
  if( libcnotify_verbose != 0 )
287
  {
288
    libcnotify_printf(
289
     "%s: sector bitmap size\t: %" PRIu32 "\n",
290
     function,
291
     block_allocation_table->sector_bitmap_size );
292
  }
293
#endif
294
97
  if( file_type == LIBVHDI_FILE_TYPE_VHD )
295
97
  {
296
97
    block_allocation_table->table_entry_size = 4;
297
97
  }
298
0
  else if( file_type == LIBVHDI_FILE_TYPE_VHDX )
299
0
  {
300
0
    block_allocation_table->table_entry_size = 8;
301
0
  }
302
#if defined( HAVE_DEBUG_OUTPUT )
303
  if( libcnotify_verbose != 0 )
304
  {
305
    libcnotify_printf(
306
     "%s: table entry size\t: %" PRIzd "\n",
307
     function,
308
     block_allocation_table->table_entry_size );
309
310
    libcnotify_printf(
311
     "\n" );
312
  }
313
#endif
314
#if defined( HAVE_DEBUG_OUTPUT )
315
  if( libcnotify_verbose != 0 )
316
  {
317
    if( ( file_type == LIBVHDI_FILE_TYPE_VHDX )
318
     && ( disk_type != LIBVHDI_DISK_TYPE_FIXED ) )
319
    {
320
      table_entries_size = block_allocation_table->number_of_entries / entries_per_chunk;
321
322
      if( ( block_allocation_table->number_of_entries % entries_per_chunk ) != 0 )
323
      {
324
        table_entries_size += 1;
325
      }
326
      table_entries_size *= entries_per_chunk + 1;
327
    }
328
    else
329
    {
330
      table_entries_size = block_allocation_table->number_of_entries;
331
    }
332
    table_entries_size *= block_allocation_table->table_entry_size;
333
334
    libcnotify_printf(
335
     "%s: table entries size\t: %" PRIu64 "\n",
336
     function,
337
     table_entries_size );
338
339
    file_offset += sector_bitmap_size;
340
341
    libcnotify_printf(
342
     "%s: reading block allocation table at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
343
     function,
344
     file_offset,
345
     file_offset );
346
347
    if( libbfio_handle_seek_offset(
348
         file_io_handle,
349
         file_offset,
350
         SEEK_SET,
351
         error ) == -1 )
352
    {
353
      libcerror_error_set(
354
       error,
355
       LIBCERROR_ERROR_DOMAIN_IO,
356
       LIBCERROR_IO_ERROR_SEEK_FAILED,
357
       "%s: unable to block allocation table at offset: %" PRIi64 " (0x%08" PRIx64 ").",
358
       function,
359
       file_offset,
360
       file_offset );
361
362
      goto on_error;
363
    }
364
    data = (uint8_t *) memory_allocate(
365
                        sizeof( uint8_t ) * 64 * 1024 );
366
367
    if( data == NULL )
368
    {
369
      libcerror_error_set(
370
       error,
371
       LIBCERROR_ERROR_DOMAIN_MEMORY,
372
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
373
       "%s: unable to create block allocation table entries data.",
374
       function );
375
376
      goto on_error;
377
    }
378
    if( libvhdi_block_descriptor_initialize(
379
         &block_descriptor,
380
         error ) != 1 )
381
    {
382
      libcerror_error_set(
383
       error,
384
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
385
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
386
       "%s: unable to create block descriptor.",
387
       function );
388
389
      goto on_error;
390
    }
391
    while( table_entries_size > 0 )
392
    {
393
      read_size = 64 * 1024;
394
395
      if( read_size > table_entries_size )
396
      {
397
        read_size = table_entries_size;
398
      }
399
      read_count = libbfio_handle_read_buffer(
400
                    file_io_handle,
401
                    data,
402
                    read_size,
403
                    error );
404
405
      if( read_count != (ssize_t) read_size )
406
      {
407
        libcerror_error_set(
408
         error,
409
         LIBCERROR_ERROR_DOMAIN_IO,
410
         LIBCERROR_IO_ERROR_READ_FAILED,
411
         "%s: unable to read block allocation table entries data.",
412
         function );
413
414
        goto on_error;
415
      }
416
      libcnotify_print_data(
417
       data,
418
       read_size,
419
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
420
421
      data_offset = 0;
422
423
      while( data_offset < read_size )
424
      {
425
        if( memory_compare(
426
             &( data[ data_offset ] ),
427
             empty_table_entry_data,
428
             block_allocation_table->table_entry_size ) != 0 )
429
        {
430
          if( libvhdi_block_descriptor_read_table_entry_data(
431
               block_descriptor,
432
               &( data[ data_offset ] ),
433
               block_allocation_table->table_entry_size,
434
               file_type,
435
               block_allocation_table->sector_bitmap_size,
436
               error ) != 1 )
437
          {
438
            libcerror_error_set(
439
             error,
440
             LIBCERROR_ERROR_DOMAIN_IO,
441
             LIBCERROR_IO_ERROR_READ_FAILED,
442
             "%s: unable to read allocation table entry.",
443
             function );
444
445
            goto on_error;
446
          }
447
        }
448
        data_offset += block_allocation_table->table_entry_size;
449
      }
450
      table_entries_size -= read_size;
451
    }
452
    if( libvhdi_block_descriptor_free(
453
         &block_descriptor,
454
         error ) != 1 )
455
    {
456
      libcerror_error_set(
457
       error,
458
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
459
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
460
       "%s: unable to free block descriptor.",
461
       function );
462
463
      goto on_error;
464
    }
465
    memory_free(
466
     data );
467
  }
468
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
469
470
97
  return( 1 );
471
472
#if defined( HAVE_DEBUG_OUTPUT )
473
474
on_error:
475
  if( block_descriptor != NULL )
476
  {
477
    libvhdi_block_descriptor_free(
478
     &block_descriptor,
479
     NULL );
480
  }
481
  if( data != NULL )
482
  {
483
    memory_free(
484
     data );
485
  }
486
  return( -1 );
487
488
#endif
489
97
}
490
491
/* Reads a block allocation table entry
492
 * Callback function for the data block vector
493
 * Returns 1 if successful or -1 on error
494
 */
495
int libvhdi_block_allocation_table_read_element_data(
496
     libvhdi_block_allocation_table_t *block_allocation_table,
497
     libbfio_handle_t *file_io_handle,
498
     libfdata_vector_t *vector,
499
     libfdata_cache_t *cache,
500
     int element_index,
501
     int element_data_file_index LIBVHDI_ATTRIBUTE_UNUSED,
502
     off64_t element_data_offset LIBVHDI_ATTRIBUTE_UNUSED,
503
     size64_t element_data_size LIBVHDI_ATTRIBUTE_UNUSED,
504
     uint32_t element_data_flags LIBVHDI_ATTRIBUTE_UNUSED,
505
     uint8_t read_flags LIBVHDI_ATTRIBUTE_UNUSED,
506
     libcerror_error_t **error )
507
0
{
508
0
  libvhdi_block_descriptor_t *block_descriptor               = NULL;
509
0
  libvhdi_block_descriptor_t *sector_bitmap_block_descriptor = NULL;
510
0
  static char *function                                      = "libvhdi_block_allocation_table_read_element_data";
511
0
  off64_t sector_bitmap_offset                               = 0;
512
0
  off64_t table_entry_offset                                 = 0;
513
514
0
  LIBVHDI_UNREFERENCED_PARAMETER( element_data_file_index );
515
0
  LIBVHDI_UNREFERENCED_PARAMETER( element_data_offset );
516
0
  LIBVHDI_UNREFERENCED_PARAMETER( element_data_size );
517
0
  LIBVHDI_UNREFERENCED_PARAMETER( element_data_flags );
518
0
  LIBVHDI_UNREFERENCED_PARAMETER( read_flags );
519
520
0
  if( block_allocation_table == NULL )
521
0
  {
522
0
    libcerror_error_set(
523
0
     error,
524
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
525
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
526
0
     "%s: invalid block allocation table.",
527
0
     function );
528
529
0
    return( -1 );
530
0
  }
531
0
  if( libvhdi_block_descriptor_initialize(
532
0
       &block_descriptor,
533
0
       error ) != 1 )
534
0
  {
535
0
    libcerror_error_set(
536
0
     error,
537
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
538
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
539
0
     "%s: unable to create block descriptor.",
540
0
     function );
541
542
0
    goto on_error;
543
0
  }
544
0
  table_entry_offset = element_index;
545
546
0
  if( ( block_allocation_table->file_type == LIBVHDI_FILE_TYPE_VHDX )
547
0
   && ( block_allocation_table->disk_type != LIBVHDI_DISK_TYPE_FIXED ) )
548
0
  {
549
0
    table_entry_offset /= block_allocation_table->entries_per_chunk;
550
0
    table_entry_offset *= block_allocation_table->entries_per_chunk + 1;
551
0
    table_entry_offset += element_index % block_allocation_table->entries_per_chunk;
552
0
  }
553
#if defined( HAVE_DEBUG_OUTPUT )
554
  if( libcnotify_verbose != 0 )
555
  {
556
    libcnotify_printf(
557
     "%s: table entry index\t: %" PRIi64 "\n",
558
     function,
559
     table_entry_offset );
560
  }
561
#endif
562
0
  table_entry_offset *= block_allocation_table->table_entry_size;
563
0
  table_entry_offset += block_allocation_table->file_offset;
564
565
#if defined( HAVE_DEBUG_OUTPUT )
566
  if( libcnotify_verbose != 0 )
567
  {
568
    libcnotify_printf(
569
     "%s: table entry offset\t: %" PRIi64 "\n",
570
     function,
571
     table_entry_offset );
572
573
    libcnotify_printf(
574
     "\n" );
575
  }
576
#endif
577
0
  if( libvhdi_block_descriptor_read_table_entry_file_io_handle(
578
0
       block_descriptor,
579
0
       file_io_handle,
580
0
       block_allocation_table->file_type,
581
0
       table_entry_offset,
582
0
       block_allocation_table->sector_bitmap_size,
583
0
       error ) != 1 )
584
0
  {
585
0
    libcerror_error_set(
586
0
     error,
587
0
     LIBCERROR_ERROR_DOMAIN_IO,
588
0
     LIBCERROR_IO_ERROR_READ_FAILED,
589
0
     "%s: unable to read block allocation table entry: %d.",
590
0
     function,
591
0
     element_index );
592
593
0
    goto on_error;
594
0
  }
595
0
  if( block_allocation_table->file_type == LIBVHDI_FILE_TYPE_VHD )
596
0
  {
597
0
    sector_bitmap_offset = block_descriptor->file_offset;
598
599
0
    if( sector_bitmap_offset != -1 )
600
0
    {
601
0
      sector_bitmap_offset -= block_allocation_table->sector_bitmap_size;
602
0
    }
603
0
  }
604
0
  else if( block_allocation_table->file_type == LIBVHDI_FILE_TYPE_VHDX )
605
0
  {
606
0
    if( block_allocation_table->disk_type != LIBVHDI_DISK_TYPE_DIFFERENTIAL )
607
0
    {
608
0
      sector_bitmap_offset = -1;
609
0
    }
610
0
    else
611
0
    {
612
0
      if( block_allocation_table->entries_per_chunk == 0 )
613
0
      {
614
0
        libcerror_error_set(
615
0
         error,
616
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
617
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
618
0
         "%s: invalid block allocation table - missing entries per chunk.",
619
0
         function );
620
621
0
        goto on_error;
622
0
      }
623
0
      if( libvhdi_block_descriptor_initialize(
624
0
           &sector_bitmap_block_descriptor,
625
0
           error ) != 1 )
626
0
      {
627
0
        libcerror_error_set(
628
0
         error,
629
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
630
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
631
0
         "%s: unable to create sector bitmap block descriptor.",
632
0
         function );
633
634
0
        goto on_error;
635
0
      }
636
0
      table_entry_offset  = 1 + ( element_index / block_allocation_table->entries_per_chunk );
637
0
      table_entry_offset *= block_allocation_table->entries_per_chunk + 1;
638
0
      table_entry_offset -= 1;
639
640
#if defined( HAVE_DEBUG_OUTPUT )
641
      if( libcnotify_verbose != 0 )
642
      {
643
        libcnotify_printf(
644
         "%s: bitmap entry index\t: %" PRIi64 "\n",
645
         function,
646
         table_entry_offset );
647
      }
648
#endif
649
0
      table_entry_offset *= block_allocation_table->table_entry_size;
650
0
      table_entry_offset += block_allocation_table->file_offset;
651
652
#if defined( HAVE_DEBUG_OUTPUT )
653
      if( libcnotify_verbose != 0 )
654
      {
655
        libcnotify_printf(
656
         "%s: bitmap entry offset\t: %" PRIi64 "\n",
657
         function,
658
         table_entry_offset );
659
660
        libcnotify_printf(
661
         "\n" );
662
      }
663
#endif
664
0
      if( libvhdi_block_descriptor_read_table_entry_file_io_handle(
665
0
           sector_bitmap_block_descriptor,
666
0
           file_io_handle,
667
0
           block_allocation_table->file_type,
668
0
           table_entry_offset,
669
0
           block_allocation_table->sector_bitmap_size,
670
0
           error ) != 1 )
671
0
      {
672
0
        libcerror_error_set(
673
0
         error,
674
0
         LIBCERROR_ERROR_DOMAIN_IO,
675
0
         LIBCERROR_IO_ERROR_READ_FAILED,
676
0
         "%s: unable to read sector bitmap block allocation table entry.",
677
0
         function );
678
679
0
        goto on_error;
680
0
      }
681
0
      sector_bitmap_offset  = sector_bitmap_block_descriptor->file_offset;
682
0
      sector_bitmap_offset += ( element_index % block_allocation_table->entries_per_chunk ) * block_allocation_table->sector_bitmap_size;
683
684
0
      if( libvhdi_block_descriptor_free(
685
0
           &sector_bitmap_block_descriptor,
686
0
           error ) != 1 )
687
0
      {
688
0
        libcerror_error_set(
689
0
         error,
690
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
691
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
692
0
         "%s: unable to free sector bitmap block descriptor.",
693
0
         function );
694
695
0
        goto on_error;
696
0
      }
697
0
    }
698
0
  }
699
#if defined( HAVE_DEBUG_OUTPUT )
700
  if( libcnotify_verbose != 0 )
701
  {
702
    libcnotify_printf(
703
     "%s: sector bitmap offset\t: %" PRIi64 "\n",
704
     function,
705
     sector_bitmap_offset );
706
707
    libcnotify_printf(
708
     "\n" );
709
  }
710
#endif
711
0
  if( libvhdi_block_descriptor_read_sector_bitmap_file_io_handle(
712
0
       block_descriptor,
713
0
       file_io_handle,
714
0
       block_allocation_table->file_type,
715
0
       sector_bitmap_offset,
716
0
       block_allocation_table->block_size,
717
0
       block_allocation_table->sector_bitmap_size,
718
0
       block_allocation_table->bytes_per_sector,
719
0
       error ) != 1 )
720
0
  {
721
0
    libcerror_error_set(
722
0
     error,
723
0
     LIBCERROR_ERROR_DOMAIN_IO,
724
0
     LIBCERROR_IO_ERROR_READ_FAILED,
725
0
     "%s: unable to read block: %d sector bitmap.",
726
0
     function,
727
0
     element_index );
728
729
0
    goto on_error;
730
0
  }
731
0
  if( libfdata_vector_set_element_value_by_index(
732
0
       vector,
733
0
       (intptr_t *) file_io_handle,
734
0
       cache,
735
0
       element_index,
736
0
       (intptr_t *) block_descriptor,
737
0
       (int (*)(intptr_t **, libcerror_error_t **)) &libvhdi_block_descriptor_free,
738
0
       LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
739
0
       error ) != 1 )
740
0
  {
741
0
    libcerror_error_set(
742
0
     error,
743
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
744
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
745
0
     "%s: unable to set block descriptor as element value.",
746
0
     function );
747
748
0
    goto on_error;
749
0
  }
750
0
  return( 1 );
751
752
0
on_error:
753
0
  if( sector_bitmap_block_descriptor != NULL )
754
0
  {
755
0
    libvhdi_block_descriptor_free(
756
0
     &sector_bitmap_block_descriptor,
757
0
     NULL );
758
0
  }
759
0
  if( block_descriptor != NULL )
760
0
  {
761
0
    libvhdi_block_descriptor_free(
762
0
     &block_descriptor,
763
0
     NULL );
764
0
  }
765
0
  return( 1 );
766
0
}
767