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