Coverage Report

Created: 2024-02-25 07:20

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