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