Coverage Report

Created: 2025-12-05 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvmdk/libvmdk/libvmdk_handle.c
Line
Count
Source
1
/*
2
 * Handle functions
3
 *
4
 * Copyright (C) 2009-2025, 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 <system_string.h>
26
#include <types.h>
27
#include <wide_string.h>
28
29
#include "libvmdk_debug.h"
30
#include "libvmdk_definitions.h"
31
#include "libvmdk_descriptor_file.h"
32
#include "libvmdk_extent_descriptor.h"
33
#include "libvmdk_extent_file.h"
34
#include "libvmdk_extent_table.h"
35
#include "libvmdk_extent_values.h"
36
#include "libvmdk_handle.h"
37
#include "libvmdk_grain_data.h"
38
#include "libvmdk_grain_table.h"
39
#include "libvmdk_io_handle.h"
40
#include "libvmdk_libbfio.h"
41
#include "libvmdk_libcdata.h"
42
#include "libvmdk_libcerror.h"
43
#include "libvmdk_libcfile.h"
44
#include "libvmdk_libcnotify.h"
45
#include "libvmdk_libcpath.h"
46
#include "libvmdk_libcthreads.h"
47
#include "libvmdk_libfcache.h"
48
#include "libvmdk_libfdata.h"
49
50
/* Creates a handle
51
 * Make sure the value handle is referencing, is set to NULL
52
 * Returns 1 if successful or -1 on error
53
 */
54
int libvmdk_handle_initialize(
55
     libvmdk_handle_t **handle,
56
     libcerror_error_t **error )
57
7.28k
{
58
7.28k
  libvmdk_internal_handle_t *internal_handle = NULL;
59
7.28k
  static char *function                      = "libvmdk_handle_initialize";
60
61
7.28k
  if( handle == NULL )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
66
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
67
0
     "%s: invalid handle.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
7.28k
  if( *handle != NULL )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
77
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
78
0
     "%s: invalid handle value already set.",
79
0
     function );
80
81
0
    return( -1 );
82
0
  }
83
7.28k
  internal_handle = memory_allocate_structure(
84
7.28k
                     libvmdk_internal_handle_t );
85
86
7.28k
  if( internal_handle == NULL )
87
0
  {
88
0
    libcerror_error_set(
89
0
     error,
90
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
91
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
92
0
     "%s: unable to create handle.",
93
0
     function );
94
95
0
    goto on_error;
96
0
  }
97
7.28k
  if( memory_set(
98
7.28k
       internal_handle,
99
7.28k
       0,
100
7.28k
       sizeof( libvmdk_internal_handle_t ) ) == NULL )
101
0
  {
102
0
    libcerror_error_set(
103
0
     error,
104
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
105
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
106
0
     "%s: unable to clear handle.",
107
0
     function );
108
109
0
    memory_free(
110
0
     internal_handle );
111
112
0
    return( -1 );
113
0
  }
114
7.28k
  if( libvmdk_io_handle_initialize(
115
7.28k
       &( internal_handle->io_handle ),
116
7.28k
       error ) != 1 )
117
0
  {
118
0
    libcerror_error_set(
119
0
     error,
120
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
121
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
122
0
     "%s: unable to create IO handle.",
123
0
     function );
124
125
0
    goto on_error;
126
0
  }
127
7.28k
  if( libcdata_array_initialize(
128
7.28k
       &( internal_handle->extent_values_array ),
129
7.28k
       0,
130
7.28k
       error ) != 1 )
131
0
  {
132
0
    libcerror_error_set(
133
0
     error,
134
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
135
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
136
0
     "%s: unable to create extent values array.",
137
0
     function );
138
139
0
    goto on_error;
140
0
  }
141
7.28k
  if( libvmdk_extent_table_initialize(
142
7.28k
       &( internal_handle->extent_table ),
143
7.28k
       internal_handle->io_handle,
144
7.28k
       error ) != 1 )
145
0
  {
146
0
    libcerror_error_set(
147
0
     error,
148
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
149
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
150
0
     "%s: unable to create extent table.",
151
0
     function );
152
153
0
    goto on_error;
154
0
  }
155
7.28k
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
156
7.28k
  if( libcthreads_read_write_lock_initialize(
157
7.28k
       &( internal_handle->read_write_lock ),
158
7.28k
       error ) != 1 )
159
0
  {
160
0
    libcerror_error_set(
161
0
     error,
162
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
163
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
164
0
     "%s: unable to initialize read/write lock.",
165
0
     function );
166
167
0
    goto on_error;
168
0
  }
169
7.28k
#endif
170
7.28k
  internal_handle->maximum_number_of_open_handles = LIBBFIO_POOL_UNLIMITED_NUMBER_OF_OPEN_HANDLES;
171
172
7.28k
  *handle = (libvmdk_handle_t *) internal_handle;
173
174
7.28k
  return( 1 );
175
176
0
on_error:
177
0
  if( internal_handle != NULL )
178
0
  {
179
0
    if( internal_handle->extent_table != NULL )
180
0
    {
181
0
      libvmdk_extent_table_free(
182
0
       &( internal_handle->extent_table ),
183
0
       NULL );
184
0
    }
185
0
    if( internal_handle->extent_values_array != NULL )
186
0
    {
187
0
      libcdata_array_free(
188
0
       &( internal_handle->extent_values_array ),
189
0
       NULL,
190
0
       NULL );
191
0
    }
192
0
    if( internal_handle->io_handle != NULL )
193
0
    {
194
0
      libvmdk_io_handle_free(
195
0
       &( internal_handle->io_handle ),
196
0
       NULL );
197
0
    }
198
0
    memory_free(
199
0
     internal_handle );
200
0
  }
201
0
  return( -1 );
202
7.28k
}
203
204
/* Frees a handle
205
 * Returns 1 if successful or -1 on error
206
 */
207
int libvmdk_handle_free(
208
     libvmdk_handle_t **handle,
209
     libcerror_error_t **error )
210
7.28k
{
211
7.28k
  libvmdk_internal_handle_t *internal_handle = NULL;
212
7.28k
  static char *function                      = "libvmdk_handle_free";
213
7.28k
  int result                                 = 1;
214
215
7.28k
  if( handle == NULL )
216
0
  {
217
0
    libcerror_error_set(
218
0
     error,
219
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
220
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
221
0
     "%s: invalid handle.",
222
0
     function );
223
224
0
    return( -1 );
225
0
  }
226
7.28k
  if( *handle != NULL )
227
7.28k
  {
228
7.28k
    internal_handle = (libvmdk_internal_handle_t *) *handle;
229
230
7.28k
    if( ( internal_handle->extent_data_file_io_pool != NULL )
231
7.28k
     || ( internal_handle->descriptor_file != NULL ) )
232
0
    {
233
0
      if( libvmdk_handle_close(
234
0
           *handle,
235
0
           error ) != 0 )
236
0
      {
237
0
        libcerror_error_set(
238
0
         error,
239
0
         LIBCERROR_ERROR_DOMAIN_IO,
240
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
241
0
         "%s: unable to close handle.",
242
0
         function );
243
244
0
        result = -1;
245
0
      }
246
0
    }
247
7.28k
    *handle = NULL;
248
249
7.28k
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
250
7.28k
    if( libcthreads_read_write_lock_free(
251
7.28k
         &( internal_handle->read_write_lock ),
252
7.28k
         error ) != 1 )
253
0
    {
254
0
      libcerror_error_set(
255
0
       error,
256
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
257
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
258
0
       "%s: unable to free read/write lock.",
259
0
       function );
260
261
0
      result = -1;
262
0
    }
263
7.28k
#endif
264
7.28k
    if( libvmdk_extent_table_free(
265
7.28k
         &( internal_handle->extent_table ),
266
7.28k
         error ) != 1 )
267
0
    {
268
0
      libcerror_error_set(
269
0
       error,
270
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
271
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
272
0
       "%s: unable to free extent table.",
273
0
       function );
274
275
0
      result = -1;
276
0
    }
277
7.28k
    if( libcdata_array_free(
278
7.28k
         &( internal_handle->extent_values_array ),
279
7.28k
         (int (*)(intptr_t **, libcerror_error_t **)) &libvmdk_extent_values_free,
280
7.28k
         error ) != 1 )
281
0
    {
282
0
      libcerror_error_set(
283
0
       error,
284
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
285
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
286
0
       "%s: unable to free extent values array.",
287
0
       function );
288
289
0
      result = -1;
290
0
    }
291
7.28k
    if( libvmdk_io_handle_free(
292
7.28k
         &( internal_handle->io_handle ),
293
7.28k
         error ) != 1 )
294
0
    {
295
0
      libcerror_error_set(
296
0
       error,
297
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
298
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
299
0
       "%s: unable to free IO handle.",
300
0
       function );
301
302
0
      result = -1;
303
0
    }
304
7.28k
    memory_free(
305
7.28k
     internal_handle );
306
7.28k
  }
307
7.28k
  return( result );
308
7.28k
}
309
310
/* Signals the handle to abort its current activity
311
 * Returns 1 if successful or -1 on error
312
 */
313
int libvmdk_handle_signal_abort(
314
     libvmdk_handle_t *handle,
315
     libcerror_error_t **error )
316
0
{
317
0
  libvmdk_internal_handle_t *internal_handle = NULL;
318
0
  static char *function                      = "libvmdk_handle_signal_abort";
319
320
0
  if( handle == NULL )
321
0
  {
322
0
    libcerror_error_set(
323
0
     error,
324
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
325
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
326
0
     "%s: invalid handle.",
327
0
     function );
328
329
0
    return( -1 );
330
0
  }
331
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
332
333
0
  if( internal_handle->io_handle == NULL )
334
0
  {
335
0
    libcerror_error_set(
336
0
     error,
337
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
338
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
339
0
     "%s: invalid handle - missing IO handle.",
340
0
     function );
341
342
0
    return( -1 );
343
0
  }
344
0
  internal_handle->io_handle->abort = 1;
345
346
0
  return( 1 );
347
0
}
348
349
/* Opens a set of VMDK file(s)
350
 * Returns 1 if successful or -1 on error
351
 */
352
int libvmdk_handle_open(
353
     libvmdk_handle_t *handle,
354
     const char *filename,
355
     int access_flags,
356
     libcerror_error_t **error )
357
0
{
358
0
  libbfio_handle_t *file_io_handle           = NULL;
359
0
  libvmdk_extent_values_t *extent_values     = NULL;
360
0
  libvmdk_internal_handle_t *internal_handle = NULL;
361
0
  char *data_files_path_end                  = NULL;
362
0
  static char *function                      = "libvmdk_handle_open";
363
0
  size_t data_files_path_length              = 0;
364
0
  size_t filename_length                     = 0;
365
0
  int number_of_extents                      = 0;
366
0
  int result                                 = 1;
367
368
0
  if( handle == NULL )
369
0
  {
370
0
    libcerror_error_set(
371
0
     error,
372
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
373
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
374
0
     "%s: invalid handle.",
375
0
     function );
376
377
0
    return( -1 );
378
0
  }
379
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
380
381
0
  if( filename == NULL )
382
0
  {
383
0
    libcerror_error_set(
384
0
     error,
385
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
386
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
387
0
     "%s: invalid filename.",
388
0
     function );
389
390
0
    return( -1 );
391
0
  }
392
0
  if( ( ( access_flags & LIBVMDK_ACCESS_FLAG_READ ) == 0 )
393
0
   && ( ( access_flags & LIBVMDK_ACCESS_FLAG_WRITE ) == 0 ) )
394
0
  {
395
0
    libcerror_error_set(
396
0
     error,
397
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
398
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
399
0
     "%s: unsupported access flags.",
400
0
     function );
401
402
0
    return( -1 );
403
0
  }
404
0
  if( ( access_flags & LIBVMDK_ACCESS_FLAG_WRITE ) != 0 )
405
0
  {
406
0
    libcerror_error_set(
407
0
     error,
408
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
409
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
410
0
     "%s: write access currently not supported.",
411
0
     function );
412
413
0
    return( -1 );
414
0
  }
415
0
  filename_length = narrow_string_length(
416
0
                     filename );
417
418
0
  if( libbfio_file_initialize(
419
0
       &file_io_handle,
420
0
       error ) != 1 )
421
0
  {
422
0
    libcerror_error_set(
423
0
     error,
424
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
425
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
426
0
     "%s: unable to create file IO handle.",
427
0
     function );
428
429
0
    goto on_error;
430
0
  }
431
#if defined( HAVE_DEBUG_OUTPUT )
432
  if( libbfio_handle_set_track_offsets_read(
433
       file_io_handle,
434
       1,
435
       error ) != 1 )
436
  {
437
    libcerror_error_set(
438
     error,
439
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
440
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
441
     "%s: unable to set track offsets read in file IO handle.",
442
     function );
443
444
    goto on_error;
445
  }
446
#endif
447
0
  if( libbfio_file_set_name(
448
0
       file_io_handle,
449
0
       filename,
450
0
       filename_length + 1,
451
0
       error ) != 1 )
452
0
  {
453
0
    libcerror_error_set(
454
0
     error,
455
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
456
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
457
0
     "%s: unable to set name in file IO handle.",
458
0
     function );
459
460
0
    goto on_error;
461
0
  }
462
0
  if( libvmdk_handle_open_file_io_handle(
463
0
       handle,
464
0
       file_io_handle,
465
0
       access_flags,
466
0
       error ) != 1 )
467
0
  {
468
0
    libcerror_error_set(
469
0
     error,
470
0
     LIBCERROR_ERROR_DOMAIN_IO,
471
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
472
0
     "%s: unable to open handle using a file IO handle.",
473
0
     function );
474
475
0
    goto on_error;
476
0
  }
477
0
  if( libbfio_handle_free(
478
0
       &file_io_handle,
479
0
       error ) != 1 )
480
0
  {
481
0
    libcerror_error_set(
482
0
     error,
483
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
484
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
485
0
     "%s: unable to free file IO handle.",
486
0
     function );
487
488
0
    goto on_error;
489
0
  }
490
  /* Note that extent file names can be renamed hence for a single monolithic sparse
491
   * or stream optimized image the filename instead of the extent data filename in
492
   * the descriptor file is used.
493
   */
494
/* TODO thread lock */
495
0
  if( ( internal_handle->disk_type == LIBVMDK_DISK_TYPE_MONOLITHIC_SPARSE )
496
0
   || ( internal_handle->disk_type == LIBVMDK_DISK_TYPE_STREAM_OPTIMIZED ) )
497
0
  {
498
0
    if( libcdata_array_get_number_of_entries(
499
0
         internal_handle->extent_values_array,
500
0
         &number_of_extents,
501
0
         error ) != 1 )
502
0
    {
503
0
      libcerror_error_set(
504
0
       error,
505
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
506
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
507
0
       "%s: unable to retrieve number of extents.",
508
0
       function );
509
510
0
      goto on_error;
511
0
    }
512
0
    if( number_of_extents == 1 )
513
0
    {
514
0
      if( libcdata_array_get_entry_by_index(
515
0
           internal_handle->extent_values_array,
516
0
           0,
517
0
           (intptr_t **) &extent_values,
518
0
           error ) != 1 )
519
0
      {
520
0
        libcerror_error_set(
521
0
         error,
522
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
523
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
524
0
         "%s: unable to retrieve extent values: 0 from array.",
525
0
         function );
526
527
0
        goto on_error;
528
0
      }
529
0
      if( extent_values == NULL )
530
0
      { 
531
0
        libcerror_error_set(
532
0
         error,
533
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
534
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
535
0
         "%s: missing extent values: 0.",
536
0
         function );
537
538
0
        goto on_error;
539
0
      }
540
0
      if( extent_values->type == LIBVMDK_EXTENT_TYPE_SPARSE )
541
0
      {
542
0
        if( libvmdk_extent_values_set_alternate_filename(
543
0
             extent_values,
544
0
             filename,
545
0
             filename_length,
546
0
             error ) != 1 )
547
0
        {
548
0
          libcerror_error_set(
549
0
           error,
550
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
551
0
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
552
0
           "%s: unable to set alternate filename in extent values.",
553
0
           function );
554
555
0
          goto on_error;
556
0
        }
557
#if defined( HAVE_DEBUG_OUTPUT )
558
        if( libcnotify_verbose != 0 )
559
        {
560
          libcnotify_printf(
561
           "%s: alternate filename\t\t\t\t\t: %" PRIs_SYSTEM "\n",
562
           function,
563
           extent_values->alternate_filename );
564
        }
565
#endif
566
0
      }
567
0
    }
568
0
  }
569
0
  data_files_path_end = narrow_string_search_character_reverse(
570
0
                         filename,
571
0
                         (int) LIBCPATH_SEPARATOR,
572
0
                         filename_length + 1 );
573
574
0
  if( data_files_path_end != NULL )
575
0
  {
576
0
    data_files_path_length = (size_t) ( data_files_path_end - filename ) + 1;
577
0
  }
578
0
  if( data_files_path_length > 0 )
579
0
  {
580
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
581
0
    if( libcthreads_read_write_lock_grab_for_write(
582
0
         internal_handle->read_write_lock,
583
0
         error ) != 1 )
584
0
    {
585
0
      libcerror_error_set(
586
0
       error,
587
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
588
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
589
0
       "%s: unable to grab read/write lock for writing.",
590
0
       function );
591
592
0
      return( -1 );
593
0
    }
594
0
#endif
595
0
    if( libvmdk_extent_table_set_data_files_path(
596
0
         internal_handle->extent_table,
597
0
         filename,
598
0
         data_files_path_length,
599
0
         error ) != 1 )
600
0
    {
601
0
      libcerror_error_set(
602
0
       error,
603
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
604
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
605
0
       "%s: unable to set data files path in extent table.",
606
0
       function );
607
608
0
      result = -1;
609
0
    }
610
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
611
0
    if( libcthreads_read_write_lock_release_for_write(
612
0
         internal_handle->read_write_lock,
613
0
         error ) != 1 )
614
0
    {
615
0
      libcerror_error_set(
616
0
       error,
617
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
618
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
619
0
       "%s: unable to release read/write lock for writing.",
620
0
       function );
621
622
0
      return( -1 );
623
0
    }
624
0
#endif
625
0
  }
626
0
  return( result );
627
628
0
on_error:
629
0
  if( file_io_handle != NULL )
630
0
  {
631
0
    libbfio_handle_free(
632
0
     &file_io_handle,
633
0
     NULL );
634
0
  }
635
0
  return( -1 );
636
0
}
637
638
#if defined( HAVE_WIDE_CHARACTER_TYPE )
639
640
/* Opens a set of VMDK file(s)
641
 * Returns 1 if successful or -1 on error
642
 */
643
int libvmdk_handle_open_wide(
644
     libvmdk_handle_t *handle,
645
     const wchar_t *filename,
646
     int access_flags,
647
     libcerror_error_t **error )
648
{
649
  libbfio_handle_t *file_io_handle           = NULL;
650
  libvmdk_extent_values_t *extent_values     = NULL;
651
  libvmdk_internal_handle_t *internal_handle = NULL;
652
  wchar_t *data_files_path_end               = NULL;
653
  static char *function                      = "libvmdk_handle_open_wide";
654
  size_t data_files_path_length              = 0;
655
  size_t filename_length                     = 0;
656
  int number_of_extents                      = 0;
657
  int result                                 = 1;
658
659
  if( handle == NULL )
660
  {
661
    libcerror_error_set(
662
     error,
663
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
664
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
665
     "%s: invalid handle.",
666
     function );
667
668
    return( -1 );
669
  }
670
  internal_handle = (libvmdk_internal_handle_t *) handle;
671
672
  if( filename == NULL )
673
  {
674
    libcerror_error_set(
675
     error,
676
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
677
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
678
     "%s: invalid filename.",
679
     function );
680
681
    return( -1 );
682
  }
683
  if( ( ( access_flags & LIBVMDK_ACCESS_FLAG_READ ) == 0 )
684
   && ( ( access_flags & LIBVMDK_ACCESS_FLAG_WRITE ) == 0 ) )
685
  {
686
    libcerror_error_set(
687
     error,
688
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
689
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
690
     "%s: unsupported access flags.",
691
     function );
692
693
    return( -1 );
694
  }
695
  if( ( access_flags & LIBVMDK_ACCESS_FLAG_WRITE ) != 0 )
696
  {
697
    libcerror_error_set(
698
     error,
699
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
700
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
701
     "%s: write access currently not supported.",
702
     function );
703
704
    return( -1 );
705
  }
706
  filename_length = wide_string_length(
707
                     filename );
708
709
  if( libbfio_file_initialize(
710
       &file_io_handle,
711
       error ) != 1 )
712
  {
713
    libcerror_error_set(
714
     error,
715
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
716
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
717
     "%s: unable to create file IO handle.",
718
     function );
719
720
    goto on_error;
721
  }
722
#if defined( HAVE_DEBUG_OUTPUT )
723
  if( libbfio_handle_set_track_offsets_read(
724
       file_io_handle,
725
       1,
726
       error ) != 1 )
727
  {
728
    libcerror_error_set(
729
     error,
730
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
731
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
732
     "%s: unable to set track offsets read in file IO handle.",
733
     function );
734
735
    goto on_error;
736
  }
737
#endif
738
  if( libbfio_file_set_name_wide(
739
       file_io_handle,
740
       filename,
741
       filename_length + 1,
742
       error ) != 1 )
743
  {
744
    libcerror_error_set(
745
     error,
746
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
747
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
748
     "%s: unable to set name in file IO handle.",
749
     function );
750
751
    goto on_error;
752
  }
753
  if( libvmdk_handle_open_file_io_handle(
754
       handle,
755
       file_io_handle,
756
       access_flags,
757
       error ) != 1 )
758
  {
759
    libcerror_error_set(
760
     error,
761
     LIBCERROR_ERROR_DOMAIN_IO,
762
     LIBCERROR_IO_ERROR_OPEN_FAILED,
763
     "%s: unable to open handle using a file IO handle.",
764
     function );
765
766
    goto on_error;
767
  }
768
  if( libbfio_handle_free(
769
       &file_io_handle,
770
       error ) != 1 )
771
  {
772
    libcerror_error_set(
773
     error,
774
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
775
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
776
     "%s: unable to free file IO handle.",
777
     function );
778
779
    goto on_error;
780
  }
781
  /* Note that extent file names can be renamed hence for a single monolithic sparse
782
   * or stream optimized image the filename instead of the extent data filename in
783
   * the descriptor file is used.
784
   */
785
/* TODO thread lock */
786
  if( ( internal_handle->disk_type == LIBVMDK_DISK_TYPE_MONOLITHIC_SPARSE )
787
   || ( internal_handle->disk_type == LIBVMDK_DISK_TYPE_STREAM_OPTIMIZED ) )
788
  {
789
    if( libcdata_array_get_number_of_entries(
790
         internal_handle->extent_values_array,
791
         &number_of_extents,
792
         error ) != 1 )
793
    {
794
      libcerror_error_set(
795
       error,
796
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
797
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
798
       "%s: unable to retrieve number of extents.",
799
       function );
800
801
      goto on_error;
802
    }
803
    if( number_of_extents == 1 )
804
    {
805
      if( libcdata_array_get_entry_by_index(
806
           internal_handle->extent_values_array,
807
           0,
808
           (intptr_t **) &extent_values,
809
           error ) != 1 )
810
      {
811
        libcerror_error_set(
812
         error,
813
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
814
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
815
         "%s: unable to retrieve extent values: 0 from array.",
816
         function );
817
818
        goto on_error;
819
      }
820
      if( extent_values == NULL )
821
      { 
822
        libcerror_error_set(
823
         error,
824
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
825
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
826
         "%s: missing extent values: 0.",
827
         function );
828
829
        goto on_error;
830
      }
831
      if( extent_values->type == LIBVMDK_EXTENT_TYPE_SPARSE )
832
      {
833
        if( libvmdk_extent_values_set_alternate_filename_wide(
834
             extent_values,
835
             filename,
836
             filename_length,
837
             error ) != 1 )
838
        {
839
          libcerror_error_set(
840
           error,
841
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
842
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
843
           "%s: unable to set alternate filename in extent values.",
844
           function );
845
846
          goto on_error;
847
        }
848
#if defined( HAVE_DEBUG_OUTPUT )
849
        if( libcnotify_verbose != 0 )
850
        {
851
          libcnotify_printf(
852
           "%s: alternate filename\t\t\t\t\t: %" PRIs_SYSTEM "\n",
853
           function,
854
           extent_values->alternate_filename );
855
        }
856
#endif
857
      }
858
    }
859
  }
860
  data_files_path_end = wide_string_search_character_reverse(
861
                         filename,
862
                         (wint_t) LIBCPATH_SEPARATOR,
863
                         filename_length + 1 );
864
865
  if( data_files_path_end != NULL )
866
  {
867
    data_files_path_length = (size_t) ( data_files_path_end - filename ) + 1;
868
  }
869
  if( data_files_path_length > 0 )
870
  {
871
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
872
    if( libcthreads_read_write_lock_grab_for_write(
873
         internal_handle->read_write_lock,
874
         error ) != 1 )
875
    {
876
      libcerror_error_set(
877
       error,
878
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
879
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
880
       "%s: unable to grab read/write lock for writing.",
881
       function );
882
883
      return( -1 );
884
    }
885
#endif
886
    if( libvmdk_extent_table_set_data_files_path_wide(
887
         internal_handle->extent_table,
888
         filename,
889
         data_files_path_length,
890
         error ) != 1 )
891
    {
892
      libcerror_error_set(
893
       error,
894
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
895
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
896
       "%s: unable to set data files path in extent table.",
897
       function );
898
899
      result = -1;
900
    }
901
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
902
    if( libcthreads_read_write_lock_release_for_write(
903
         internal_handle->read_write_lock,
904
         error ) != 1 )
905
    {
906
      libcerror_error_set(
907
       error,
908
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
909
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
910
       "%s: unable to release read/write lock for writing.",
911
       function );
912
913
      return( -1 );
914
    }
915
#endif
916
  }
917
  return( result );
918
919
on_error:
920
  if( file_io_handle != NULL )
921
  {
922
    libbfio_handle_free(
923
     &file_io_handle,
924
     NULL );
925
  }
926
  return( -1 );
927
}
928
929
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
930
931
/* Opens a set of VMDK file(s) using a Basic File IO (bfio) handle
932
 * Returns 1 if successful or -1 on error
933
 */
934
int libvmdk_handle_open_file_io_handle(
935
     libvmdk_handle_t *handle,
936
     libbfio_handle_t *file_io_handle,
937
     int access_flags,
938
     libcerror_error_t **error )
939
7.28k
{
940
7.28k
  libvmdk_internal_handle_t *internal_handle = NULL;
941
7.28k
  static char *function                      = "libvmdk_handle_open_file_io_handle";
942
7.28k
  uint8_t file_io_handle_opened_in_library   = 0;
943
7.28k
  int bfio_access_flags                      = 0;
944
7.28k
  int file_io_handle_is_open                 = 0;
945
7.28k
  int result                                 = 1;
946
947
7.28k
  if( handle == NULL )
948
0
  {
949
0
    libcerror_error_set(
950
0
     error,
951
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
952
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
953
0
     "%s: invalid handle.",
954
0
     function );
955
956
0
    return( -1 );
957
0
  }
958
7.28k
  internal_handle = (libvmdk_internal_handle_t *) handle;
959
960
7.28k
  if( internal_handle->descriptor_file != NULL )
961
0
  {
962
0
    libcerror_error_set(
963
0
     error,
964
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
965
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
966
0
     "%s: invalid handle - descriptor file already set.",
967
0
     function );
968
969
0
    return( -1 );
970
0
  }
971
7.28k
  if( internal_handle->io_handle == NULL )
972
0
  {
973
0
    libcerror_error_set(
974
0
     error,
975
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
976
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
977
0
     "%s: invalid handle - missing IO handle.",
978
0
     function );
979
980
0
    return( -1 );
981
0
  }
982
7.28k
  if( file_io_handle == NULL )
983
0
  {
984
0
    libcerror_error_set(
985
0
     error,
986
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
987
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
988
0
     "%s: invalid file IO handle.",
989
0
     function );
990
991
0
    return( -1 );
992
0
  }
993
7.28k
  if( ( ( access_flags & LIBVMDK_ACCESS_FLAG_READ ) == 0 )
994
0
   && ( ( access_flags & LIBVMDK_ACCESS_FLAG_WRITE ) == 0 ) )
995
0
  {
996
0
    libcerror_error_set(
997
0
     error,
998
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
999
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1000
0
     "%s: unsupported access flags.",
1001
0
     function );
1002
1003
0
    return( -1 );
1004
0
  }
1005
7.28k
  if( ( access_flags & LIBVMDK_ACCESS_FLAG_WRITE ) != 0 )
1006
0
  {
1007
0
    libcerror_error_set(
1008
0
     error,
1009
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1010
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1011
0
     "%s: write access currently not supported.",
1012
0
     function );
1013
1014
0
    return( -1 );
1015
0
  }
1016
7.28k
  if( ( access_flags & LIBVMDK_ACCESS_FLAG_READ ) != 0 )
1017
7.28k
  {
1018
7.28k
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
1019
7.28k
  }
1020
7.28k
  file_io_handle_is_open = libbfio_handle_is_open(
1021
7.28k
                            file_io_handle,
1022
7.28k
                            error );
1023
1024
7.28k
  if( file_io_handle_is_open == -1 )
1025
0
  {
1026
0
    libcerror_error_set(
1027
0
     error,
1028
0
     LIBCERROR_ERROR_DOMAIN_IO,
1029
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
1030
0
     "%s: unable to open file.",
1031
0
     function );
1032
1033
0
    goto on_error;
1034
0
  }
1035
7.28k
  else if( file_io_handle_is_open == 0 )
1036
7.28k
  {
1037
7.28k
    if( libbfio_handle_open(
1038
7.28k
         file_io_handle,
1039
7.28k
         bfio_access_flags,
1040
7.28k
         error ) != 1 )
1041
0
    {
1042
0
      libcerror_error_set(
1043
0
       error,
1044
0
       LIBCERROR_ERROR_DOMAIN_IO,
1045
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
1046
0
       "%s: unable to open file IO handle.",
1047
0
       function );
1048
1049
0
      goto on_error;
1050
0
    }
1051
7.28k
    file_io_handle_opened_in_library = 1;
1052
7.28k
  }
1053
7.28k
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
1054
7.28k
  if( libcthreads_read_write_lock_grab_for_write(
1055
7.28k
       internal_handle->read_write_lock,
1056
7.28k
       error ) != 1 )
1057
0
  {
1058
0
    libcerror_error_set(
1059
0
     error,
1060
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1061
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1062
0
     "%s: unable to grab read/write lock for writing.",
1063
0
     function );
1064
1065
0
    goto on_error;
1066
0
  }
1067
7.28k
#endif
1068
7.28k
  if( libvmdk_internal_handle_open_read(
1069
7.28k
       internal_handle,
1070
7.28k
       file_io_handle,
1071
7.28k
       error ) != 1 )
1072
6.75k
  {
1073
6.75k
    libcerror_error_set(
1074
6.75k
     error,
1075
6.75k
     LIBCERROR_ERROR_DOMAIN_IO,
1076
6.75k
     LIBCERROR_IO_ERROR_READ_FAILED,
1077
6.75k
     "%s: unable to read from file IO handle.",
1078
6.75k
     function );
1079
1080
6.75k
    result = -1;
1081
6.75k
  }
1082
531
  else
1083
531
  {
1084
531
    internal_handle->access_flags = access_flags;
1085
531
  }
1086
7.28k
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
1087
7.28k
  if( libcthreads_read_write_lock_release_for_write(
1088
7.28k
       internal_handle->read_write_lock,
1089
7.28k
       error ) != 1 )
1090
0
  {
1091
0
    libcerror_error_set(
1092
0
     error,
1093
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1094
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1095
0
     "%s: unable to release read/write lock for writing.",
1096
0
     function );
1097
1098
0
    return( -1 );
1099
0
  }
1100
7.28k
#endif
1101
7.28k
  if( file_io_handle_opened_in_library != 0 )
1102
7.28k
  {
1103
7.28k
    if( libbfio_handle_close(
1104
7.28k
         file_io_handle,
1105
7.28k
         error ) != 0 )
1106
0
    {
1107
0
      libcerror_error_set(
1108
0
       error,
1109
0
       LIBCERROR_ERROR_DOMAIN_IO,
1110
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
1111
0
       "%s: unable to close file IO handle.",
1112
0
       function );
1113
1114
0
      goto on_error;
1115
0
    }
1116
7.28k
    file_io_handle_opened_in_library = 0;
1117
7.28k
  }
1118
7.28k
  return( result );
1119
1120
0
on_error:
1121
0
  if( file_io_handle_opened_in_library != 0 )
1122
0
  {
1123
0
    libbfio_handle_close(
1124
0
     file_io_handle,
1125
0
     error );
1126
0
  }
1127
0
  return( -1 );
1128
7.28k
}
1129
1130
/* Opens the extent data files
1131
 * If the extent data filenames were not set explicitly this function assumes the extent data files
1132
 * are in the same location as the descriptor file
1133
 * Returns 1 if successful or -1 on error
1134
 */
1135
int libvmdk_handle_open_extent_data_files(
1136
     libvmdk_handle_t *handle,
1137
     libcerror_error_t **error )
1138
0
{
1139
0
  libbfio_pool_t *file_io_pool                  = NULL;
1140
0
  libvmdk_extent_values_t *extent_values        = NULL;
1141
0
  libvmdk_internal_handle_t *internal_handle    = NULL;
1142
0
  system_character_t *extent_data_file_location = NULL;
1143
0
  system_character_t *extent_data_file_path     = NULL;
1144
0
  static char *function                         = "libvmdk_handle_open_extent_data_files";
1145
0
  size_t extent_data_file_location_size         = 0;
1146
0
  int extent_index                              = 0;
1147
0
  int number_of_extents                         = 0;
1148
0
  int result                                    = 0;
1149
1150
0
  if( handle == NULL )
1151
0
  {
1152
0
    libcerror_error_set(
1153
0
     error,
1154
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1155
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1156
0
     "%s: invalid handle.",
1157
0
     function );
1158
1159
0
    return( -1 );
1160
0
  }
1161
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
1162
1163
0
  if( ( ( internal_handle->access_flags & LIBVMDK_ACCESS_FLAG_READ ) == 0 )
1164
0
   && ( ( internal_handle->access_flags & LIBVMDK_ACCESS_FLAG_WRITE ) == 0 ) )
1165
0
  {
1166
0
    libcerror_error_set(
1167
0
     error,
1168
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1169
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1170
0
     "%s: unsupported access flags.",
1171
0
     function );
1172
1173
0
    return( -1 );
1174
0
  }
1175
0
  if( ( internal_handle->access_flags & LIBVMDK_ACCESS_FLAG_WRITE ) != 0 )
1176
0
  {
1177
0
    libcerror_error_set(
1178
0
     error,
1179
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1180
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1181
0
     "%s: write access currently not supported.",
1182
0
     function );
1183
1184
0
    return( -1 );
1185
0
  }
1186
0
  if( internal_handle->descriptor_file == NULL )
1187
0
  {
1188
0
    libcerror_error_set(
1189
0
     error,
1190
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1191
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1192
0
     "%s: invalid handle - missing descriptor file.",
1193
0
     function );
1194
1195
0
    return( -1 );
1196
0
  }
1197
0
  if( internal_handle->extent_data_file_io_pool != NULL )
1198
0
  {
1199
0
    libcerror_error_set(
1200
0
     error,
1201
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1202
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1203
0
     "%s: invalid handle - extent data file IO pool already exists.",
1204
0
     function );
1205
1206
0
    return( -1 );
1207
0
  }
1208
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
1209
0
  if( libcthreads_read_write_lock_grab_for_write(
1210
0
       internal_handle->read_write_lock,
1211
0
       error ) != 1 )
1212
0
  {
1213
0
    libcerror_error_set(
1214
0
     error,
1215
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1216
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1217
0
     "%s: unable to grab read/write lock for writing.",
1218
0
     function );
1219
1220
0
    return( -1 );
1221
0
  }
1222
0
#endif
1223
0
  if( libcdata_array_get_number_of_entries(
1224
0
       internal_handle->extent_values_array,
1225
0
       &number_of_extents,
1226
0
       error ) != 1 )
1227
0
  {
1228
0
    libcerror_error_set(
1229
0
     error,
1230
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1231
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1232
0
     "%s: unable to retrieve number of extents.",
1233
0
     function );
1234
1235
0
    goto on_error;
1236
0
  }
1237
0
  if( number_of_extents == 0 )
1238
0
  {
1239
0
    libcerror_error_set(
1240
0
     error,
1241
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1242
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1243
0
     "%s: invalid number of extents value out of bounds.",
1244
0
     function );
1245
1246
0
    return( -1 );
1247
0
  }
1248
0
  if( libbfio_pool_initialize(
1249
0
       &file_io_pool,
1250
0
       number_of_extents,
1251
0
       internal_handle->maximum_number_of_open_handles,
1252
0
       error ) != 1 )
1253
0
  {
1254
0
    libcerror_error_set(
1255
0
     error,
1256
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1257
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1258
0
     "%s: unable to create file IO pool.",
1259
0
     function );
1260
1261
0
    goto on_error;
1262
0
  }
1263
0
  for( extent_index = 0;
1264
0
       extent_index < number_of_extents;
1265
0
       extent_index++ )
1266
0
  {
1267
0
    if( libcdata_array_get_entry_by_index(
1268
0
         internal_handle->extent_values_array,
1269
0
         extent_index,
1270
0
         (intptr_t **) &extent_values,
1271
0
         error ) != 1 )
1272
0
    {
1273
0
      libcerror_error_set(
1274
0
       error,
1275
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1276
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1277
0
       "%s: unable to retrieve extent values: %d from array.",
1278
0
       function,
1279
0
       extent_index );
1280
1281
0
      goto on_error;
1282
0
    }
1283
0
    if( extent_values == NULL )
1284
0
    {
1285
0
      libcerror_error_set(
1286
0
       error,
1287
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1288
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1289
0
       "%s: missing extent values: %d.",
1290
0
       function,
1291
0
       extent_index );
1292
1293
0
      goto on_error;
1294
0
    }
1295
0
    if( extent_values->type != LIBVMDK_EXTENT_TYPE_ZERO )
1296
0
    {
1297
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
1298
      result = libvmdk_extent_table_get_extent_data_file_path_wide(
1299
                internal_handle->extent_table,
1300
                extent_values,
1301
                &extent_data_file_location,
1302
                &extent_data_file_location_size,
1303
                error );
1304
#else
1305
0
      result = libvmdk_extent_table_get_extent_data_file_path(
1306
0
                internal_handle->extent_table,
1307
0
                extent_values,
1308
0
                &extent_data_file_location,
1309
0
                &extent_data_file_location_size,
1310
0
                error );
1311
0
#endif
1312
0
      if( result != 1 )
1313
0
      {
1314
0
        libcerror_error_set(
1315
0
         error,
1316
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1317
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1318
0
         "%s: unable to create extent data file location.",
1319
0
         function );
1320
1321
0
        goto on_error;
1322
0
      }
1323
0
      extent_data_file_path = extent_data_file_location;
1324
1325
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
1326
      result = libcfile_file_exists_wide(
1327
                extent_data_file_path,
1328
                error );
1329
#else
1330
0
      result = libcfile_file_exists(
1331
0
                extent_data_file_path,
1332
0
                error );
1333
0
#endif
1334
0
      if( result == -1 )
1335
0
      {
1336
0
        libcerror_error_set(
1337
0
         error,
1338
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1339
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1340
0
         "%s: unable to determine if extent: %d data file exists.",
1341
0
         function,
1342
0
         extent_index );
1343
1344
0
        goto on_error;
1345
0
      }
1346
0
      else if( ( result == 0 )
1347
0
            && ( extent_values->alternate_filename != NULL ) )
1348
0
      {
1349
0
        memory_free(
1350
0
         extent_data_file_location );
1351
1352
0
        extent_data_file_location      = NULL;
1353
0
        extent_data_file_location_size = 0;
1354
1355
0
        extent_data_file_path = extent_values->alternate_filename;
1356
0
      }
1357
      /* Note that the open extent data file function will initialize extent_data_file_io_pool
1358
       */
1359
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
1360
      result = libvmdk_handle_open_extent_data_file_wide(
1361
          internal_handle,
1362
          file_io_pool,
1363
          extent_index,
1364
          extent_data_file_path,
1365
          error );
1366
#else
1367
0
      result = libvmdk_handle_open_extent_data_file(
1368
0
          internal_handle,
1369
0
          file_io_pool,
1370
0
          extent_index,
1371
0
          extent_data_file_path,
1372
0
          error );
1373
0
#endif
1374
0
      if( result != 1 )
1375
0
      {
1376
0
        libcerror_error_set(
1377
0
         error,
1378
0
         LIBCERROR_ERROR_DOMAIN_IO,
1379
0
         LIBCERROR_IO_ERROR_OPEN_FAILED,
1380
0
         "%s: unable to open extent data file: %" PRIs_SYSTEM ".",
1381
0
         function,
1382
0
         extent_data_file_path );
1383
1384
0
        goto on_error;
1385
0
      }
1386
0
      if( extent_data_file_location != NULL )
1387
0
      {
1388
0
        memory_free(
1389
0
         extent_data_file_location );
1390
1391
0
        extent_data_file_location = NULL;
1392
0
      }
1393
0
    }
1394
0
  }
1395
0
  if( libvmdk_internal_handle_open_read_extent_data_files(
1396
0
       internal_handle,
1397
0
       file_io_pool,
1398
0
       error ) != 1 )
1399
0
  {
1400
0
                libcerror_error_set(
1401
0
                 error,
1402
0
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1403
0
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1404
0
                 "%s: unable to read extent data files.",
1405
0
                 function );
1406
1407
0
                goto on_error;
1408
0
  }
1409
0
  internal_handle->extent_data_file_io_pool                    = file_io_pool;
1410
0
  internal_handle->extent_data_file_io_pool_created_in_library = 1;
1411
1412
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
1413
0
  if( libcthreads_read_write_lock_release_for_write(
1414
0
       internal_handle->read_write_lock,
1415
0
       error ) != 1 )
1416
0
  {
1417
0
    libcerror_error_set(
1418
0
     error,
1419
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1420
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1421
0
     "%s: unable to release read/write lock for writing.",
1422
0
     function );
1423
1424
0
    return( -1 );
1425
0
  }
1426
0
#endif
1427
0
  return( 1 );
1428
1429
0
on_error:
1430
0
  if( file_io_pool != NULL )
1431
0
  {
1432
0
    libbfio_pool_close_all(
1433
0
     file_io_pool,
1434
0
     NULL );
1435
0
    libbfio_pool_free(
1436
0
     &file_io_pool,
1437
0
     NULL );
1438
0
  }
1439
0
  if( extent_data_file_location != NULL )
1440
0
  {
1441
0
    memory_free(
1442
0
     extent_data_file_location );
1443
0
  }
1444
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
1445
0
  libcthreads_read_write_lock_release_for_write(
1446
0
   internal_handle->read_write_lock,
1447
0
   NULL );
1448
0
#endif
1449
0
  return( -1 );
1450
0
}
1451
1452
/* Opens the extent data files using a Basic File IO (bfio) pool
1453
 * This function assumes the extent data files are in same order as defined by the descriptor file
1454
 * Returns 1 if successful or -1 on error
1455
 */
1456
int libvmdk_handle_open_extent_data_files_file_io_pool(
1457
     libvmdk_handle_t *handle,
1458
     libbfio_pool_t *file_io_pool,
1459
     libcerror_error_t **error )
1460
0
{
1461
0
  libvmdk_internal_handle_t *internal_handle = NULL;
1462
0
  static char *function                      = "libvmdk_handle_open_extent_data_files_file_io_pool";
1463
0
  int result                                 = 1;
1464
1465
0
  if( handle == NULL )
1466
0
  {
1467
0
    libcerror_error_set(
1468
0
     error,
1469
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1470
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1471
0
     "%s: invalid handle.",
1472
0
     function );
1473
1474
0
    return( -1 );
1475
0
  }
1476
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
1477
1478
0
  if( ( ( internal_handle->access_flags & LIBVMDK_ACCESS_FLAG_READ ) == 0 )
1479
0
   && ( ( internal_handle->access_flags & LIBVMDK_ACCESS_FLAG_WRITE ) == 0 ) )
1480
0
  {
1481
0
    libcerror_error_set(
1482
0
     error,
1483
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1484
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1485
0
     "%s: unsupported access flags.",
1486
0
     function );
1487
1488
0
    return( -1 );
1489
0
  }
1490
0
  if( ( internal_handle->access_flags & LIBVMDK_ACCESS_FLAG_WRITE ) != 0 )
1491
0
  {
1492
0
    libcerror_error_set(
1493
0
     error,
1494
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1495
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1496
0
     "%s: write access currently not supported.",
1497
0
     function );
1498
1499
0
    return( -1 );
1500
0
  }
1501
0
  if( internal_handle->descriptor_file == NULL )
1502
0
  {
1503
0
    libcerror_error_set(
1504
0
     error,
1505
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1506
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1507
0
     "%s: invalid handle - missing descriptor file.",
1508
0
     function );
1509
1510
0
    return( -1 );
1511
0
  }
1512
0
  if( internal_handle->extent_data_file_io_pool != NULL )
1513
0
  {
1514
0
    libcerror_error_set(
1515
0
     error,
1516
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1517
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1518
0
     "%s: invalid handle - extent data file IO pool already exists.",
1519
0
     function );
1520
1521
0
    return( -1 );
1522
0
  }
1523
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
1524
0
  if( libcthreads_read_write_lock_grab_for_write(
1525
0
       internal_handle->read_write_lock,
1526
0
       error ) != 1 )
1527
0
  {
1528
0
    libcerror_error_set(
1529
0
     error,
1530
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1531
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1532
0
     "%s: unable to grab read/write lock for writing.",
1533
0
     function );
1534
1535
0
    return( -1 );
1536
0
  }
1537
0
#endif
1538
0
  if( libvmdk_internal_handle_open_read_extent_data_files(
1539
0
       internal_handle,
1540
0
       file_io_pool,
1541
0
       error ) != 1 )
1542
0
  {
1543
0
                libcerror_error_set(
1544
0
                 error,
1545
0
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1546
0
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1547
0
                 "%s: unable to read extent data files.",
1548
0
                 function );
1549
1550
0
                result = -1;
1551
0
  }
1552
0
  else
1553
0
  {
1554
0
    internal_handle->extent_data_file_io_pool = file_io_pool;
1555
0
  }
1556
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
1557
0
  if( libcthreads_read_write_lock_release_for_write(
1558
0
       internal_handle->read_write_lock,
1559
0
       error ) != 1 )
1560
0
  {
1561
0
    libcerror_error_set(
1562
0
     error,
1563
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1564
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1565
0
     "%s: unable to release read/write lock for writing.",
1566
0
     function );
1567
1568
0
    return( -1 );
1569
0
  }
1570
0
#endif
1571
0
  return( result );
1572
0
}
1573
1574
/* Opens a specific extent data file
1575
 * Returns 1 if successful or -1 on error
1576
 */
1577
int libvmdk_handle_open_extent_data_file(
1578
     libvmdk_internal_handle_t *internal_handle,
1579
     libbfio_pool_t *file_io_pool,
1580
     int extent_index,
1581
     const char *filename,
1582
     libcerror_error_t **error )
1583
0
{
1584
0
  libbfio_handle_t *file_io_handle = NULL;
1585
0
  static char *function            = "libvmdk_handle_open_extent_data_file";
1586
0
  size_t filename_length           = 0;
1587
0
  int bfio_access_flags            = 0;
1588
1589
0
  if( internal_handle == NULL )
1590
0
  {
1591
0
    libcerror_error_set(
1592
0
     error,
1593
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1594
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1595
0
     "%s: invalid handle.",
1596
0
     function );
1597
1598
0
    return( -1 );
1599
0
  }
1600
0
  if( filename == NULL )
1601
0
  {
1602
0
    libcerror_error_set(
1603
0
     error,
1604
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1605
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1606
0
     "%s: invalid filename.",
1607
0
     function );
1608
1609
0
    return( -1 );
1610
0
  }
1611
0
  if( ( internal_handle->access_flags & LIBVMDK_ACCESS_FLAG_READ ) != 0 )
1612
0
  {
1613
0
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
1614
0
  }
1615
0
  if( libbfio_file_initialize(
1616
0
       &file_io_handle,
1617
0
       error ) != 1 )
1618
0
  {
1619
0
    libcerror_error_set(
1620
0
     error,
1621
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1622
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1623
0
     "%s: unable to create file IO handle.",
1624
0
     function );
1625
1626
0
    goto on_error;
1627
0
  }
1628
#if defined( HAVE_DEBUG_OUTPUT )
1629
  if( libbfio_handle_set_track_offsets_read(
1630
       file_io_handle,
1631
       1,
1632
       error ) != 1 )
1633
  {
1634
                libcerror_error_set(
1635
                 error,
1636
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1637
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1638
                 "%s: unable to set track offsets read in file IO handle.",
1639
                 function );
1640
1641
                goto on_error;
1642
  }
1643
#endif
1644
0
  filename_length = narrow_string_length(
1645
0
                     filename );
1646
1647
0
  if( libbfio_file_set_name(
1648
0
       file_io_handle,
1649
0
       filename,
1650
0
       filename_length + 1,
1651
0
       error ) != 1 )
1652
0
  {
1653
0
                libcerror_error_set(
1654
0
                 error,
1655
0
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1656
0
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1657
0
                 "%s: unable to set filename in file IO handle.",
1658
0
                 function );
1659
1660
0
                goto on_error;
1661
0
  }
1662
0
  if( libbfio_handle_open(
1663
0
       file_io_handle,
1664
0
       bfio_access_flags,
1665
0
       error ) != 1 )
1666
0
  {
1667
0
    libcerror_error_set(
1668
0
     error,
1669
0
     LIBCERROR_ERROR_DOMAIN_IO,
1670
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
1671
0
     "%s: unable to open file IO handle.",
1672
0
     function );
1673
1674
0
    goto on_error;
1675
0
  }
1676
0
  if( libbfio_pool_set_handle(
1677
0
       file_io_pool,
1678
0
       extent_index,
1679
0
       file_io_handle,
1680
0
       bfio_access_flags,
1681
0
       error ) != 1 )
1682
0
  {
1683
0
    libcerror_error_set(
1684
0
     error,
1685
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1686
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1687
0
     "%s: unable to set file IO handle: %d in pool.",
1688
0
     function,
1689
0
     extent_index );
1690
1691
0
    goto on_error;
1692
0
  }
1693
0
  return( 1 );
1694
1695
0
on_error:
1696
0
  if( file_io_handle != NULL )
1697
0
  {
1698
0
    libbfio_handle_free(
1699
0
     &file_io_handle,
1700
0
     NULL );
1701
0
  }
1702
0
  return( -1 );
1703
0
}
1704
1705
#if defined( HAVE_WIDE_CHARACTER_TYPE )
1706
1707
/* Opens a specific extent data file
1708
 * Returns 1 if successful or -1 on error
1709
 */
1710
int libvmdk_handle_open_extent_data_file_wide(
1711
     libvmdk_internal_handle_t *internal_handle,
1712
     libbfio_pool_t *file_io_pool,
1713
     int extent_index,
1714
     const wchar_t *filename,
1715
     libcerror_error_t **error )
1716
{
1717
  libbfio_handle_t *file_io_handle = NULL;
1718
  static char *function            = "libvmdk_handle_open_extent_data_file_wide";
1719
  size_t filename_length           = 0;
1720
  int bfio_access_flags            = 0;
1721
1722
  if( internal_handle == NULL )
1723
  {
1724
    libcerror_error_set(
1725
     error,
1726
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1727
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1728
     "%s: invalid handle.",
1729
     function );
1730
1731
    return( -1 );
1732
  }
1733
  if( filename == NULL )
1734
  {
1735
    libcerror_error_set(
1736
     error,
1737
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1738
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1739
     "%s: invalid filename.",
1740
     function );
1741
1742
    return( -1 );
1743
  }
1744
  if( ( internal_handle->access_flags & LIBVMDK_ACCESS_FLAG_READ ) != 0 )
1745
  {
1746
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
1747
  }
1748
  if( libbfio_file_initialize(
1749
       &file_io_handle,
1750
       error ) != 1 )
1751
  {
1752
    libcerror_error_set(
1753
     error,
1754
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1755
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1756
     "%s: unable to create file IO handle.",
1757
     function );
1758
1759
                goto on_error;
1760
  }
1761
#if defined( HAVE_DEBUG_OUTPUT )
1762
  if( libbfio_handle_set_track_offsets_read(
1763
       file_io_handle,
1764
       1,
1765
       error ) != 1 )
1766
  {
1767
                libcerror_error_set(
1768
                 error,
1769
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1770
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1771
                 "%s: unable to set track offsets read in file IO handle.",
1772
                 function );
1773
1774
                goto on_error;
1775
  }
1776
#endif
1777
  filename_length = wide_string_length(
1778
                     filename );
1779
1780
  if( libbfio_file_set_name_wide(
1781
       file_io_handle,
1782
       filename,
1783
       filename_length + 1,
1784
       error ) != 1 )
1785
  {
1786
                libcerror_error_set(
1787
                 error,
1788
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1789
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1790
                 "%s: unable to set filename in file IO handle.",
1791
                 function );
1792
1793
                goto on_error;
1794
  }
1795
  if( libbfio_handle_open(
1796
       file_io_handle,
1797
       bfio_access_flags,
1798
       error ) != 1 )
1799
  {
1800
    libcerror_error_set(
1801
     error,
1802
     LIBCERROR_ERROR_DOMAIN_IO,
1803
     LIBCERROR_IO_ERROR_OPEN_FAILED,
1804
     "%s: unable to open file IO handle.",
1805
     function );
1806
1807
    goto on_error;
1808
  }
1809
  if( libbfio_pool_set_handle(
1810
       file_io_pool,
1811
       extent_index,
1812
       file_io_handle,
1813
       bfio_access_flags,
1814
       error ) != 1 )
1815
  {
1816
    libcerror_error_set(
1817
     error,
1818
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1819
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1820
     "%s: unable to set file IO handle: %d in pool.",
1821
     function,
1822
     extent_index );
1823
1824
    goto on_error;
1825
  }
1826
  return( 1 );
1827
1828
on_error:
1829
  if( file_io_handle != NULL )
1830
  {
1831
    libbfio_handle_free(
1832
     &file_io_handle,
1833
     NULL );
1834
  }
1835
  return( -1 );
1836
}
1837
1838
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
1839
1840
/* Closes the VMDK file(s)
1841
 * Returns 0 if successful or -1 on error
1842
 */
1843
int libvmdk_handle_close(
1844
     libvmdk_handle_t *handle,
1845
     libcerror_error_t **error )
1846
531
{
1847
531
  libvmdk_internal_handle_t *internal_handle = NULL;
1848
531
  static char *function                      = "libvmdk_handle_close";
1849
531
  int result                                 = 0;
1850
1851
531
  if( handle == NULL )
1852
0
  {
1853
0
    libcerror_error_set(
1854
0
     error,
1855
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1856
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1857
0
     "%s: invalid handle.",
1858
0
     function );
1859
1860
0
    return( -1 );
1861
0
  }
1862
531
  internal_handle = (libvmdk_internal_handle_t *) handle;
1863
1864
531
  if( internal_handle->descriptor_file == NULL )
1865
0
  {
1866
0
    libcerror_error_set(
1867
0
     error,
1868
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1869
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1870
0
     "%s: invalid file - missing descriptor file.",
1871
0
     function );
1872
1873
0
    return( -1 );
1874
0
  }
1875
531
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
1876
531
  if( libcthreads_read_write_lock_grab_for_write(
1877
531
       internal_handle->read_write_lock,
1878
531
       error ) != 1 )
1879
0
  {
1880
0
    libcerror_error_set(
1881
0
     error,
1882
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1883
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1884
0
     "%s: unable to grab read/write lock for writing.",
1885
0
     function );
1886
1887
0
    return( -1 );
1888
0
  }
1889
531
#endif
1890
531
  if( internal_handle->extent_data_file_io_pool_created_in_library != 0 )
1891
0
  {
1892
0
    if( libbfio_pool_close_all(
1893
0
         internal_handle->extent_data_file_io_pool,
1894
0
         error ) != 0 )
1895
0
    {
1896
0
      libcerror_error_set(
1897
0
       error,
1898
0
       LIBCERROR_ERROR_DOMAIN_IO,
1899
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
1900
0
       "%s: unable to close all files in extent data file IO pool.",
1901
0
       function );
1902
1903
0
      result = -1;
1904
0
    }
1905
0
    if( libbfio_pool_free(
1906
0
         &( internal_handle->extent_data_file_io_pool ),
1907
0
         error ) != 1 )
1908
0
    {
1909
0
      libcerror_error_set(
1910
0
       error,
1911
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1912
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1913
0
       "%s: unable to free extent data file IO pool.",
1914
0
       function );
1915
1916
0
      result = -1;
1917
0
    }
1918
0
    internal_handle->extent_data_file_io_pool_created_in_library = 0;
1919
0
  }
1920
531
  internal_handle->extent_data_file_io_pool = NULL;
1921
531
  internal_handle->current_offset           = 0;
1922
1923
531
  if( libvmdk_io_handle_clear(
1924
531
       internal_handle->io_handle,
1925
531
       error ) != 1 )
1926
0
  {
1927
0
    libcerror_error_set(
1928
0
     error,
1929
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1930
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1931
0
     "%s: unable to clear IO handle.",
1932
0
     function );
1933
1934
0
    result = -1;
1935
0
  }
1936
531
  if( internal_handle->descriptor_file != NULL )
1937
531
  {
1938
531
    if( libvmdk_descriptor_file_free(
1939
531
         &( internal_handle->descriptor_file ),
1940
531
         error ) != 1 )
1941
0
    {
1942
0
      libcerror_error_set(
1943
0
       error,
1944
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1945
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1946
0
       "%s: unable to free descriptor file.",
1947
0
       function );
1948
1949
0
      result = -1;
1950
0
    }
1951
531
  }
1952
531
  if( internal_handle->grain_table != NULL )
1953
0
  {
1954
0
    if( libvmdk_grain_table_free(
1955
0
         &( internal_handle->grain_table ),
1956
0
         error ) != 1 )
1957
0
    {
1958
0
      libcerror_error_set(
1959
0
       error,
1960
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1961
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1962
0
       "%s: unable to free grain table.",
1963
0
       function );
1964
1965
0
      result = -1;
1966
0
    }
1967
0
  }
1968
531
  if( internal_handle->grains_cache != NULL )
1969
0
  {
1970
0
    if( libfcache_cache_free(
1971
0
         &( internal_handle->grains_cache ),
1972
0
         error ) != 1 )
1973
0
    {
1974
0
      libcerror_error_set(
1975
0
       error,
1976
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1977
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1978
0
       "%s: unable to free grains cache.",
1979
0
       function );
1980
1981
0
      result = -1;
1982
0
    }
1983
0
  }
1984
531
  if( libvmdk_extent_table_clear(
1985
531
       internal_handle->extent_table,
1986
531
       error ) != 1 )
1987
0
  {
1988
0
    libcerror_error_set(
1989
0
     error,
1990
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1991
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1992
0
     "%s: unable to clear extent table.",
1993
0
     function );
1994
1995
0
    result = -1;
1996
0
  }
1997
531
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
1998
531
  if( libcthreads_read_write_lock_release_for_write(
1999
531
       internal_handle->read_write_lock,
2000
531
       error ) != 1 )
2001
0
  {
2002
0
    libcerror_error_set(
2003
0
     error,
2004
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2005
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2006
0
     "%s: unable to release read/write lock for writing.",
2007
0
     function );
2008
2009
0
    return( -1 );
2010
0
  }
2011
531
#endif
2012
531
  return( result );
2013
531
}
2014
2015
/* Opens a handle for reading
2016
 * Returns 1 if successful or -1 on error
2017
 */
2018
int libvmdk_internal_handle_open_read(
2019
     libvmdk_internal_handle_t *internal_handle,
2020
     libbfio_handle_t *file_io_handle,
2021
     libcerror_error_t **error )
2022
7.28k
{
2023
7.28k
  libvmdk_extent_file_t *extent_file = NULL;
2024
7.28k
  uint8_t *descriptor_data           = NULL;
2025
7.28k
  static char *function              = "libvmdk_internal_handle_open_read";
2026
7.28k
  uint8_t file_type                  = 0;
2027
7.28k
  int result                         = 0;
2028
2029
7.28k
  if( internal_handle == NULL )
2030
0
  {
2031
0
    libcerror_error_set(
2032
0
     error,
2033
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2034
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2035
0
     "%s: invalid handle.",
2036
0
     function );
2037
2038
0
    return( -1 );
2039
0
  }
2040
7.28k
  if( internal_handle->io_handle == NULL )
2041
0
  {
2042
0
    libcerror_error_set(
2043
0
     error,
2044
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2045
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2046
0
     "%s: invalid handle - missing IO handle.",
2047
0
     function );
2048
2049
0
    return( -1 );
2050
0
  }
2051
7.28k
  if( internal_handle->descriptor_file != NULL )
2052
0
  {
2053
0
    libcerror_error_set(
2054
0
     error,
2055
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2056
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2057
0
     "%s: invalid handle - descriptor file already set.",
2058
0
     function );
2059
2060
0
    return( -1 );
2061
0
  }
2062
7.28k
  result = libvmdk_internal_handle_open_read_signature(
2063
7.28k
      file_io_handle,
2064
7.28k
      &file_type,
2065
7.28k
      error );
2066
2067
7.28k
  if( result == -1 )
2068
8
  {
2069
8
    libcerror_error_set(
2070
8
     error,
2071
8
     LIBCERROR_ERROR_DOMAIN_IO,
2072
8
     LIBCERROR_IO_ERROR_READ_FAILED,
2073
8
     "%s: unable to read signature.",
2074
8
     function );
2075
2076
8
    goto on_error;
2077
8
  }
2078
7.27k
  else if( result == 0 )
2079
255
  {
2080
255
    file_type = LIBVMDK_FILE_TYPE_RAW_DATA;
2081
255
  }
2082
7.27k
  switch( file_type )
2083
7.27k
  {
2084
6.70k
    case LIBVMDK_FILE_TYPE_DESCRIPTOR_FILE:
2085
6.70k
      if( libvmdk_descriptor_file_initialize(
2086
6.70k
           &( internal_handle->descriptor_file ),
2087
6.70k
           error ) != 1 )
2088
0
      {
2089
0
        libcerror_error_set(
2090
0
         error,
2091
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2092
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2093
0
         "%s: unable to create descriptor file.",
2094
0
         function );
2095
2096
0
        goto on_error;
2097
0
      }
2098
6.70k
      if( libvmdk_descriptor_file_read_file_io_handle(
2099
6.70k
           internal_handle->descriptor_file,
2100
6.70k
           file_io_handle,
2101
6.70k
           internal_handle->extent_values_array,
2102
6.70k
           error ) != 1 )
2103
6.17k
      {
2104
6.17k
        libcerror_error_set(
2105
6.17k
         error,
2106
6.17k
         LIBCERROR_ERROR_DOMAIN_IO,
2107
6.17k
         LIBCERROR_IO_ERROR_READ_FAILED,
2108
6.17k
         "%s: unable to read descriptor file.",
2109
6.17k
         function );
2110
2111
6.17k
        goto on_error;
2112
6.17k
      }
2113
530
      break;
2114
2115
530
    case LIBVMDK_FILE_TYPE_VMDK_SPARSE_DATA:
2116
312
      if( libvmdk_extent_file_initialize(
2117
312
           &extent_file,
2118
312
           internal_handle->io_handle,
2119
312
           error ) != 1 )
2120
0
      {
2121
0
        libcerror_error_set(
2122
0
         error,
2123
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2124
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2125
0
         "%s: unable to create extent file.",
2126
0
         function );
2127
2128
0
        goto on_error;
2129
0
      }
2130
312
      if( libvmdk_extent_file_read_file_header_file_io_handle(
2131
312
           extent_file,
2132
312
           file_io_handle,
2133
312
           0,
2134
312
           error ) != 1 )
2135
293
      {
2136
293
        libcerror_error_set(
2137
293
         error,
2138
293
         LIBCERROR_ERROR_DOMAIN_IO,
2139
293
         LIBCERROR_IO_ERROR_READ_FAILED,
2140
293
         "%s: unable to read extent file header.",
2141
293
         function );
2142
2143
293
        goto on_error;
2144
293
      }
2145
19
      if( extent_file->descriptor_size > 0 )
2146
18
      {
2147
18
        if( libvmdk_descriptor_file_initialize(
2148
18
             &( internal_handle->descriptor_file ),
2149
18
             error ) != 1 )
2150
0
        {
2151
0
          libcerror_error_set(
2152
0
           error,
2153
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2154
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2155
0
           "%s: unable to create descriptor file.",
2156
0
           function );
2157
2158
0
          goto on_error;
2159
0
        }
2160
18
        if( extent_file->descriptor_size > (size64_t) MEMORY_MAXIMUM_ALLOCATION_SIZE )
2161
1
        {
2162
1
          libcerror_error_set(
2163
1
           error,
2164
1
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2165
1
           LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
2166
1
           "%s: invalid extent file - descriptor size value exceeds maximum allocation size.",
2167
1
           function );
2168
2169
1
          goto on_error;
2170
1
        }
2171
17
        descriptor_data = (uint8_t *) memory_allocate(
2172
17
                     sizeof( uint8_t ) * (size_t) extent_file->descriptor_size );
2173
2174
17
        if( descriptor_data == NULL )
2175
0
        {
2176
0
          libcerror_error_set(
2177
0
           error,
2178
0
           LIBCERROR_ERROR_DOMAIN_MEMORY,
2179
0
           LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
2180
0
           "%s: unable to create descriptor data.",
2181
0
           function );
2182
2183
0
          goto on_error;
2184
0
        }
2185
17
        if( libvmdk_extent_file_read_descriptor_data_file_io_handle(
2186
17
             extent_file,
2187
17
             file_io_handle,
2188
17
             descriptor_data,
2189
17
             (size_t) extent_file->descriptor_size,
2190
17
             error ) != 1 )
2191
9
        {
2192
9
          libcerror_error_set(
2193
9
           error,
2194
9
           LIBCERROR_ERROR_DOMAIN_IO,
2195
9
           LIBCERROR_IO_ERROR_READ_FAILED,
2196
9
           "%s: unable to read descriptor data.",
2197
9
           function );
2198
2199
9
          goto on_error;
2200
9
        }
2201
8
        if( libvmdk_descriptor_file_read_string(
2202
8
             internal_handle->descriptor_file,
2203
8
             (char *) descriptor_data,
2204
8
             (size_t) extent_file->descriptor_size,
2205
8
             internal_handle->extent_values_array,
2206
8
             error ) != 1 )
2207
7
        {
2208
7
          libcerror_error_set(
2209
7
           error,
2210
7
           LIBCERROR_ERROR_DOMAIN_IO,
2211
7
           LIBCERROR_IO_ERROR_READ_FAILED,
2212
7
           "%s: unable to read descriptor from string.",
2213
7
           function );
2214
2215
7
          goto on_error;
2216
7
        }
2217
1
        memory_free(
2218
1
         descriptor_data );
2219
2220
1
        descriptor_data = NULL;
2221
1
      }
2222
2
      if( libvmdk_extent_file_free(
2223
2
           &extent_file,
2224
2
           error ) != 1 )
2225
0
      {
2226
0
        libcerror_error_set(
2227
0
         error,
2228
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2229
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2230
0
         "%s: unable to free extent file.",
2231
0
         function );
2232
2233
0
        goto on_error;
2234
0
      }
2235
2
      break;
2236
2237
255
    case LIBVMDK_FILE_TYPE_RAW_DATA:
2238
256
    case LIBVMDK_FILE_TYPE_COWD_SPARSE_DATA:
2239
256
    default:
2240
256
      libcerror_error_set(
2241
256
       error,
2242
256
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2243
256
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2244
256
       "%s: unsupported file type.",
2245
256
       function );
2246
2247
256
      goto on_error;
2248
7.27k
  }
2249
532
  if( libvmdk_descriptor_file_get_disk_type(
2250
532
       internal_handle->descriptor_file,
2251
532
       &( internal_handle->disk_type ),
2252
532
       error ) != 1 )
2253
1
  {
2254
1
    libcerror_error_set(
2255
1
     error,
2256
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2257
1
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2258
1
     "%s: unable to retrieve disk type.",
2259
1
     function );
2260
2261
1
    goto on_error;
2262
1
  }
2263
531
  if( libvmdk_descriptor_file_get_media_size(
2264
531
       internal_handle->descriptor_file,
2265
531
       &( internal_handle->io_handle->media_size ),
2266
531
       error ) != 1 )
2267
0
  {
2268
0
    libcerror_error_set(
2269
0
     error,
2270
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2271
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2272
0
     "%s: unable to retrieve media size.",
2273
0
     function );
2274
2275
0
    goto on_error;
2276
0
  }
2277
531
  return( 1 );
2278
2279
6.75k
on_error:
2280
6.75k
  if( descriptor_data != NULL )
2281
16
  {
2282
16
    memory_free(
2283
16
     descriptor_data );
2284
16
  }
2285
6.75k
  if( extent_file != NULL )
2286
310
  {
2287
310
    libvmdk_extent_file_free(
2288
310
     &extent_file,
2289
310
     NULL );
2290
310
  }
2291
6.75k
  if( internal_handle->descriptor_file != NULL )
2292
6.19k
  {
2293
6.19k
    libvmdk_descriptor_file_free(
2294
6.19k
     &( internal_handle->descriptor_file ),
2295
6.19k
     NULL );
2296
6.19k
  }
2297
6.75k
  return( -1 );
2298
531
}
2299
2300
/* Reads the extent data files
2301
 * Returns 1 if successful or -1 on error
2302
 */
2303
int libvmdk_internal_handle_open_read_extent_data_files(
2304
     libvmdk_internal_handle_t *internal_handle,
2305
     libbfio_pool_t *file_io_pool,
2306
     libcerror_error_t **error )
2307
0
{
2308
0
  libvmdk_extent_file_t *extent_file     = NULL;
2309
0
  libvmdk_extent_values_t *extent_values = NULL;
2310
0
  static char *function                  = "libvmdk_internal_handle_open_read_extent_data_files";
2311
0
  size64_t extent_file_size              = 0;
2312
0
  int extent_index                       = 0;
2313
0
  int number_of_extents                  = 0;
2314
0
  int number_of_file_io_handles          = 0;
2315
2316
0
  if( internal_handle == NULL )
2317
0
  {
2318
0
    libcerror_error_set(
2319
0
     error,
2320
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2321
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2322
0
     "%s: invalid handle.",
2323
0
     function );
2324
2325
0
    return( -1 );
2326
0
  }
2327
0
  if( internal_handle->io_handle == NULL )
2328
0
  {
2329
0
    libcerror_error_set(
2330
0
     error,
2331
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2332
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2333
0
     "%s: invalid handle - missing IO handle.",
2334
0
     function );
2335
2336
0
    return( -1 );
2337
0
  }
2338
0
  if( internal_handle->descriptor_file == NULL )
2339
0
  {
2340
0
    libcerror_error_set(
2341
0
     error,
2342
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2343
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2344
0
     "%s: invalid handle - missing descriptor file.",
2345
0
     function );
2346
2347
0
    return( -1 );
2348
0
  }
2349
0
  if( internal_handle->grain_table != NULL )
2350
0
  {
2351
0
    libcerror_error_set(
2352
0
     error,
2353
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2354
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2355
0
     "%s: invalid handle - grain table already set.",
2356
0
     function );
2357
2358
0
    return( -1 );
2359
0
  }
2360
0
  if( internal_handle->grains_cache != NULL )
2361
0
  {
2362
0
    libcerror_error_set(
2363
0
     error,
2364
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2365
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2366
0
     "%s: invalid handle - grains cache already set.",
2367
0
     function );
2368
2369
0
    return( -1 );
2370
0
  }
2371
0
  if( libcdata_array_get_number_of_entries(
2372
0
       internal_handle->extent_values_array,
2373
0
       &number_of_extents,
2374
0
       error ) != 1 )
2375
0
  {
2376
0
    libcerror_error_set(
2377
0
     error,
2378
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2379
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2380
0
     "%s: unable to retrieve number of extents.",
2381
0
     function );
2382
2383
0
    goto on_error;
2384
0
  }
2385
0
  if( number_of_extents == 0 )
2386
0
  {
2387
0
    libcerror_error_set(
2388
0
     error,
2389
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2390
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2391
0
     "%s: missing extents.",
2392
0
     function );
2393
2394
0
    goto on_error;
2395
0
  }
2396
0
  if( libbfio_pool_get_number_of_handles(
2397
0
       file_io_pool,
2398
0
       &number_of_file_io_handles,
2399
0
       error ) != 1 )
2400
0
  {
2401
0
    libcerror_error_set(
2402
0
     error,
2403
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2404
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2405
0
     "%s: unable to retrieve the number of file IO handles.",
2406
0
     function );
2407
2408
0
    return( -1 );
2409
0
  }
2410
0
  if( number_of_extents != number_of_file_io_handles )
2411
0
  {
2412
0
    libcerror_error_set(
2413
0
     error,
2414
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2415
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2416
0
     "%s: mismatch between number of file IO handles in pool and number of extents in metadata.",
2417
0
     function );
2418
2419
0
    goto on_error;
2420
0
  }
2421
0
  if( libvmdk_extent_table_initialize_extents(
2422
0
       internal_handle->extent_table,
2423
0
       number_of_extents,
2424
0
       internal_handle->disk_type,
2425
0
       error ) != 1 )
2426
0
  {
2427
0
    libcerror_error_set(
2428
0
     error,
2429
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2430
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2431
0
     "%s: unable to initialize extent table extents.",
2432
0
     function );
2433
2434
0
    goto on_error;
2435
0
  }
2436
0
  if( libvmdk_grain_table_initialize(
2437
0
       &( internal_handle->grain_table ),
2438
0
       internal_handle->io_handle,
2439
0
       error ) != 1 )
2440
0
  {
2441
0
    libcerror_error_set(
2442
0
     error,
2443
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2444
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2445
0
     "%s: unable to create grain table.",
2446
0
     function );
2447
2448
0
    goto on_error;
2449
0
  }
2450
0
  if( libfcache_cache_initialize(
2451
0
       &( internal_handle->grains_cache ),
2452
0
       LIBVMDK_MAXIMUM_CACHE_ENTRIES_GRAINS,
2453
0
       error ) != 1 )
2454
0
  {
2455
0
    libcerror_error_set(
2456
0
     error,
2457
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2458
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2459
0
     "%s: unable to create grains cache.",
2460
0
     function );
2461
2462
0
    goto on_error;
2463
0
  }
2464
0
  for( extent_index = 0;
2465
0
       extent_index < number_of_extents;
2466
0
       extent_index++ )
2467
0
  {
2468
0
    if( libcdata_array_get_entry_by_index(
2469
0
         internal_handle->extent_values_array,
2470
0
         extent_index,
2471
0
         (intptr_t **) &extent_values,
2472
0
         error ) != 1 )
2473
0
    {
2474
0
      libcerror_error_set(
2475
0
       error,
2476
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2477
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2478
0
       "%s: unable to retrieve extent values: %d from array.",
2479
0
       function,
2480
0
       extent_index );
2481
2482
0
      goto on_error;
2483
0
    }
2484
0
    if( libbfio_pool_get_size(
2485
0
         file_io_pool,
2486
0
         extent_index,
2487
0
         &extent_file_size,
2488
0
         error ) != 1 )
2489
0
    {
2490
0
      libcerror_error_set(
2491
0
       error,
2492
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2493
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2494
0
       "%s: unable to retrieve size of file IO pool entry: %d.",
2495
0
       function,
2496
0
       extent_index );
2497
2498
0
      goto on_error;
2499
0
    }
2500
0
    if( libvmdk_extent_table_set_extent_by_extent_values(
2501
0
         internal_handle->extent_table,
2502
0
         extent_values,
2503
0
         extent_index,
2504
0
         extent_index,
2505
0
         extent_file_size,
2506
0
         extent_values->offset,
2507
0
         extent_values->size,
2508
0
         error ) != 1 )
2509
0
    {
2510
0
      libcerror_error_set(
2511
0
       error,
2512
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2513
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2514
0
       "%s: unable to set extent: %d in table.",
2515
0
       function,
2516
0
       extent_index );
2517
2518
0
      goto on_error;
2519
0
    }
2520
0
    if( ( extent_values->type == LIBVMDK_EXTENT_TYPE_SPARSE )
2521
0
     || ( extent_values->type == LIBVMDK_EXTENT_TYPE_VMFS_SPARSE ) )
2522
0
    {
2523
0
      if( libvmdk_extent_file_initialize(
2524
0
           &extent_file,
2525
0
           internal_handle->io_handle,
2526
0
           error ) != 1 )
2527
0
      {
2528
0
        libcerror_error_set(
2529
0
         error,
2530
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2531
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2532
0
         "%s: unable to create extent file: %d.",
2533
0
         function,
2534
0
         extent_index );
2535
2536
0
        goto on_error;
2537
0
      }
2538
#if defined( HAVE_DEBUG_OUTPUT )
2539
      if( libcnotify_verbose != 0 )
2540
      {
2541
        libcnotify_printf(
2542
         "Reading extent file: %d file header:\n",
2543
         extent_index );
2544
      }
2545
#endif
2546
0
      if( libvmdk_extent_file_read_file_header(
2547
0
           extent_file,
2548
0
           file_io_pool,
2549
0
           extent_index,
2550
0
           0,
2551
0
           error ) != 1 )
2552
0
      {
2553
0
        libcerror_error_set(
2554
0
         error,
2555
0
         LIBCERROR_ERROR_DOMAIN_IO,
2556
0
         LIBCERROR_IO_ERROR_READ_FAILED,
2557
0
         "%s: unable to read extent file: %d header.",
2558
0
         function,
2559
0
         extent_index );
2560
2561
0
        goto on_error;
2562
0
      }
2563
0
      if( ( extent_file->file_type != LIBVMDK_FILE_TYPE_COWD_SPARSE_DATA )
2564
0
       && ( extent_file->file_type != LIBVMDK_FILE_TYPE_VMDK_SPARSE_DATA ) )
2565
0
      {
2566
0
        libcerror_error_set(
2567
0
         error,
2568
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2569
0
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2570
0
         "%s: extent file type not supported for extent type.",
2571
0
         function );
2572
2573
0
        goto on_error;
2574
0
      }
2575
0
      if( ( internal_handle->disk_type != LIBVMDK_DISK_TYPE_STREAM_OPTIMIZED )
2576
0
       && ( extent_file->file_type == LIBVMDK_FILE_TYPE_VMDK_SPARSE_DATA )
2577
0
       && ( ( extent_file->flags & LIBVMDK_FLAG_HAS_GRAIN_COMPRESSION ) != LIBVMDK_COMPRESSION_METHOD_NONE ) )
2578
0
      {
2579
0
        libcerror_error_set(
2580
0
         error,
2581
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2582
0
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2583
0
         "%s: grain compression not supported for disk type.",
2584
0
         function );
2585
2586
0
        goto on_error;
2587
0
      }
2588
0
      if( ( extent_file->file_type == LIBVMDK_FILE_TYPE_VMDK_SPARSE_DATA )
2589
0
       && ( extent_file->primary_grain_directory_offset == (off64_t) -1 )
2590
0
       && ( extent_file->compression_method == LIBVMDK_COMPRESSION_METHOD_DEFLATE ) )
2591
0
      {
2592
0
        if( libvmdk_extent_file_read_file_header(
2593
0
             extent_file,
2594
0
             file_io_pool,
2595
0
             extent_index,
2596
0
             extent_file_size - 1024,
2597
0
             error ) != 1 )
2598
0
        {
2599
0
          libcerror_error_set(
2600
0
           error,
2601
0
           LIBCERROR_ERROR_DOMAIN_IO,
2602
0
           LIBCERROR_IO_ERROR_READ_FAILED,
2603
0
           "%s: unable to read secondary extent file: %d header.",
2604
0
           function,
2605
0
           extent_index );
2606
2607
0
          goto on_error;
2608
0
        }
2609
0
      }
2610
0
      if( extent_index == 0 )
2611
0
      {
2612
0
        internal_handle->io_handle->grain_size = extent_file->grain_size;
2613
0
      }
2614
0
      else if( extent_file->grain_size != internal_handle->io_handle->grain_size )
2615
0
      {
2616
0
        libcerror_error_set(
2617
0
         error,
2618
0
         LIBCERROR_ERROR_DOMAIN_INPUT,
2619
0
         LIBCERROR_INPUT_ERROR_VALUE_MISMATCH,
2620
0
         "%s: extent file: %d grain size mismatch.",
2621
0
         function,
2622
0
         extent_index );
2623
2624
0
        goto on_error;
2625
0
      }
2626
0
      if( extent_file->is_dirty != 0 )
2627
0
      {
2628
0
        internal_handle->io_handle->is_dirty = 1;
2629
0
      }
2630
#if defined( HAVE_DEBUG_OUTPUT )
2631
      if( libcnotify_verbose != 0 )
2632
      {
2633
        libcnotify_printf(
2634
         "Reading extent file: %d grain directories:\n",
2635
         extent_index );
2636
      }
2637
#endif
2638
0
      if( libvmdk_extent_file_read_grain_directories(
2639
0
           extent_file,
2640
0
           file_io_pool,
2641
0
           extent_index,
2642
0
           error ) != 1 )
2643
0
      {
2644
0
        libcerror_error_set(
2645
0
         error,
2646
0
         LIBCERROR_ERROR_DOMAIN_IO,
2647
0
         LIBCERROR_IO_ERROR_READ_FAILED,
2648
0
         "%s: unable to read extent file: %d grain directories.",
2649
0
         function,
2650
0
         extent_index );
2651
2652
0
        goto on_error;
2653
0
      }
2654
0
      if( libvmdk_extent_table_set_extent_storage_media_size_by_index(
2655
0
           internal_handle->extent_table,
2656
0
           extent_index,
2657
0
           extent_file->storage_media_size,
2658
0
           error ) != 1 )
2659
0
      {
2660
0
        libcerror_error_set(
2661
0
         error,
2662
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2663
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2664
0
         "%s: unable to set mapped range of element: %d in extent table.",
2665
0
         function,
2666
0
         extent_index );
2667
2668
0
        goto on_error;
2669
0
      }
2670
0
      if( libvmdk_extent_file_free(
2671
0
           &extent_file,
2672
0
           error ) != 1 )
2673
0
      {
2674
0
        libcerror_error_set(
2675
0
         error,
2676
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2677
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2678
0
         "%s: unable to free extent file.",
2679
0
         function );
2680
2681
0
        goto on_error;
2682
0
      }
2683
0
    }
2684
0
    else if( ( extent_values->type != LIBVMDK_EXTENT_TYPE_FLAT )
2685
0
          && ( extent_values->type != LIBVMDK_EXTENT_TYPE_VMFS_FLAT ) )
2686
0
    {
2687
0
      libcerror_error_set(
2688
0
       error,
2689
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2690
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2691
0
       "%s: unsupported extent type.",
2692
0
       function );
2693
2694
0
      goto on_error;
2695
0
    }
2696
0
    if( internal_handle->io_handle->abort == 1 )
2697
0
    {
2698
0
      goto on_error;
2699
0
    }
2700
0
  }
2701
0
  return( 1 );
2702
2703
0
on_error:
2704
0
  if( extent_file != NULL )
2705
0
  {
2706
0
    libvmdk_extent_file_free(
2707
0
     &extent_file,
2708
0
     NULL );
2709
0
  }
2710
0
  if( internal_handle->grains_cache != NULL )
2711
0
  {
2712
0
    libfcache_cache_free(
2713
0
     &( internal_handle->grains_cache ),
2714
0
     NULL );
2715
0
  }
2716
0
  if( internal_handle->grain_table != NULL )
2717
0
  {
2718
0
    libvmdk_grain_table_free(
2719
0
     &( internal_handle->grain_table ),
2720
0
     NULL );
2721
0
  }
2722
0
  return( -1 );
2723
0
}
2724
2725
/* Reads the file signature and tries to determine the file type
2726
 * Returns 1 if successful, 0 if no file type could be determined or -1 on error
2727
 */
2728
int libvmdk_internal_handle_open_read_signature(
2729
     libbfio_handle_t *file_io_handle,
2730
     uint8_t *file_type,
2731
     libcerror_error_t **error )
2732
7.28k
{
2733
7.28k
  libcsplit_narrow_split_string_t *lines = NULL;
2734
7.28k
  uint8_t *signature                     = NULL;
2735
7.28k
  static char *function                  = "libvmdk_internal_handle_open_read_signature";
2736
7.28k
  ssize_t read_count                     = 0;
2737
7.28k
  int line_index                         = 0;
2738
7.28k
  int number_of_lines                    = 0;
2739
7.28k
  int result                             = 0;
2740
2741
7.28k
  if( file_type == NULL )
2742
0
  {
2743
0
    libcerror_error_set(
2744
0
     error,
2745
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2746
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2747
0
     "%s: invalid file type.",
2748
0
     function );
2749
2750
0
    return( -1 );
2751
0
  }
2752
7.28k
  signature = (uint8_t *) memory_allocate(
2753
7.28k
                           sizeof( uint8_t ) * 2048 );
2754
2755
7.28k
  if( signature == NULL )
2756
0
  {
2757
0
    libcerror_error_set(
2758
0
     error,
2759
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
2760
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
2761
0
     "%s: unable to create signature.",
2762
0
     function );
2763
2764
0
    goto on_error;
2765
0
  }
2766
7.28k
  if( memory_set(
2767
7.28k
       signature,
2768
7.28k
       0,
2769
7.28k
       sizeof( uint8_t ) * 2048 ) == NULL )
2770
0
  {
2771
0
    libcerror_error_set(
2772
0
     error,
2773
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
2774
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
2775
0
     "%s: unable to clear signature.",
2776
0
     function );
2777
2778
0
    goto on_error;
2779
0
  }
2780
7.28k
  read_count = libbfio_handle_read_buffer_at_offset(
2781
7.28k
                file_io_handle,
2782
7.28k
                signature,
2783
7.28k
                32,
2784
7.28k
                0,
2785
7.28k
                error );
2786
2787
7.28k
  if( read_count != (ssize_t) 32 )
2788
8
  {
2789
8
    libcerror_error_set(
2790
8
     error,
2791
8
     LIBCERROR_ERROR_DOMAIN_IO,
2792
8
     LIBCERROR_IO_ERROR_READ_FAILED,
2793
8
     "%s: unable to read signature at offset: 0 (0x00000000).",
2794
8
     function );
2795
2796
8
    goto on_error;
2797
8
  }
2798
7.27k
  if( memory_compare(
2799
7.27k
       signature,
2800
7.27k
       cowd_sparse_file_signature,
2801
7.27k
       4 ) == 0 )
2802
1
  {
2803
1
    *file_type = LIBVMDK_FILE_TYPE_COWD_SPARSE_DATA;
2804
1
    result     = 1;
2805
1
  }
2806
7.27k
  else if( memory_compare(
2807
7.27k
            signature,
2808
7.27k
            vmdk_sparse_file_signature,
2809
7.27k
            4 ) == 0 )
2810
312
  {
2811
312
    *file_type = LIBVMDK_FILE_TYPE_VMDK_SPARSE_DATA;
2812
312
    result     = 1;
2813
312
  }
2814
6.96k
  else if( signature[ 0 ] == '#' )
2815
6.92k
  {
2816
6.92k
    read_count = libbfio_handle_read_buffer(
2817
6.92k
                  file_io_handle,
2818
6.92k
                  &( signature[ 32 ] ),
2819
6.92k
                  2048 - 32,
2820
6.92k
                  error );
2821
2822
6.92k
    if( read_count == -1 )
2823
0
    {
2824
0
      libcerror_error_set(
2825
0
       error,
2826
0
       LIBCERROR_ERROR_DOMAIN_IO,
2827
0
       LIBCERROR_IO_ERROR_READ_FAILED,
2828
0
       "%s: unable to read signature.",
2829
0
       function );
2830
2831
0
      goto on_error;
2832
0
    }
2833
6.92k
    if( libcsplit_narrow_string_split(
2834
6.92k
         (char *) signature,
2835
6.92k
         32 + read_count,
2836
6.92k
         '\n',
2837
6.92k
         &lines,
2838
6.92k
         error ) != 1 )
2839
0
    {
2840
0
      libcerror_error_set(
2841
0
       error,
2842
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2843
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2844
0
       "%s: unable to split file data into lines.",
2845
0
       function );
2846
2847
0
      goto on_error;
2848
0
    }
2849
6.92k
    if( libcsplit_narrow_split_string_get_number_of_segments(
2850
6.92k
         lines,
2851
6.92k
         &number_of_lines,
2852
6.92k
         error ) != 1 )
2853
0
    {
2854
0
      libcerror_error_set(
2855
0
       error,
2856
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2857
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2858
0
       "%s: unable to retrieve number of lines.",
2859
0
       function );
2860
2861
0
      goto on_error;
2862
0
    }
2863
6.92k
    result = libvmdk_descriptor_file_read_signature(
2864
6.92k
        lines,
2865
6.92k
        number_of_lines,
2866
6.92k
        &line_index,
2867
6.92k
              error );
2868
2869
6.92k
    if( result == -1 )
2870
0
    {
2871
0
      libcerror_error_set(
2872
0
       error,
2873
0
       LIBCERROR_ERROR_DOMAIN_IO,
2874
0
       LIBCERROR_IO_ERROR_READ_FAILED,
2875
0
       "%s: unable to read descriptor file.",
2876
0
       function );
2877
2878
0
      goto on_error;
2879
0
    }
2880
6.92k
    else if( result != 0 )
2881
6.70k
    {
2882
6.70k
      *file_type = LIBVMDK_FILE_TYPE_DESCRIPTOR_FILE;
2883
6.70k
    }
2884
6.92k
    if( libcsplit_narrow_split_string_free(
2885
6.92k
         &lines,
2886
6.92k
         error ) != 1 )
2887
0
    {
2888
0
      libcerror_error_set(
2889
0
       error,
2890
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2891
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2892
0
       "%s: unable to free lines.",
2893
0
       function );
2894
2895
0
      goto on_error;
2896
0
    }
2897
6.92k
  }
2898
7.27k
  memory_free(
2899
7.27k
   signature );
2900
2901
7.27k
  return( result );
2902
2903
8
on_error:
2904
8
  if( lines != NULL )
2905
0
  {
2906
0
    libcsplit_narrow_split_string_free(
2907
0
     &lines,
2908
0
     NULL );
2909
0
  }
2910
8
  if( signature != NULL )
2911
8
  {
2912
8
    memory_free(
2913
8
     signature );
2914
8
  }
2915
8
  return( -1 );
2916
7.27k
}
2917
2918
/* Reads (media) data at the current offset into a buffer using a Basic File IO (bfio) pool
2919
 * This function is not multi-thread safe acquire write lock before call
2920
 * Returns the number of bytes read or -1 on error
2921
 */
2922
ssize_t libvmdk_internal_handle_read_buffer_from_file_io_pool(
2923
         libvmdk_internal_handle_t *internal_handle,
2924
         libbfio_pool_t *file_io_pool,
2925
         void *buffer,
2926
         size_t buffer_size,
2927
         libcerror_error_t **error )
2928
0
{
2929
0
  libvmdk_grain_data_t *grain_data = NULL;
2930
0
  static char *function            = "libvmdk_internal_handle_read_buffer_from_file_io_pool";
2931
0
  size_t buffer_offset             = 0;
2932
0
  size_t read_size                 = 0;
2933
0
  ssize_t read_count               = 0;
2934
0
  off64_t grain_data_offset        = 0;
2935
0
  uint64_t grain_index             = 0;
2936
0
  int grain_is_sparse              = 0;
2937
2938
0
  if( internal_handle == NULL )
2939
0
  {
2940
0
    libcerror_error_set(
2941
0
     error,
2942
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2943
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2944
0
     "%s: invalid handle.",
2945
0
     function );
2946
2947
0
    return( -1 );
2948
0
  }
2949
0
  if( internal_handle->io_handle == NULL )
2950
0
  {
2951
0
    libcerror_error_set(
2952
0
     error,
2953
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2954
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2955
0
     "%s: invalid handle - missing IO handle.",
2956
0
     function );
2957
2958
0
    return( -1 );
2959
0
  }
2960
0
  if( internal_handle->current_offset < 0 )
2961
0
  {
2962
0
    libcerror_error_set(
2963
0
     error,
2964
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2965
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2966
0
     "%s: invalid handle - invalid IO handle - current offset value out of bounds.",
2967
0
     function );
2968
2969
0
    return( -1 );
2970
0
  }
2971
0
  if( internal_handle->descriptor_file == NULL )
2972
0
  {
2973
0
    libcerror_error_set(
2974
0
     error,
2975
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2976
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2977
0
     "%s: invalid handle - missing descriptor file.",
2978
0
     function );
2979
2980
0
    return( -1 );
2981
0
  }
2982
0
  if( ( internal_handle->descriptor_file->parent_content_identifier_set != 0 )
2983
0
   && ( internal_handle->descriptor_file->parent_content_identifier != 0xffffffffUL ) )
2984
0
  {
2985
0
    if( internal_handle->parent_handle == NULL )
2986
0
    {
2987
0
      libcerror_error_set(
2988
0
       error,
2989
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2990
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2991
0
       "%s: invalid handle - missing parent handle.",
2992
0
       function );
2993
2994
0
      return( -1 );
2995
0
    }
2996
0
  }
2997
0
  if( buffer == NULL )
2998
0
  {
2999
0
    libcerror_error_set(
3000
0
     error,
3001
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3002
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3003
0
     "%s: invalid buffer.",
3004
0
     function );
3005
3006
0
    return( -1 );
3007
0
  }
3008
0
  if( buffer_size > (size_t) SSIZE_MAX )
3009
0
  {
3010
0
    libcerror_error_set(
3011
0
     error,
3012
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3013
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3014
0
     "%s: invalid element data size value exceeds maximum.",
3015
0
     function );
3016
3017
0
    return( -1 );
3018
0
  }
3019
0
  internal_handle->io_handle->abort = 0;
3020
3021
0
  if( buffer_size == 0 )
3022
0
  {
3023
0
    return( 0 );
3024
0
  }
3025
0
  if( (size64_t) internal_handle->current_offset >= internal_handle->io_handle->media_size )
3026
0
  {
3027
0
    return( 0 );
3028
0
  }
3029
0
  if( internal_handle->extent_table->extent_files_stream != NULL )
3030
0
  {
3031
#if defined( HAVE_DEBUG_OUTPUT )
3032
    if( libcnotify_verbose != 0 )
3033
    {
3034
      libcnotify_printf(
3035
       "%s: requested offset\t\t\t\t: %" PRIi64 " (0x%08" PRIx64 ")\n",
3036
       function,
3037
       internal_handle->current_offset,
3038
       internal_handle->current_offset );
3039
    }
3040
#endif
3041
0
    read_size = buffer_size;
3042
3043
0
    if( ( (size64_t) read_size > internal_handle->io_handle->media_size )
3044
0
     || ( (size64_t) internal_handle->current_offset > ( internal_handle->io_handle->media_size - read_size ) ) )
3045
0
    {
3046
0
      read_size = (size_t) ( internal_handle->io_handle->media_size - internal_handle->current_offset );
3047
0
    }
3048
0
    read_count = libfdata_stream_read_buffer_at_offset(
3049
0
                  internal_handle->extent_table->extent_files_stream,
3050
0
            (intptr_t *) file_io_pool,
3051
0
            (uint8_t *) buffer,
3052
0
            read_size,
3053
0
            internal_handle->current_offset,
3054
0
            0,
3055
0
            error );
3056
3057
0
    if( read_count != (ssize_t) read_size )
3058
0
    {
3059
0
      libcerror_error_set(
3060
0
       error,
3061
0
       LIBCERROR_ERROR_DOMAIN_IO,
3062
0
       LIBCERROR_IO_ERROR_READ_FAILED,
3063
0
       "%s: unable to read buffer from extent files stream at offset: %" PRIi64 " (0x%" PRIx64 ").",
3064
0
       function,
3065
0
       internal_handle->current_offset,
3066
0
       internal_handle->current_offset );
3067
3068
0
      return( -1 );
3069
0
    }
3070
0
    internal_handle->current_offset += (off64_t) read_size;
3071
3072
0
    buffer_offset = read_size;
3073
0
  }
3074
0
  else
3075
0
  {
3076
0
    grain_index       = internal_handle->current_offset / internal_handle->io_handle->grain_size;
3077
0
    grain_data_offset = (off64_t) ( internal_handle->current_offset % internal_handle->io_handle->grain_size );
3078
3079
0
    while( buffer_offset < buffer_size )
3080
0
    {
3081
0
      grain_is_sparse = libvmdk_grain_table_grain_is_sparse_at_offset(
3082
0
             internal_handle->grain_table,
3083
0
             grain_index,
3084
0
             file_io_pool,
3085
0
             internal_handle->extent_table,
3086
0
             internal_handle->current_offset,
3087
0
             error );
3088
3089
0
      if( grain_is_sparse == -1 )
3090
0
      {
3091
0
        libcerror_error_set(
3092
0
         error,
3093
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3094
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3095
0
         "%s: unable to determine if the grain: %" PRIu64 " is sparse.",
3096
0
         function,
3097
0
         grain_index );
3098
3099
0
        return( -1 );
3100
0
      }
3101
0
      read_size = (size_t) ( internal_handle->io_handle->grain_size - grain_data_offset );
3102
3103
0
      if( read_size > ( buffer_size - buffer_offset ) )
3104
0
      {
3105
0
        read_size = buffer_size - buffer_offset;
3106
0
      }
3107
0
      if( ( (size64_t) read_size > internal_handle->io_handle->media_size )
3108
0
       || ( (size64_t) internal_handle->current_offset > ( internal_handle->io_handle->media_size - read_size ) ) )
3109
0
      {
3110
0
        read_size = (size_t) ( internal_handle->io_handle->media_size - internal_handle->current_offset );
3111
0
      }
3112
0
      if( grain_is_sparse != 0 )
3113
0
      {
3114
0
        if( internal_handle->parent_handle == NULL )
3115
0
        {
3116
0
          if( memory_set(
3117
0
               &( ( (uint8_t *) buffer )[ buffer_offset ] ),
3118
0
               0,
3119
0
               read_size ) == NULL )
3120
0
          {
3121
0
            libcerror_error_set(
3122
0
             error,
3123
0
             LIBCERROR_ERROR_DOMAIN_MEMORY,
3124
0
             LIBCERROR_MEMORY_ERROR_SET_FAILED,
3125
0
             "%s: unable to fill buffer with sparse grain.",
3126
0
             function );
3127
3128
0
            return( -1 );
3129
0
          }
3130
0
        }
3131
0
        else
3132
0
        {
3133
/* TODO do we need grain offset or current offset ? */
3134
0
          if( libvmdk_handle_seek_offset(
3135
0
               internal_handle->parent_handle,
3136
0
               internal_handle->current_offset,
3137
0
               SEEK_SET,
3138
0
               error ) == -1 )
3139
0
          {
3140
0
            libcerror_error_set(
3141
0
             error,
3142
0
             LIBCERROR_ERROR_DOMAIN_IO,
3143
0
             LIBCERROR_IO_ERROR_SEEK_FAILED,
3144
0
             "%s: unable to seek grain offset: %" PRIi64 " (0x%08" PRIx64 ") in parent.",
3145
0
             function,
3146
0
             internal_handle->current_offset,
3147
0
             internal_handle->current_offset );
3148
3149
0
            return( -1 );
3150
0
          }
3151
0
          read_count = libvmdk_handle_read_buffer(
3152
0
                  internal_handle->parent_handle,
3153
0
                  &( ( (uint8_t *) buffer )[ buffer_offset ] ),
3154
0
                  read_size,
3155
0
                  error );
3156
3157
0
          if( read_count != (ssize_t) read_size )
3158
0
          {
3159
0
            libcerror_error_set(
3160
0
             error,
3161
0
             LIBCERROR_ERROR_DOMAIN_IO,
3162
0
             LIBCERROR_IO_ERROR_READ_FAILED,
3163
0
             "%s: unable to read grain data from parent.",
3164
0
             function );
3165
3166
0
            return( -1 );
3167
0
          }
3168
0
        }
3169
0
      }
3170
0
      else
3171
0
      {
3172
0
        if( libvmdk_grain_table_get_grain_data_at_offset(
3173
0
             internal_handle->grain_table,
3174
0
             grain_index,
3175
0
             file_io_pool,
3176
0
             internal_handle->extent_table,
3177
0
             internal_handle->grains_cache,
3178
0
             internal_handle->current_offset,
3179
0
             &grain_data,
3180
0
             &grain_data_offset,
3181
0
             error ) != 1 )
3182
0
        {
3183
0
          libcerror_error_set(
3184
0
           error,
3185
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
3186
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3187
0
           "%s: unable to retrieve grain: %d data.",
3188
0
           function,
3189
0
           grain_index );
3190
3191
0
          return( -1 );
3192
0
        }
3193
0
        if( grain_data == NULL )
3194
0
        {
3195
0
          libcerror_error_set(
3196
0
           error,
3197
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
3198
0
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3199
0
           "%s: missing grain: %d data.",
3200
0
           function,
3201
0
           grain_index );
3202
3203
0
          return( -1 );
3204
0
        }
3205
0
        if( (size64_t) grain_data_offset > grain_data->data_size )
3206
0
        {
3207
0
          libcerror_error_set(
3208
0
           error,
3209
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
3210
0
           LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3211
0
           "%s: grain data offset value out of bounds.",
3212
0
           function );
3213
3214
0
          return( -1 );
3215
0
        }
3216
0
        if( read_size > (size_t) ( grain_data->data_size - grain_data_offset ) )
3217
0
        {
3218
0
          libcerror_error_set(
3219
0
           error,
3220
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
3221
0
           LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3222
0
           "%s: read size value out of bounds.",
3223
0
           function );
3224
3225
0
          return( -1 );
3226
0
        }
3227
0
        if( memory_copy(
3228
0
             &( ( (uint8_t *) buffer )[ buffer_offset ] ),
3229
0
             &( ( grain_data->data )[ grain_data_offset ] ),
3230
0
             read_size ) == NULL )
3231
0
        {
3232
0
          libcerror_error_set(
3233
0
           error,
3234
0
           LIBCERROR_ERROR_DOMAIN_MEMORY,
3235
0
           LIBCERROR_MEMORY_ERROR_COPY_FAILED,
3236
0
           "%s: unable to copy grain data to buffer.",
3237
0
           function );
3238
3239
0
          return( -1 );
3240
0
        }
3241
0
      }
3242
0
      buffer_offset    += read_size;
3243
0
      grain_index      += 1;
3244
0
      grain_data_offset = 0;
3245
3246
0
      internal_handle->current_offset += (off64_t) read_size;
3247
3248
0
      if( (size64_t) internal_handle->current_offset >= internal_handle->io_handle->media_size )
3249
0
      {
3250
0
        break;
3251
0
      }
3252
0
      if( internal_handle->io_handle->abort != 0 )
3253
0
      {
3254
0
        break;
3255
0
      }
3256
0
    }
3257
0
  }
3258
0
  return( (ssize_t) buffer_offset );
3259
0
}
3260
3261
/* Reads (media) data at the current offset into a buffer
3262
 * Returns the number of bytes read or -1 on error
3263
 */
3264
ssize_t libvmdk_handle_read_buffer(
3265
         libvmdk_handle_t *handle,
3266
         void *buffer,
3267
         size_t buffer_size,
3268
         libcerror_error_t **error )
3269
0
{
3270
0
  libvmdk_internal_handle_t *internal_handle = NULL;
3271
0
  static char *function                      = "libvmdk_handle_read_buffer";
3272
0
  ssize_t read_count                         = 0;
3273
3274
0
  if( handle == NULL )
3275
0
  {
3276
0
    libcerror_error_set(
3277
0
     error,
3278
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3279
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3280
0
     "%s: invalid handle.",
3281
0
     function );
3282
3283
0
    return( -1 );
3284
0
  }
3285
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
3286
3287
0
  if( internal_handle->extent_data_file_io_pool == NULL )
3288
0
  {
3289
0
    libcerror_error_set(
3290
0
     error,
3291
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3292
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3293
0
     "%s: invalid handle - missing extent data file IO pool.",
3294
0
     function );
3295
3296
0
    return( -1 );
3297
0
  }
3298
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3299
0
  if( libcthreads_read_write_lock_grab_for_write(
3300
0
       internal_handle->read_write_lock,
3301
0
       error ) != 1 )
3302
0
  {
3303
0
    libcerror_error_set(
3304
0
     error,
3305
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3306
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3307
0
     "%s: unable to grab read/write lock for writing.",
3308
0
     function );
3309
3310
0
    return( -1 );
3311
0
  }
3312
0
#endif
3313
0
  read_count = libvmdk_internal_handle_read_buffer_from_file_io_pool(
3314
0
          internal_handle,
3315
0
          internal_handle->extent_data_file_io_pool,
3316
0
          buffer,
3317
0
          buffer_size,
3318
0
          error );
3319
3320
0
  if( read_count < 0 )
3321
0
  {
3322
0
    libcerror_error_set(
3323
0
     error,
3324
0
     LIBCERROR_ERROR_DOMAIN_IO,
3325
0
     LIBCERROR_IO_ERROR_READ_FAILED,
3326
0
     "%s: unable to read buffer.",
3327
0
     function );
3328
3329
0
    read_count = -1;
3330
0
  }
3331
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3332
0
  if( libcthreads_read_write_lock_release_for_write(
3333
0
       internal_handle->read_write_lock,
3334
0
       error ) != 1 )
3335
0
  {
3336
0
    libcerror_error_set(
3337
0
     error,
3338
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3339
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3340
0
     "%s: unable to release read/write lock for writing.",
3341
0
     function );
3342
3343
0
    return( -1 );
3344
0
  }
3345
0
#endif
3346
0
  return( read_count );
3347
0
}
3348
3349
/* Reads (media) data at a specific offset
3350
 * Returns the number of bytes read or -1 on error
3351
 */
3352
ssize_t libvmdk_handle_read_buffer_at_offset(
3353
         libvmdk_handle_t *handle,
3354
         void *buffer,
3355
         size_t buffer_size,
3356
         off64_t offset,
3357
         libcerror_error_t **error )
3358
0
{
3359
0
  libvmdk_internal_handle_t *internal_handle = NULL;
3360
0
  static char *function                      = "libvmdk_handle_read_buffer_at_offset";
3361
0
  ssize_t read_count                         = 0;
3362
3363
0
  if( handle == NULL )
3364
0
  {
3365
0
    libcerror_error_set(
3366
0
     error,
3367
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3368
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3369
0
     "%s: invalid handle.",
3370
0
     function );
3371
3372
0
    return( -1 );
3373
0
  }
3374
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
3375
3376
0
  if( internal_handle->extent_data_file_io_pool == NULL )
3377
0
  {
3378
0
    libcerror_error_set(
3379
0
     error,
3380
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3381
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3382
0
     "%s: invalid handle - missing extent data file IO pool.",
3383
0
     function );
3384
3385
0
    return( -1 );
3386
0
  }
3387
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3388
0
  if( libcthreads_read_write_lock_grab_for_write(
3389
0
       internal_handle->read_write_lock,
3390
0
       error ) != 1 )
3391
0
  {
3392
0
    libcerror_error_set(
3393
0
     error,
3394
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3395
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3396
0
     "%s: unable to grab read/write lock for writing.",
3397
0
     function );
3398
3399
0
    return( -1 );
3400
0
  }
3401
0
#endif
3402
0
  if( libvmdk_internal_handle_seek_offset(
3403
0
       internal_handle,
3404
0
       offset,
3405
0
       SEEK_SET,
3406
0
       error ) == -1 )
3407
0
  {
3408
0
    libcerror_error_set(
3409
0
     error,
3410
0
     LIBCERROR_ERROR_DOMAIN_IO,
3411
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
3412
0
     "%s: unable to seek offset.",
3413
0
     function );
3414
3415
0
    goto on_error;
3416
0
  }
3417
0
  read_count = libvmdk_internal_handle_read_buffer_from_file_io_pool(
3418
0
          internal_handle,
3419
0
          internal_handle->extent_data_file_io_pool,
3420
0
          buffer,
3421
0
          buffer_size,
3422
0
          error );
3423
3424
0
  if( read_count == -1 )
3425
0
  {
3426
0
    libcerror_error_set(
3427
0
     error,
3428
0
     LIBCERROR_ERROR_DOMAIN_IO,
3429
0
     LIBCERROR_IO_ERROR_READ_FAILED,
3430
0
     "%s: unable to read buffer.",
3431
0
     function );
3432
3433
0
    goto on_error;
3434
0
  }
3435
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3436
0
  if( libcthreads_read_write_lock_release_for_write(
3437
0
       internal_handle->read_write_lock,
3438
0
       error ) != 1 )
3439
0
  {
3440
0
    libcerror_error_set(
3441
0
     error,
3442
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3443
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3444
0
     "%s: unable to release read/write lock for writing.",
3445
0
     function );
3446
3447
0
    return( -1 );
3448
0
  }
3449
0
#endif
3450
0
  return( read_count );
3451
3452
0
on_error:
3453
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3454
0
  libcthreads_read_write_lock_release_for_write(
3455
0
   internal_handle->read_write_lock,
3456
0
   NULL );
3457
0
#endif
3458
0
  return( -1 );
3459
0
}
3460
3461
/* Seeks a certain offset of the (media) data
3462
 * This function is not multi-thread safe acquire write lock before call
3463
 * Returns the offset if seek is successful or -1 on error
3464
 */
3465
off64_t libvmdk_internal_handle_seek_offset(
3466
         libvmdk_internal_handle_t *internal_handle,
3467
         off64_t offset,
3468
         int whence,
3469
         libcerror_error_t **error )
3470
0
{
3471
0
  static char *function = "libvmdk_internal_handle_seek_offset";
3472
3473
0
  if( internal_handle == NULL )
3474
0
  {
3475
0
    libcerror_error_set(
3476
0
     error,
3477
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3478
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3479
0
     "%s: invalid handle.",
3480
0
     function );
3481
3482
0
    return( -1 );
3483
0
  }
3484
0
  if( internal_handle->io_handle == NULL )
3485
0
  {
3486
0
    libcerror_error_set(
3487
0
     error,
3488
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3489
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3490
0
     "%s: invalid handle - missing IO handle.",
3491
0
     function );
3492
3493
0
    return( -1 );
3494
0
  }
3495
0
  if( ( whence != SEEK_CUR )
3496
0
   && ( whence != SEEK_END )
3497
0
   && ( whence != SEEK_SET ) )
3498
0
  {
3499
0
    libcerror_error_set(
3500
0
     error,
3501
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3502
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3503
0
     "%s: unsupported whence.",
3504
0
     function );
3505
3506
0
    return( -1 );
3507
0
  }
3508
0
  if( whence == SEEK_CUR )
3509
0
  {
3510
0
    offset += internal_handle->current_offset;
3511
0
  }
3512
0
  else if( whence == SEEK_END )
3513
0
  {
3514
0
    offset += (off64_t) internal_handle->io_handle->media_size;
3515
0
  }
3516
0
  if( offset < 0 )
3517
0
  {
3518
0
    libcerror_error_set(
3519
0
     error,
3520
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3521
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
3522
0
     "%s: invalid offset value out of bounds.",
3523
0
     function );
3524
3525
0
    return( -1 );
3526
0
  }
3527
0
  internal_handle->current_offset = offset;
3528
3529
0
  return( offset );
3530
0
}
3531
3532
/* Seeks a certain offset of the (media) data
3533
 * Returns the offset if seek is successful or -1 on error
3534
 */
3535
off64_t libvmdk_handle_seek_offset(
3536
         libvmdk_handle_t *handle,
3537
         off64_t offset,
3538
         int whence,
3539
         libcerror_error_t **error )
3540
0
{
3541
0
  libvmdk_internal_handle_t *internal_handle = NULL;
3542
0
  static char *function                      = "libvmdk_handle_seek_offset";
3543
3544
0
  if( handle == NULL )
3545
0
  {
3546
0
    libcerror_error_set(
3547
0
     error,
3548
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3549
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3550
0
     "%s: invalid handle.",
3551
0
     function );
3552
3553
0
    return( -1 );
3554
0
  }
3555
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
3556
3557
0
  if( internal_handle->extent_data_file_io_pool == NULL )
3558
0
  {
3559
0
    libcerror_error_set(
3560
0
     error,
3561
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3562
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3563
0
     "%s: invalid handle - missing extent data file IO pool.",
3564
0
     function );
3565
3566
0
    return( -1 );
3567
0
  }
3568
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3569
0
  if( libcthreads_read_write_lock_grab_for_write(
3570
0
       internal_handle->read_write_lock,
3571
0
       error ) != 1 )
3572
0
  {
3573
0
    libcerror_error_set(
3574
0
     error,
3575
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3576
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3577
0
     "%s: unable to grab read/write lock for writing.",
3578
0
     function );
3579
3580
0
    return( -1 );
3581
0
  }
3582
0
#endif
3583
0
  offset = libvmdk_internal_handle_seek_offset(
3584
0
            internal_handle,
3585
0
            offset,
3586
0
            whence,
3587
0
            error );
3588
3589
0
  if( offset == -1 )
3590
0
  {
3591
0
    libcerror_error_set(
3592
0
     error,
3593
0
     LIBCERROR_ERROR_DOMAIN_IO,
3594
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
3595
0
     "%s: unable to seek offset.",
3596
0
     function );
3597
3598
0
    offset = -1;
3599
0
  }
3600
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3601
0
  if( libcthreads_read_write_lock_release_for_write(
3602
0
       internal_handle->read_write_lock,
3603
0
       error ) != 1 )
3604
0
  {
3605
0
    libcerror_error_set(
3606
0
     error,
3607
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3608
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3609
0
     "%s: unable to release read/write lock for writing.",
3610
0
     function );
3611
3612
0
    return( -1 );
3613
0
  }
3614
0
#endif
3615
0
  return( offset );
3616
0
}
3617
3618
/* Retrieves the current offset of the (media) data
3619
 * Returns 1 if successful or -1 on error
3620
 */
3621
int libvmdk_handle_get_offset(
3622
     libvmdk_handle_t *handle,
3623
     off64_t *offset,
3624
     libcerror_error_t **error )
3625
0
{
3626
0
  libvmdk_internal_handle_t *internal_handle = NULL;
3627
0
  static char *function                      = "libvmdk_handle_get_offset";
3628
3629
0
  if( handle == NULL )
3630
0
  {
3631
0
    libcerror_error_set(
3632
0
     error,
3633
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3634
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3635
0
     "%s: invalid handle.",
3636
0
     function );
3637
3638
0
    return( -1 );
3639
0
  }
3640
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
3641
3642
0
  if( internal_handle->io_handle == NULL )
3643
0
  {
3644
0
    libcerror_error_set(
3645
0
     error,
3646
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3647
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3648
0
     "%s: invalid handle - missing IO handle.",
3649
0
     function );
3650
3651
0
    return( -1 );
3652
0
  }
3653
0
  if( internal_handle->extent_data_file_io_pool == NULL )
3654
0
  {
3655
0
    libcerror_error_set(
3656
0
     error,
3657
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3658
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3659
0
     "%s: invalid handle - missing extent data file IO pool.",
3660
0
     function );
3661
3662
0
    return( -1 );
3663
0
  }
3664
0
  if( offset == NULL )
3665
0
  {
3666
0
    libcerror_error_set(
3667
0
     error,
3668
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3669
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3670
0
     "%s: invalid offset.",
3671
0
     function );
3672
3673
0
    return( -1 );
3674
0
  }
3675
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3676
0
  if( libcthreads_read_write_lock_grab_for_read(
3677
0
       internal_handle->read_write_lock,
3678
0
       error ) != 1 )
3679
0
  {
3680
0
    libcerror_error_set(
3681
0
     error,
3682
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3683
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3684
0
     "%s: unable to grab read/write lock for reading.",
3685
0
     function );
3686
3687
0
    return( -1 );
3688
0
  }
3689
0
#endif
3690
0
  *offset = internal_handle->current_offset;
3691
3692
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3693
0
  if( libcthreads_read_write_lock_release_for_read(
3694
0
       internal_handle->read_write_lock,
3695
0
       error ) != 1 )
3696
0
  {
3697
0
    libcerror_error_set(
3698
0
     error,
3699
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3700
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3701
0
     "%s: unable to release read/write lock for reading.",
3702
0
     function );
3703
3704
0
    return( -1 );
3705
0
  }
3706
0
#endif
3707
0
  return( 1 );
3708
0
}
3709
3710
/* Sets the maximum number of (concurrent) open file handles
3711
 * Returns 1 if successful or -1 on error
3712
 */
3713
int libvmdk_handle_set_maximum_number_of_open_handles(
3714
     libvmdk_handle_t *handle,
3715
     int maximum_number_of_open_handles,
3716
     libcerror_error_t **error )
3717
0
{
3718
0
  libvmdk_internal_handle_t *internal_handle = NULL;
3719
0
  static char *function                      = "libvmdk_handle_set_maximum_number_of_open_handles";
3720
0
  int result                                 = 1;
3721
3722
0
  if( handle == NULL )
3723
0
  {
3724
0
    libcerror_error_set(
3725
0
     error,
3726
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3727
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3728
0
     "%s: invalid handle.",
3729
0
     function );
3730
3731
0
    return( -1 );
3732
0
  }
3733
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
3734
3735
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3736
0
  if( libcthreads_read_write_lock_grab_for_write(
3737
0
       internal_handle->read_write_lock,
3738
0
       error ) != 1 )
3739
0
  {
3740
0
    libcerror_error_set(
3741
0
     error,
3742
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3743
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3744
0
     "%s: unable to grab read/write lock for writing.",
3745
0
     function );
3746
3747
0
    return( -1 );
3748
0
  }
3749
0
#endif
3750
0
  if( internal_handle->extent_data_file_io_pool != NULL )
3751
0
  {
3752
0
    if( libbfio_pool_set_maximum_number_of_open_handles(
3753
0
         internal_handle->extent_data_file_io_pool,
3754
0
         maximum_number_of_open_handles,
3755
0
         error ) != -1 )
3756
0
    {
3757
0
      libcerror_error_set(
3758
0
       error,
3759
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3760
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3761
0
       "%s: unable to set maximum number of open handles in extent data file IO pool.",
3762
0
       function );
3763
3764
0
      result = -1;
3765
0
    }
3766
0
  }
3767
0
  if( result == 1 )
3768
0
  {
3769
0
    internal_handle->maximum_number_of_open_handles = maximum_number_of_open_handles;
3770
0
  }
3771
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3772
0
  if( libcthreads_read_write_lock_release_for_write(
3773
0
       internal_handle->read_write_lock,
3774
0
       error ) != 1 )
3775
0
  {
3776
0
    libcerror_error_set(
3777
0
     error,
3778
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3779
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3780
0
     "%s: unable to release read/write lock for writing.",
3781
0
     function );
3782
3783
0
    return( -1 );
3784
0
  }
3785
0
#endif
3786
0
  return( result );
3787
0
}
3788
3789
/* Sets the parent handle
3790
 * Returns 1 if successful or -1 on error
3791
 */
3792
int libvmdk_handle_set_parent_handle(
3793
     libvmdk_handle_t *handle,
3794
     libvmdk_handle_t *parent_handle,
3795
     libcerror_error_t **error )
3796
0
{
3797
0
  libvmdk_internal_handle_t *internal_handle = NULL;
3798
0
  static char *function                      = "libvmdk_handle_set_parent_handle";
3799
0
  uint32_t content_identifier                = 0;
3800
3801
0
  if( handle == NULL )
3802
0
  {
3803
0
    libcerror_error_set(
3804
0
     error,
3805
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3806
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3807
0
     "%s: invalid handle.",
3808
0
     function );
3809
3810
0
    return( -1 );
3811
0
  }
3812
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
3813
3814
0
  if( internal_handle->descriptor_file == NULL )
3815
0
  {
3816
0
    libcerror_error_set(
3817
0
     error,
3818
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3819
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3820
0
     "%s: invalid handle - missing descriptor file.",
3821
0
     function );
3822
3823
0
    return( -1 );
3824
0
  }
3825
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3826
0
  if( libcthreads_read_write_lock_grab_for_write(
3827
0
       internal_handle->read_write_lock,
3828
0
       error ) != 1 )
3829
0
  {
3830
0
    libcerror_error_set(
3831
0
     error,
3832
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3833
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3834
0
     "%s: unable to grab read/write lock for writing.",
3835
0
     function );
3836
3837
0
    return( -1 );
3838
0
  }
3839
0
#endif
3840
0
  if( libvmdk_handle_get_content_identifier(
3841
0
       parent_handle,
3842
0
       &content_identifier,
3843
0
       error ) != 1 )
3844
0
  {
3845
0
    libcerror_error_set(
3846
0
     error,
3847
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3848
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3849
0
     "%s: unable to retrieve content identifier from parent handle.",
3850
0
     function );
3851
3852
0
    goto on_error;
3853
0
  }
3854
0
  if( content_identifier != internal_handle->descriptor_file->parent_content_identifier )
3855
0
  {
3856
0
    libcerror_error_set(
3857
0
     error,
3858
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3859
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3860
0
     "%s: mismatch in content identifier.",
3861
0
     function );
3862
3863
0
    goto on_error;
3864
0
  }
3865
0
  internal_handle->parent_handle = parent_handle;
3866
3867
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3868
0
  if( libcthreads_read_write_lock_release_for_write(
3869
0
       internal_handle->read_write_lock,
3870
0
       error ) != 1 )
3871
0
  {
3872
0
    libcerror_error_set(
3873
0
     error,
3874
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3875
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3876
0
     "%s: unable to release read/write lock for writing.",
3877
0
     function );
3878
3879
0
    return( -1 );
3880
0
  }
3881
0
#endif
3882
0
  return( 1 );
3883
3884
0
on_error:
3885
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3886
0
  libcthreads_read_write_lock_release_for_write(
3887
0
   internal_handle->read_write_lock,
3888
0
   NULL );
3889
0
#endif
3890
0
  return( -1 );
3891
0
}
3892
3893
/* Sets the path to the extent data files
3894
 * Returns 1 if successful or -1 on error
3895
 */
3896
int libvmdk_handle_set_extent_data_files_path(
3897
     libvmdk_handle_t *handle,
3898
     const char *path,
3899
     size_t path_length,
3900
     libcerror_error_t **error )
3901
0
{
3902
0
  libvmdk_internal_handle_t *internal_handle = NULL;
3903
0
  static char *function                      = "libvmdk_handle_set_extent_data_files_path";
3904
0
  int result                                 = 1;
3905
3906
0
  if( handle == NULL )
3907
0
  {
3908
0
    libcerror_error_set(
3909
0
     error,
3910
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3911
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3912
0
     "%s: invalid handle.",
3913
0
     function );
3914
3915
0
    return( -1 );
3916
0
  }
3917
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
3918
3919
0
  if( path == NULL )
3920
0
  {
3921
0
    libcerror_error_set(
3922
0
     error,
3923
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3924
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3925
0
     "%s: invalid path.",
3926
0
     function );
3927
3928
0
    return( -1 );
3929
0
  }
3930
0
  if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
3931
0
  {
3932
0
    libcerror_error_set(
3933
0
     error,
3934
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3935
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3936
0
     "%s: invalid path length value exceeds maximum.",
3937
0
     function );
3938
3939
0
    return( -1 );
3940
0
  }
3941
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3942
0
  if( libcthreads_read_write_lock_grab_for_write(
3943
0
       internal_handle->read_write_lock,
3944
0
       error ) != 1 )
3945
0
  {
3946
0
    libcerror_error_set(
3947
0
     error,
3948
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3949
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3950
0
     "%s: unable to grab read/write lock for writing.",
3951
0
     function );
3952
3953
0
    return( -1 );
3954
0
  }
3955
0
#endif
3956
0
  if( libvmdk_extent_table_set_data_files_path(
3957
0
       internal_handle->extent_table,
3958
0
       path,
3959
0
       path_length,
3960
0
       error ) != 1 )
3961
0
  {
3962
0
    libcerror_error_set(
3963
0
     error,
3964
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3965
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3966
0
     "%s: unable to set data files path in extent table.",
3967
0
     function );
3968
3969
0
    result = -1;
3970
0
  }
3971
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
3972
0
  if( libcthreads_read_write_lock_release_for_write(
3973
0
       internal_handle->read_write_lock,
3974
0
       error ) != 1 )
3975
0
  {
3976
0
    libcerror_error_set(
3977
0
     error,
3978
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3979
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3980
0
     "%s: unable to release read/write lock for writing.",
3981
0
     function );
3982
3983
0
    return( -1 );
3984
0
  }
3985
0
#endif
3986
0
  return( result );
3987
0
}
3988
3989
#if defined( HAVE_WIDE_CHARACTER_TYPE )
3990
3991
/* Sets the path to the extent data files
3992
 * Returns 1 if successful or -1 on error
3993
 */
3994
int libvmdk_handle_set_extent_data_files_path_wide(
3995
     libvmdk_handle_t *handle,
3996
     const wchar_t *path,
3997
     size_t path_length,
3998
     libcerror_error_t **error )
3999
{
4000
  libvmdk_internal_handle_t *internal_handle = NULL;
4001
  static char *function                      = "libvmdk_handle_set_extent_data_files_path_wide";
4002
  int result                                 = 1;
4003
4004
  if( handle == NULL )
4005
  {
4006
    libcerror_error_set(
4007
     error,
4008
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4009
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4010
     "%s: invalid handle.",
4011
     function );
4012
4013
    return( -1 );
4014
  }
4015
  internal_handle = (libvmdk_internal_handle_t *) handle;
4016
4017
  if( path == NULL )
4018
  {
4019
    libcerror_error_set(
4020
     error,
4021
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4022
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4023
     "%s: invalid path.",
4024
     function );
4025
4026
    return( -1 );
4027
  }
4028
  if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
4029
  {
4030
    libcerror_error_set(
4031
     error,
4032
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4033
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4034
     "%s: invalid path length value exceeds maximum.",
4035
     function );
4036
4037
    return( -1 );
4038
  }
4039
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4040
  if( libcthreads_read_write_lock_grab_for_write(
4041
       internal_handle->read_write_lock,
4042
       error ) != 1 )
4043
  {
4044
    libcerror_error_set(
4045
     error,
4046
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4047
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4048
     "%s: unable to grab read/write lock for writing.",
4049
     function );
4050
4051
    return( -1 );
4052
  }
4053
#endif
4054
  if( libvmdk_extent_table_set_data_files_path_wide(
4055
       internal_handle->extent_table,
4056
       path,
4057
       path_length,
4058
       error ) != 1 )
4059
  {
4060
    libcerror_error_set(
4061
     error,
4062
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4063
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4064
     "%s: unable to set data files path in extent table.",
4065
     function );
4066
4067
    result = -1;
4068
  }
4069
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4070
  if( libcthreads_read_write_lock_release_for_write(
4071
       internal_handle->read_write_lock,
4072
       error ) != 1 )
4073
  {
4074
    libcerror_error_set(
4075
     error,
4076
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4077
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4078
     "%s: unable to release read/write lock for writing.",
4079
     function );
4080
4081
    return( -1 );
4082
  }
4083
#endif
4084
  return( result );
4085
}
4086
4087
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
4088
4089
/* Retrieves the disk type
4090
 * Returns 1 if successful or -1 on error
4091
 */
4092
int libvmdk_handle_get_disk_type(
4093
     libvmdk_handle_t *handle,
4094
     int *disk_type,
4095
     libcerror_error_t **error )
4096
0
{
4097
0
  libvmdk_internal_handle_t *internal_handle = NULL;
4098
0
  static char *function                      = "libvmdk_handle_get_disk_type";
4099
4100
0
  if( handle == NULL )
4101
0
  {
4102
0
    libcerror_error_set(
4103
0
     error,
4104
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4105
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4106
0
     "%s: invalid handle.",
4107
0
     function );
4108
4109
0
    return( -1 );
4110
0
  }
4111
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
4112
4113
0
  if( internal_handle->descriptor_file == NULL )
4114
0
  {
4115
0
    libcerror_error_set(
4116
0
     error,
4117
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4118
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4119
0
     "%s: invalid handle - missing descriptor file.",
4120
0
     function );
4121
4122
0
    return( -1 );
4123
0
  }
4124
0
  if( disk_type == NULL )
4125
0
  {
4126
0
    libcerror_error_set(
4127
0
     error,
4128
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4129
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4130
0
     "%s: invalid disk type.",
4131
0
     function );
4132
4133
0
    return( -1 );
4134
0
  }
4135
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4136
0
  if( libcthreads_read_write_lock_grab_for_read(
4137
0
       internal_handle->read_write_lock,
4138
0
       error ) != 1 )
4139
0
  {
4140
0
    libcerror_error_set(
4141
0
     error,
4142
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4143
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4144
0
     "%s: unable to grab read/write lock for reading.",
4145
0
     function );
4146
4147
0
    return( -1 );
4148
0
  }
4149
0
#endif
4150
0
  *disk_type = internal_handle->disk_type;
4151
4152
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4153
0
  if( libcthreads_read_write_lock_release_for_read(
4154
0
       internal_handle->read_write_lock,
4155
0
       error ) != 1 )
4156
0
  {
4157
0
    libcerror_error_set(
4158
0
     error,
4159
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4160
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4161
0
     "%s: unable to release read/write lock for reading.",
4162
0
     function );
4163
4164
0
    return( -1 );
4165
0
  }
4166
0
#endif
4167
0
  return( 1 );
4168
0
}
4169
4170
/* Retrieves the media size
4171
 * Returns 1 if successful or -1 on error
4172
 */
4173
int libvmdk_handle_get_media_size(
4174
     libvmdk_handle_t *handle,
4175
     size64_t *media_size,
4176
     libcerror_error_t **error )
4177
0
{
4178
0
  libvmdk_internal_handle_t *internal_handle = NULL;
4179
0
  static char *function                      = "libvmdk_handle_get_media_size";
4180
4181
0
  if( handle == NULL )
4182
0
  {
4183
0
    libcerror_error_set(
4184
0
     error,
4185
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4186
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4187
0
     "%s: invalid handle.",
4188
0
     function );
4189
4190
0
    return( -1 );
4191
0
  }
4192
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
4193
4194
0
  if( internal_handle->descriptor_file == NULL )
4195
0
  {
4196
0
    libcerror_error_set(
4197
0
     error,
4198
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4199
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4200
0
     "%s: invalid handle - missing descriptor file.",
4201
0
     function );
4202
4203
0
    return( -1 );
4204
0
  }
4205
0
  if( media_size == NULL )
4206
0
  {
4207
0
    libcerror_error_set(
4208
0
     error,
4209
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4210
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4211
0
     "%s: invalid media size.",
4212
0
     function );
4213
4214
0
    return( -1 );
4215
0
  }
4216
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4217
0
  if( libcthreads_read_write_lock_grab_for_read(
4218
0
       internal_handle->read_write_lock,
4219
0
       error ) != 1 )
4220
0
  {
4221
0
    libcerror_error_set(
4222
0
     error,
4223
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4224
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4225
0
     "%s: unable to grab read/write lock for reading.",
4226
0
     function );
4227
4228
0
    return( -1 );
4229
0
  }
4230
0
#endif
4231
0
  *media_size = internal_handle->descriptor_file->media_size;
4232
4233
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4234
0
  if( libcthreads_read_write_lock_release_for_read(
4235
0
       internal_handle->read_write_lock,
4236
0
       error ) != 1 )
4237
0
  {
4238
0
    libcerror_error_set(
4239
0
     error,
4240
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4241
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4242
0
     "%s: unable to release read/write lock for reading.",
4243
0
     function );
4244
4245
0
    return( -1 );
4246
0
  }
4247
0
#endif
4248
0
  return( 1 );
4249
0
}
4250
4251
/* Retrieves the content identifier
4252
 * Returns 1 if successful or -1 on error
4253
 */
4254
int libvmdk_handle_get_content_identifier(
4255
     libvmdk_handle_t *handle,
4256
     uint32_t *content_identifier,
4257
     libcerror_error_t **error )
4258
0
{
4259
0
  libvmdk_internal_handle_t *internal_handle = NULL;
4260
0
  static char *function                      = "libvmdk_handle_get_content_identifier";
4261
4262
0
  if( handle == NULL )
4263
0
  {
4264
0
    libcerror_error_set(
4265
0
     error,
4266
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4267
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4268
0
     "%s: invalid handle.",
4269
0
     function );
4270
4271
0
    return( -1 );
4272
0
  }
4273
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
4274
4275
0
  if( internal_handle->descriptor_file == NULL )
4276
0
  {
4277
0
    libcerror_error_set(
4278
0
     error,
4279
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4280
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4281
0
     "%s: invalid handle - missing descriptor file.",
4282
0
     function );
4283
4284
0
    return( -1 );
4285
0
  }
4286
0
  if( content_identifier == NULL )
4287
0
  {
4288
0
    libcerror_error_set(
4289
0
     error,
4290
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4291
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4292
0
     "%s: invalid content identifier.",
4293
0
     function );
4294
4295
0
    return( -1 );
4296
0
  }
4297
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4298
0
  if( libcthreads_read_write_lock_grab_for_read(
4299
0
       internal_handle->read_write_lock,
4300
0
       error ) != 1 )
4301
0
  {
4302
0
    libcerror_error_set(
4303
0
     error,
4304
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4305
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4306
0
     "%s: unable to grab read/write lock for reading.",
4307
0
     function );
4308
4309
0
    return( -1 );
4310
0
  }
4311
0
#endif
4312
0
  *content_identifier = internal_handle->descriptor_file->content_identifier;
4313
4314
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4315
0
  if( libcthreads_read_write_lock_release_for_read(
4316
0
       internal_handle->read_write_lock,
4317
0
       error ) != 1 )
4318
0
  {
4319
0
    libcerror_error_set(
4320
0
     error,
4321
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4322
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4323
0
     "%s: unable to release read/write lock for reading.",
4324
0
     function );
4325
4326
0
    return( -1 );
4327
0
  }
4328
0
#endif
4329
0
  return( 1 );
4330
0
}
4331
4332
/* Retrieves the parent content identifier
4333
 * Returns 1 if successful, 0 if not available or -1 on error
4334
 */
4335
int libvmdk_handle_get_parent_content_identifier(
4336
     libvmdk_handle_t *handle,
4337
     uint32_t *parent_content_identifier,
4338
     libcerror_error_t **error )
4339
0
{
4340
0
  libvmdk_internal_handle_t *internal_handle = NULL;
4341
0
  static char *function                      = "libvmdk_handle_get_parent_content_identifier";
4342
0
  int result                                 = 0;
4343
4344
0
  if( handle == NULL )
4345
0
  {
4346
0
    libcerror_error_set(
4347
0
     error,
4348
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4349
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4350
0
     "%s: invalid handle.",
4351
0
     function );
4352
4353
0
    return( -1 );
4354
0
  }
4355
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
4356
4357
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4358
0
  if( libcthreads_read_write_lock_grab_for_read(
4359
0
       internal_handle->read_write_lock,
4360
0
       error ) != 1 )
4361
0
  {
4362
0
    libcerror_error_set(
4363
0
     error,
4364
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4365
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4366
0
     "%s: unable to grab read/write lock for reading.",
4367
0
     function );
4368
4369
0
    return( -1 );
4370
0
  }
4371
0
#endif
4372
0
  result = libvmdk_descriptor_file_get_parent_content_identifier(
4373
0
            internal_handle->descriptor_file,
4374
0
            parent_content_identifier,
4375
0
            error );
4376
4377
0
  if( result == -1 )
4378
0
  {
4379
0
    libcerror_error_set(
4380
0
     error,
4381
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4382
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4383
0
     "%s: unable to retrieve parent content identifier.",
4384
0
     function );
4385
4386
0
    result = -1;
4387
0
  }
4388
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4389
0
  if( libcthreads_read_write_lock_release_for_read(
4390
0
       internal_handle->read_write_lock,
4391
0
       error ) != 1 )
4392
0
  {
4393
0
    libcerror_error_set(
4394
0
     error,
4395
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4396
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4397
0
     "%s: unable to release read/write lock for reading.",
4398
0
     function );
4399
4400
0
    return( -1 );
4401
0
  }
4402
0
#endif
4403
0
  return( result );
4404
0
}
4405
4406
/* Retrieves the size of the UTF-8 encoded parent filename
4407
 * The returned size includes the end of string character
4408
 * Returns 1 if successful, 0 if not available or -1 on error
4409
 */
4410
int libvmdk_handle_get_utf8_parent_filename_size(
4411
     libvmdk_handle_t *handle,
4412
     size_t *utf8_string_size,
4413
     libcerror_error_t **error )
4414
0
{
4415
0
  libvmdk_internal_handle_t *internal_handle = NULL;
4416
0
  static char *function                      = "libvmdk_handle_get_utf8_parent_filename_size";
4417
0
  int result                                 = 0;
4418
4419
0
  if( handle == NULL )
4420
0
  {
4421
0
    libcerror_error_set(
4422
0
     error,
4423
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4424
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4425
0
     "%s: invalid handle.",
4426
0
     function );
4427
4428
0
    return( -1 );
4429
0
  }
4430
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
4431
4432
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4433
0
  if( libcthreads_read_write_lock_grab_for_read(
4434
0
       internal_handle->read_write_lock,
4435
0
       error ) != 1 )
4436
0
  {
4437
0
    libcerror_error_set(
4438
0
     error,
4439
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4440
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4441
0
     "%s: unable to grab read/write lock for reading.",
4442
0
     function );
4443
4444
0
    return( -1 );
4445
0
  }
4446
0
#endif
4447
0
  result = libvmdk_descriptor_file_get_utf8_parent_filename_size(
4448
0
            internal_handle->descriptor_file,
4449
0
            utf8_string_size,
4450
0
            error );
4451
4452
0
  if( result == -1 )
4453
0
  {
4454
0
    libcerror_error_set(
4455
0
     error,
4456
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4457
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4458
0
     "%s: unable to retrieve UTF-8 parent filename size.",
4459
0
     function );
4460
4461
0
    result = -1;
4462
0
  }
4463
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4464
0
  if( libcthreads_read_write_lock_release_for_read(
4465
0
       internal_handle->read_write_lock,
4466
0
       error ) != 1 )
4467
0
  {
4468
0
    libcerror_error_set(
4469
0
     error,
4470
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4471
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4472
0
     "%s: unable to release read/write lock for reading.",
4473
0
     function );
4474
4475
0
    return( -1 );
4476
0
  }
4477
0
#endif
4478
0
  return( result );
4479
0
}
4480
4481
/* Retrieves the UTF-8 encoded parent filename
4482
 * The size should include the end of string character
4483
 * Returns 1 if successful, 0 if not available or -1 on error
4484
 */
4485
int libvmdk_handle_get_utf8_parent_filename(
4486
     libvmdk_handle_t *handle,
4487
     uint8_t *utf8_string,
4488
     size_t utf8_string_size,
4489
     libcerror_error_t **error )
4490
0
{
4491
0
  libvmdk_internal_handle_t *internal_handle = NULL;
4492
0
  static char *function                      = "libvmdk_handle_get_utf8_parent_filename";
4493
0
  int result                                 = 0;
4494
4495
0
  if( handle == NULL )
4496
0
  {
4497
0
    libcerror_error_set(
4498
0
     error,
4499
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4500
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4501
0
     "%s: invalid handle.",
4502
0
     function );
4503
4504
0
    return( -1 );
4505
0
  }
4506
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
4507
4508
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4509
0
  if( libcthreads_read_write_lock_grab_for_read(
4510
0
       internal_handle->read_write_lock,
4511
0
       error ) != 1 )
4512
0
  {
4513
0
    libcerror_error_set(
4514
0
     error,
4515
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4516
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4517
0
     "%s: unable to grab read/write lock for reading.",
4518
0
     function );
4519
4520
0
    return( -1 );
4521
0
  }
4522
0
#endif
4523
0
  result = libvmdk_descriptor_file_get_utf8_parent_filename(
4524
0
            internal_handle->descriptor_file,
4525
0
            utf8_string,
4526
0
            utf8_string_size,
4527
0
            error );
4528
4529
0
  if( result == -1 )
4530
0
  {
4531
0
    libcerror_error_set(
4532
0
     error,
4533
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4534
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4535
0
     "%s: unable to retrieve UTF-8 parent filename.",
4536
0
     function );
4537
4538
0
    result = -1;
4539
0
  }
4540
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4541
0
  if( libcthreads_read_write_lock_release_for_read(
4542
0
       internal_handle->read_write_lock,
4543
0
       error ) != 1 )
4544
0
  {
4545
0
    libcerror_error_set(
4546
0
     error,
4547
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4548
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4549
0
     "%s: unable to release read/write lock for reading.",
4550
0
     function );
4551
4552
0
    return( -1 );
4553
0
  }
4554
0
#endif
4555
0
  return( result );
4556
0
}
4557
4558
/* Retrieves the size of the UTF-16 encoded parent filename
4559
 * The returned size includes the end of string character
4560
 * Returns 1 if successful, 0 if not available or -1 on error
4561
 */
4562
int libvmdk_handle_get_utf16_parent_filename_size(
4563
     libvmdk_handle_t *handle,
4564
     size_t *utf16_string_size,
4565
     libcerror_error_t **error )
4566
0
{
4567
0
  libvmdk_internal_handle_t *internal_handle = NULL;
4568
0
  static char *function                      = "libvmdk_handle_get_utf16_parent_filename_size";
4569
0
  int result                                 = 0;
4570
4571
0
  if( handle == NULL )
4572
0
  {
4573
0
    libcerror_error_set(
4574
0
     error,
4575
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4576
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4577
0
     "%s: invalid handle.",
4578
0
     function );
4579
4580
0
    return( -1 );
4581
0
  }
4582
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
4583
4584
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4585
0
  if( libcthreads_read_write_lock_grab_for_read(
4586
0
       internal_handle->read_write_lock,
4587
0
       error ) != 1 )
4588
0
  {
4589
0
    libcerror_error_set(
4590
0
     error,
4591
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4592
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4593
0
     "%s: unable to grab read/write lock for reading.",
4594
0
     function );
4595
4596
0
    return( -1 );
4597
0
  }
4598
0
#endif
4599
0
  result = libvmdk_descriptor_file_get_utf16_parent_filename_size(
4600
0
            internal_handle->descriptor_file,
4601
0
            utf16_string_size,
4602
0
            error );
4603
4604
0
  if( result == -1 )
4605
0
  {
4606
0
    libcerror_error_set(
4607
0
     error,
4608
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4609
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4610
0
     "%s: unable to retrieve UTF-16 parent filename size.",
4611
0
     function );
4612
4613
0
    result = -1;
4614
0
  }
4615
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4616
0
  if( libcthreads_read_write_lock_release_for_read(
4617
0
       internal_handle->read_write_lock,
4618
0
       error ) != 1 )
4619
0
  {
4620
0
    libcerror_error_set(
4621
0
     error,
4622
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4623
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4624
0
     "%s: unable to release read/write lock for reading.",
4625
0
     function );
4626
4627
0
    return( -1 );
4628
0
  }
4629
0
#endif
4630
0
  return( result );
4631
0
}
4632
4633
/* Retrieves the UTF-16 encoded parent filename
4634
 * The size should include the end of string character
4635
 * Returns 1 if successful, 0 if not available or -1 on error
4636
 */
4637
int libvmdk_handle_get_utf16_parent_filename(
4638
     libvmdk_handle_t *handle,
4639
     uint16_t *utf16_string,
4640
     size_t utf16_string_size,
4641
     libcerror_error_t **error )
4642
0
{
4643
0
  libvmdk_internal_handle_t *internal_handle = NULL;
4644
0
  static char *function                      = "libvmdk_handle_get_utf16_parent_filename";
4645
0
  int result                                 = 0;
4646
4647
0
  if( handle == NULL )
4648
0
  {
4649
0
    libcerror_error_set(
4650
0
     error,
4651
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4652
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4653
0
     "%s: invalid handle.",
4654
0
     function );
4655
4656
0
    return( -1 );
4657
0
  }
4658
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
4659
4660
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4661
0
  if( libcthreads_read_write_lock_grab_for_read(
4662
0
       internal_handle->read_write_lock,
4663
0
       error ) != 1 )
4664
0
  {
4665
0
    libcerror_error_set(
4666
0
     error,
4667
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4668
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4669
0
     "%s: unable to grab read/write lock for reading.",
4670
0
     function );
4671
4672
0
    return( -1 );
4673
0
  }
4674
0
#endif
4675
0
  result = libvmdk_descriptor_file_get_utf16_parent_filename(
4676
0
            internal_handle->descriptor_file,
4677
0
            utf16_string,
4678
0
            utf16_string_size,
4679
0
            error );
4680
4681
0
  if( result == -1 )
4682
0
  {
4683
0
    libcerror_error_set(
4684
0
     error,
4685
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4686
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4687
0
     "%s: unable to retrieve UTF-16 parent filename.",
4688
0
     function );
4689
4690
0
    result = -1;
4691
0
  }
4692
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4693
0
  if( libcthreads_read_write_lock_release_for_read(
4694
0
       internal_handle->read_write_lock,
4695
0
       error ) != 1 )
4696
0
  {
4697
0
    libcerror_error_set(
4698
0
     error,
4699
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4700
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4701
0
     "%s: unable to release read/write lock for reading.",
4702
0
     function );
4703
4704
0
    return( -1 );
4705
0
  }
4706
0
#endif
4707
0
  return( result );
4708
0
}
4709
4710
/* Retrieves the number of extents
4711
 * Returns 1 if successful or -1 on error
4712
 */
4713
int libvmdk_handle_get_number_of_extents(
4714
     libvmdk_handle_t *handle,
4715
     int *number_of_extents,
4716
     libcerror_error_t **error )
4717
0
{
4718
0
  libvmdk_internal_handle_t *internal_handle = NULL;
4719
0
  static char *function                      = "libvmdk_handle_get_number_of_extents";
4720
0
  int result                                 = 1;
4721
4722
0
  if( handle == NULL )
4723
0
  {
4724
0
    libcerror_error_set(
4725
0
     error,
4726
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4727
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4728
0
     "%s: invalid handle.",
4729
0
     function );
4730
4731
0
    return( -1 );
4732
0
  }
4733
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
4734
4735
0
  if( internal_handle->descriptor_file == NULL )
4736
0
  {
4737
0
    libcerror_error_set(
4738
0
     error,
4739
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4740
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4741
0
     "%s: invalid handle - missing descriptor file.",
4742
0
     function );
4743
4744
0
    return( -1 );
4745
0
  }
4746
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4747
0
  if( libcthreads_read_write_lock_grab_for_read(
4748
0
       internal_handle->read_write_lock,
4749
0
       error ) != 1 )
4750
0
  {
4751
0
    libcerror_error_set(
4752
0
     error,
4753
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4754
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4755
0
     "%s: unable to grab read/write lock for reading.",
4756
0
     function );
4757
4758
0
    return( -1 );
4759
0
  }
4760
0
#endif
4761
0
  if( libcdata_array_get_number_of_entries(
4762
0
       internal_handle->extent_values_array,
4763
0
       number_of_extents,
4764
0
       error ) != 1 )
4765
0
  {
4766
0
    libcerror_error_set(
4767
0
     error,
4768
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4769
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4770
0
     "%s: unable to retrieve number of extents.",
4771
0
     function );
4772
4773
0
    result = -1;
4774
0
  }
4775
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4776
0
  if( libcthreads_read_write_lock_release_for_read(
4777
0
       internal_handle->read_write_lock,
4778
0
       error ) != 1 )
4779
0
  {
4780
0
    libcerror_error_set(
4781
0
     error,
4782
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4783
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4784
0
     "%s: unable to release read/write lock for reading.",
4785
0
     function );
4786
4787
0
    return( -1 );
4788
0
  }
4789
0
#endif
4790
0
  return( result );
4791
0
}
4792
4793
/* Retrieves a specific extent descriptor
4794
 * Returns 1 if successful or -1 on error
4795
 */
4796
int libvmdk_handle_get_extent_descriptor(
4797
     libvmdk_handle_t *handle,
4798
     int extent_index,
4799
     libvmdk_extent_descriptor_t **extent_descriptor,
4800
     libcerror_error_t **error )
4801
0
{
4802
0
  libvmdk_extent_values_t *extent_values     = NULL;
4803
0
  libvmdk_internal_handle_t *internal_handle = NULL;
4804
0
  static char *function                      = "libvmdk_handle_get_extent_descriptor";
4805
0
  int result                                 = 1;
4806
4807
0
  if( handle == NULL )
4808
0
  {
4809
0
    libcerror_error_set(
4810
0
     error,
4811
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4812
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4813
0
     "%s: invalid handle.",
4814
0
     function );
4815
4816
0
    return( -1 );
4817
0
  }
4818
0
  internal_handle = (libvmdk_internal_handle_t *) handle;
4819
4820
0
  if( internal_handle->descriptor_file == NULL )
4821
0
  {
4822
0
    libcerror_error_set(
4823
0
     error,
4824
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4825
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4826
0
     "%s: invalid handle - missing descriptor file.",
4827
0
     function );
4828
4829
0
    return( -1 );
4830
0
  }
4831
0
  if( extent_descriptor == NULL )
4832
0
  {
4833
0
    libcerror_error_set(
4834
0
     error,
4835
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4836
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4837
0
     "%s: invalid extent descriptor.",
4838
0
     function );
4839
4840
0
    return( -1 );
4841
0
  }
4842
0
  if( *extent_descriptor != NULL )
4843
0
  {
4844
0
    libcerror_error_set(
4845
0
     error,
4846
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4847
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
4848
0
     "%s: invalid extent descriptor value already set.",
4849
0
     function );
4850
4851
0
    return( -1 );
4852
0
  }
4853
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4854
0
  if( libcthreads_read_write_lock_grab_for_read(
4855
0
       internal_handle->read_write_lock,
4856
0
       error ) != 1 )
4857
0
  {
4858
0
    libcerror_error_set(
4859
0
     error,
4860
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4861
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4862
0
     "%s: unable to grab read/write lock for reading.",
4863
0
     function );
4864
4865
0
    return( -1 );
4866
0
  }
4867
0
#endif
4868
0
  if( libcdata_array_get_entry_by_index(
4869
0
       internal_handle->extent_values_array,
4870
0
       extent_index,
4871
0
       (intptr_t **) &extent_values,
4872
0
       error ) != 1 )
4873
0
  {
4874
0
    libcerror_error_set(
4875
0
     error,
4876
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4877
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4878
0
     "%s: unable to retrieve extent: %d from array.",
4879
0
     function,
4880
0
     extent_index );
4881
4882
0
    result = -1;
4883
0
  }
4884
0
  else if( libvmdk_extent_descriptor_initialize(
4885
0
            extent_descriptor,
4886
0
            extent_values,
4887
0
            error ) != 1 )
4888
0
  {
4889
0
    libcerror_error_set(
4890
0
     error,
4891
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4892
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4893
0
     "%s: unable to create extent descriptor.",
4894
0
     function );
4895
4896
0
    result = -1;
4897
0
  }
4898
0
#if defined( HAVE_LIBVMDK_MULTI_THREAD_SUPPORT )
4899
0
  if( libcthreads_read_write_lock_release_for_read(
4900
0
       internal_handle->read_write_lock,
4901
0
       error ) != 1 )
4902
0
  {
4903
0
    libcerror_error_set(
4904
0
     error,
4905
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4906
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4907
0
     "%s: unable to release read/write lock for reading.",
4908
0
     function );
4909
4910
0
    return( -1 );
4911
0
  }
4912
0
#endif
4913
0
  return( result );
4914
0
}
4915