1 /*
2 * Extent table 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_definitions.h"
30 #include "libvmdk_extent_descriptor.h"
31 #include "libvmdk_extent_file.h"
32 #include "libvmdk_extent_table.h"
33 #include "libvmdk_libbfio.h"
34 #include "libvmdk_libcdata.h"
35 #include "libvmdk_libcerror.h"
36 #include "libvmdk_libfcache.h"
37 #include "libvmdk_libfdata.h"
38 #include "libvmdk_system_string.h"
39
40 /* Creates an extent table
41 * Make sure the value extent_table is referencing, is set to NULL
42 * Returns 1 if successful or -1 on error
43 */
libvmdk_extent_table_initialize(libvmdk_extent_table_t ** extent_table,libvmdk_io_handle_t * io_handle,libcerror_error_t ** error)44 int libvmdk_extent_table_initialize(
45 libvmdk_extent_table_t **extent_table,
46 libvmdk_io_handle_t *io_handle,
47 libcerror_error_t **error )
48 {
49 static char *function = "libvmdk_extent_table_initialize";
50
51 if( extent_table == NULL )
52 {
53 libcerror_error_set(
54 error,
55 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
56 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
57 "%s: invalid extent table.",
58 function );
59
60 return( -1 );
61 }
62 if( *extent_table != NULL )
63 {
64 libcerror_error_set(
65 error,
66 LIBCERROR_ERROR_DOMAIN_RUNTIME,
67 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
68 "%s: invalid extent table value already set.",
69 function );
70
71 return( -1 );
72 }
73 if( io_handle == NULL )
74 {
75 libcerror_error_set(
76 error,
77 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
78 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
79 "%s: invalid IO handle.",
80 function );
81
82 return( -1 );
83 }
84 *extent_table = memory_allocate_structure(
85 libvmdk_extent_table_t );
86
87 if( *extent_table == NULL )
88 {
89 libcerror_error_set(
90 error,
91 LIBCERROR_ERROR_DOMAIN_MEMORY,
92 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
93 "%s: unable to create extent table.",
94 function );
95
96 goto on_error;
97 }
98 if( memory_set(
99 *extent_table,
100 0,
101 sizeof( libvmdk_extent_table_t ) ) == NULL )
102 {
103 libcerror_error_set(
104 error,
105 LIBCERROR_ERROR_DOMAIN_MEMORY,
106 LIBCERROR_MEMORY_ERROR_SET_FAILED,
107 "%s: unable to clear extent table.",
108 function );
109
110 goto on_error;
111 }
112 ( *extent_table )->io_handle = io_handle;
113
114 return( 1 );
115
116 on_error:
117 if( *extent_table != NULL )
118 {
119 memory_free(
120 *extent_table );
121
122 *extent_table = NULL;
123 }
124 return( -1 );
125 }
126
127 /* Frees an extent table
128 * Returns 1 if successful or -1 on error
129 */
libvmdk_extent_table_free(libvmdk_extent_table_t ** extent_table,libcerror_error_t ** error)130 int libvmdk_extent_table_free(
131 libvmdk_extent_table_t **extent_table,
132 libcerror_error_t **error )
133 {
134 static char *function = "libvmdk_extent_table_free";
135 int result = 1;
136
137 if( extent_table == NULL )
138 {
139 libcerror_error_set(
140 error,
141 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
142 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
143 "%s: invalid extent table.",
144 function );
145
146 return( -1 );
147 }
148 if( *extent_table != NULL )
149 {
150 if( libvmdk_extent_table_clear(
151 *extent_table,
152 error ) != 1 )
153 {
154 libcerror_error_set(
155 error,
156 LIBCERROR_ERROR_DOMAIN_RUNTIME,
157 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
158 "%s: unable to clear extent table.",
159 function );
160
161 result = -1;
162 }
163 memory_free(
164 *extent_table );
165
166 *extent_table = NULL;
167 }
168 return( result );
169 }
170
171 /* Clears the extent table
172 * Returns 1 if successful or -1 on error
173 */
libvmdk_extent_table_clear(libvmdk_extent_table_t * extent_table,libcerror_error_t ** error)174 int libvmdk_extent_table_clear(
175 libvmdk_extent_table_t *extent_table,
176 libcerror_error_t **error )
177 {
178 static char *function = "libvmdk_extent_table_clear";
179 int result = 1;
180
181 if( extent_table == NULL )
182 {
183 libcerror_error_set(
184 error,
185 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
186 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
187 "%s: invalid extent table.",
188 function );
189
190 return( -1 );
191 }
192 if( extent_table->data_files_path != NULL )
193 {
194 memory_free(
195 extent_table->data_files_path );
196
197 extent_table->data_files_path = NULL;
198 extent_table->data_files_path_size = 0;
199 }
200 if( extent_table->extent_files_list != NULL )
201 {
202 if( libfdata_list_free(
203 &( extent_table->extent_files_list ),
204 error ) != 1 )
205 {
206 libcerror_error_set(
207 error,
208 LIBCERROR_ERROR_DOMAIN_RUNTIME,
209 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
210 "%s: unable to free extent files list.",
211 function );
212
213 result = -1;
214 }
215 }
216 if( extent_table->extent_files_cache != NULL )
217 {
218 if( libfcache_cache_free(
219 &( extent_table->extent_files_cache ),
220 error ) != 1 )
221 {
222 libcerror_error_set(
223 error,
224 LIBCERROR_ERROR_DOMAIN_RUNTIME,
225 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
226 "%s: unable to free extent files cache.",
227 function );
228
229 result = -1;
230 }
231 }
232 if( extent_table->extent_files_stream != NULL )
233 {
234 if( libfdata_stream_free(
235 &( extent_table->extent_files_stream ),
236 error ) != 1 )
237 {
238 libcerror_error_set(
239 error,
240 LIBCERROR_ERROR_DOMAIN_RUNTIME,
241 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
242 "%s: unable to free extent files stream.",
243 function );
244
245 result = -1;
246 }
247 }
248 if( memory_set(
249 extent_table,
250 0,
251 sizeof( libvmdk_extent_table_t ) ) == NULL )
252 {
253 libcerror_error_set(
254 error,
255 LIBCERROR_ERROR_DOMAIN_MEMORY,
256 LIBCERROR_MEMORY_ERROR_SET_FAILED,
257 "%s: unable to extent table.",
258 function );
259
260 result = -1;
261 }
262 return( result );
263 }
264
265 /* Clones the extent table
266 * Returns 1 if successful or -1 on error
267 */
libvmdk_extent_table_clone(libvmdk_extent_table_t ** destination_extent_table,libvmdk_extent_table_t * source_extent_table,libcerror_error_t ** error)268 int libvmdk_extent_table_clone(
269 libvmdk_extent_table_t **destination_extent_table,
270 libvmdk_extent_table_t *source_extent_table,
271 libcerror_error_t **error )
272 {
273 static char *function = "libvmdk_extent_table_clone";
274
275 if( destination_extent_table == NULL )
276 {
277 libcerror_error_set(
278 error,
279 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
280 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
281 "%s: invalid destination extent table.",
282 function );
283
284 return( -1 );
285 }
286 if( *destination_extent_table != NULL )
287 {
288 libcerror_error_set(
289 error,
290 LIBCERROR_ERROR_DOMAIN_RUNTIME,
291 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
292 "%s: invalid destination extent table value already set.",
293 function );
294
295 return( -1 );
296 }
297 if( source_extent_table == NULL )
298 {
299 *destination_extent_table = NULL;
300
301 return( 1 );
302 }
303 *destination_extent_table = memory_allocate_structure(
304 libvmdk_extent_table_t );
305
306 if( *destination_extent_table == NULL )
307 {
308 libcerror_error_set(
309 error,
310 LIBCERROR_ERROR_DOMAIN_MEMORY,
311 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
312 "%s: unable to create destination extent table.",
313 function );
314
315 goto on_error;
316 }
317 if( memory_set(
318 *destination_extent_table,
319 0,
320 sizeof( libvmdk_extent_table_t ) ) == NULL )
321 {
322 libcerror_error_set(
323 error,
324 LIBCERROR_ERROR_DOMAIN_MEMORY,
325 LIBCERROR_MEMORY_ERROR_SET_FAILED,
326 "%s: unable to clear source to destination extent table.",
327 function );
328
329 memory_free(
330 *destination_extent_table );
331
332 *destination_extent_table = NULL;
333
334 return( -1 );
335 }
336 if( source_extent_table->data_files_path != NULL )
337 {
338 ( *destination_extent_table )->data_files_path = system_string_allocate(
339 source_extent_table->data_files_path_size );
340
341 if( *destination_extent_table == NULL )
342 {
343 libcerror_error_set(
344 error,
345 LIBCERROR_ERROR_DOMAIN_MEMORY,
346 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
347 "%s: unable to create destination extent table.",
348 function );
349
350 goto on_error;
351 }
352 if( memory_copy(
353 ( *destination_extent_table )->data_files_path,
354 source_extent_table->data_files_path,
355 sizeof( system_character_t ) * source_extent_table->data_files_path_size ) == NULL )
356 {
357 libcerror_error_set(
358 error,
359 LIBCERROR_ERROR_DOMAIN_MEMORY,
360 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
361 "%s: unable to copy source to destination data files path.",
362 function );
363
364 goto on_error;
365 }
366 ( *destination_extent_table )->data_files_path_size = source_extent_table->data_files_path_size;
367 }
368 if( libfdata_list_clone(
369 &( ( *destination_extent_table )->extent_files_list ),
370 source_extent_table->extent_files_list,
371 error ) != 1 )
372 {
373 libcerror_error_set(
374 error,
375 LIBCERROR_ERROR_DOMAIN_RUNTIME,
376 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
377 "%s: unable to create destination extent files list.",
378 function );
379
380 goto on_error;
381 }
382 if( libfcache_cache_clone(
383 &( ( *destination_extent_table )->extent_files_cache ),
384 source_extent_table->extent_files_cache,
385 error ) != 1 )
386 {
387 libcerror_error_set(
388 error,
389 LIBCERROR_ERROR_DOMAIN_RUNTIME,
390 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
391 "%s: unable to create destination extent files cache.",
392 function );
393
394 goto on_error;
395 }
396 if( libfdata_stream_clone(
397 &( ( *destination_extent_table )->extent_files_stream ),
398 source_extent_table->extent_files_stream,
399 error ) != 1 )
400 {
401 libcerror_error_set(
402 error,
403 LIBCERROR_ERROR_DOMAIN_RUNTIME,
404 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
405 "%s: unable to create destination extent files stream.",
406 function );
407
408 goto on_error;
409 }
410 return( 1 );
411
412 on_error:
413 if( *destination_extent_table != NULL )
414 {
415 if( ( *destination_extent_table )->extent_files_cache != NULL )
416 {
417 libfcache_cache_free(
418 &( ( *destination_extent_table )->extent_files_cache ),
419 NULL );
420 }
421 if( ( *destination_extent_table )->extent_files_list != NULL )
422 {
423 libfdata_list_free(
424 &( ( *destination_extent_table )->extent_files_list ),
425 NULL );
426 }
427 if( ( *destination_extent_table )->data_files_path != NULL )
428 {
429 memory_free(
430 ( *destination_extent_table )->data_files_path );
431 }
432 memory_free(
433 *destination_extent_table );
434
435 *destination_extent_table = NULL;
436 }
437 return( -1 );
438 }
439
440 /* Retrieves the size of the data file_path
441 * Returns 1 if successful, 0 if value not present or -1 on error
442 */
libvmdk_extent_table_get_data_files_path_size(libvmdk_extent_table_t * extent_table,size_t * path_size,libcerror_error_t ** error)443 int libvmdk_extent_table_get_data_files_path_size(
444 libvmdk_extent_table_t *extent_table,
445 size_t *path_size,
446 libcerror_error_t **error )
447 {
448 static char *function = "libvmdk_extent_table_get_data_files_path_size";
449
450 if( extent_table == NULL )
451 {
452 libcerror_error_set(
453 error,
454 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
455 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
456 "%s: invalid extent table.",
457 function );
458
459 return( -1 );
460 }
461 if( extent_table->data_files_path == NULL )
462 {
463 return( 0 );
464 }
465 if( libvmdk_system_string_size_to_narrow_string(
466 extent_table->data_files_path,
467 extent_table->data_files_path_size,
468 path_size,
469 error ) != 1 )
470 {
471 libcerror_error_set(
472 error,
473 LIBCERROR_ERROR_DOMAIN_CONVERSION,
474 LIBCERROR_CONVERSION_ERROR_GENERIC,
475 "%s: unable to determine data files path size.",
476 function );
477
478 return( -1 );
479 }
480 return( 1 );
481 }
482
483 /* Retrieves the data files path
484 * Returns 1 if successful, 0 if value not present or -1 on error
485 */
libvmdk_extent_table_get_data_files_path(libvmdk_extent_table_t * extent_table,char * path,size_t path_size,libcerror_error_t ** error)486 int libvmdk_extent_table_get_data_files_path(
487 libvmdk_extent_table_t *extent_table,
488 char *path,
489 size_t path_size,
490 libcerror_error_t **error )
491 {
492 static char *function = "libvmdk_extent_table_get_data_files_path";
493 size_t narrow_path_size = 0;
494
495 if( extent_table == NULL )
496 {
497 libcerror_error_set(
498 error,
499 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
500 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
501 "%s: invalid extent table.",
502 function );
503
504 return( -1 );
505 }
506 if( path == NULL )
507 {
508 libcerror_error_set(
509 error,
510 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
511 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
512 "%s: invalid path.",
513 function );
514
515 return( -1 );
516 }
517 if( path_size > (size_t) SSIZE_MAX )
518 {
519 libcerror_error_set(
520 error,
521 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
522 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
523 "%s: invalid path size value exceeds maximum.",
524 function );
525
526 return( -1 );
527 }
528 if( extent_table->data_files_path == NULL )
529 {
530 return( 0 );
531 }
532 if( libvmdk_system_string_size_to_narrow_string(
533 extent_table->data_files_path,
534 extent_table->data_files_path_size,
535 &narrow_path_size,
536 error ) != 1 )
537 {
538 libcerror_error_set(
539 error,
540 LIBCERROR_ERROR_DOMAIN_CONVERSION,
541 LIBCERROR_CONVERSION_ERROR_GENERIC,
542 "%s: unable to determine data files path size.",
543 function );
544
545 return( -1 );
546 }
547 if( path_size < narrow_path_size )
548 {
549 libcerror_error_set(
550 error,
551 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
552 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
553 "%s: path too small.",
554 function );
555
556 return( -1 );
557 }
558 if( libvmdk_system_string_copy_to_narrow_string(
559 extent_table->data_files_path,
560 extent_table->data_files_path_size,
561 path,
562 path_size,
563 error ) != 1 )
564 {
565 libcerror_error_set(
566 error,
567 LIBCERROR_ERROR_DOMAIN_CONVERSION,
568 LIBCERROR_CONVERSION_ERROR_GENERIC,
569 "%s: unable to set data files path.",
570 function );
571
572 return( -1 );
573 }
574 return( 1 );
575 }
576
577 /* Sets the data files path
578 * Returns 1 if successful or -1 on error
579 */
libvmdk_extent_table_set_data_files_path(libvmdk_extent_table_t * extent_table,const char * path,size_t path_length,libcerror_error_t ** error)580 int libvmdk_extent_table_set_data_files_path(
581 libvmdk_extent_table_t *extent_table,
582 const char *path,
583 size_t path_length,
584 libcerror_error_t **error )
585 {
586 static char *function = "libvmdk_extent_table_set_data_files_path";
587
588 if( extent_table == NULL )
589 {
590 libcerror_error_set(
591 error,
592 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
593 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
594 "%s: invalid extent table.",
595 function );
596
597 return( -1 );
598 }
599 if( path == NULL )
600 {
601 libcerror_error_set(
602 error,
603 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
604 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
605 "%s: invalid path.",
606 function );
607
608 return( -1 );
609 }
610 if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
611 {
612 libcerror_error_set(
613 error,
614 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
615 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
616 "%s: invalid path length value exceeds maximum.",
617 function );
618
619 return( -1 );
620 }
621 if( extent_table->data_files_path != NULL )
622 {
623 memory_free(
624 extent_table->data_files_path );
625
626 extent_table->data_files_path = NULL;
627 extent_table->data_files_path_size = 0;
628 }
629 if( libvmdk_system_string_size_from_narrow_string(
630 path,
631 path_length + 1,
632 &( extent_table->data_files_path_size ),
633 error ) != 1 )
634 {
635 libcerror_error_set(
636 error,
637 LIBCERROR_ERROR_DOMAIN_CONVERSION,
638 LIBCERROR_CONVERSION_ERROR_GENERIC,
639 "%s: unable to determine data files path size.",
640 function );
641
642 goto on_error;
643 }
644 extent_table->data_files_path = system_string_allocate(
645 extent_table->data_files_path_size );
646
647 if( extent_table->data_files_path == NULL )
648 {
649 libcerror_error_set(
650 error,
651 LIBCERROR_ERROR_DOMAIN_MEMORY,
652 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
653 "%s: unable to create data files path.",
654 function );
655
656 goto on_error;
657 }
658 if( libvmdk_system_string_copy_from_narrow_string(
659 extent_table->data_files_path,
660 extent_table->data_files_path_size,
661 path,
662 path_length + 1,
663 error ) != 1 )
664 {
665 libcerror_error_set(
666 error,
667 LIBCERROR_ERROR_DOMAIN_CONVERSION,
668 LIBCERROR_CONVERSION_ERROR_GENERIC,
669 "%s: unable to set data files path.",
670 function );
671
672 goto on_error;
673 }
674 return( 1 );
675
676 on_error:
677 if( extent_table->data_files_path != NULL )
678 {
679 memory_free(
680 extent_table->data_files_path );
681
682 extent_table->data_files_path = NULL;
683 }
684 extent_table->data_files_path_size = 0;
685
686 return( -1 );
687 }
688
689 #if defined( HAVE_WIDE_CHARACTER_TYPE )
690
691 /* Retrieves the size of the data files path
692 * Returns 1 if successful, 0 if value not present or -1 on error
693 */
libvmdk_extent_table_get_data_files_path_size_wide(libvmdk_extent_table_t * extent_table,size_t * path_size,libcerror_error_t ** error)694 int libvmdk_extent_table_get_data_files_path_size_wide(
695 libvmdk_extent_table_t *extent_table,
696 size_t *path_size,
697 libcerror_error_t **error )
698 {
699 static char *function = "libvmdk_extent_table_get_data_files_path_size_wide";
700
701 if( extent_table == NULL )
702 {
703 libcerror_error_set(
704 error,
705 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
706 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
707 "%s: invalid extent table.",
708 function );
709
710 return( -1 );
711 }
712 if( path_size == NULL )
713 {
714 libcerror_error_set(
715 error,
716 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
717 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
718 "%s: invalid path size.",
719 function );
720
721 return( -1 );
722 }
723 if( extent_table->data_files_path == NULL )
724 {
725 return( 0 );
726 }
727 if( libvmdk_system_string_size_to_wide_string(
728 extent_table->data_files_path,
729 extent_table->data_files_path_size,
730 path_size,
731 error ) != 1 )
732 {
733 libcerror_error_set(
734 error,
735 LIBCERROR_ERROR_DOMAIN_CONVERSION,
736 LIBCERROR_CONVERSION_ERROR_GENERIC,
737 "%s: unable to determine data files path size.",
738 function );
739
740 return( -1 );
741 }
742 return( 1 );
743 }
744
745 /* Retrieves the data files path
746 * Returns 1 if successful, 0 if value not present or -1 on error
747 */
libvmdk_extent_table_get_data_files_path_wide(libvmdk_extent_table_t * extent_table,wchar_t * path,size_t path_size,libcerror_error_t ** error)748 int libvmdk_extent_table_get_data_files_path_wide(
749 libvmdk_extent_table_t *extent_table,
750 wchar_t *path,
751 size_t path_size,
752 libcerror_error_t **error )
753 {
754 static char *function = "libvmdk_extent_table_get_data_files_path_wide";
755 size_t wide_path_size = 0;
756
757 if( extent_table == NULL )
758 {
759 libcerror_error_set(
760 error,
761 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
762 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
763 "%s: invalid extent table.",
764 function );
765
766 return( -1 );
767 }
768 if( path == NULL )
769 {
770 libcerror_error_set(
771 error,
772 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
773 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
774 "%s: invalid path.",
775 function );
776
777 return( -1 );
778 }
779 if( path_size > (size_t) SSIZE_MAX )
780 {
781 libcerror_error_set(
782 error,
783 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
784 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
785 "%s: invalid path size value exceeds maximum.",
786 function );
787
788 return( -1 );
789 }
790 if( extent_table->data_files_path == NULL )
791 {
792 return( 0 );
793 }
794 if( libvmdk_system_string_size_to_wide_string(
795 extent_table->data_files_path,
796 extent_table->data_files_path_size,
797 &wide_path_size,
798 error ) != 1 )
799 {
800 libcerror_error_set(
801 error,
802 LIBCERROR_ERROR_DOMAIN_CONVERSION,
803 LIBCERROR_CONVERSION_ERROR_GENERIC,
804 "%s: unable to determine data files path size.",
805 function );
806
807 return( -1 );
808 }
809 if( path_size < wide_path_size )
810 {
811 libcerror_error_set(
812 error,
813 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
814 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
815 "%s: path too small.",
816 function );
817
818 return( -1 );
819 }
820 if( libvmdk_system_string_copy_to_wide_string(
821 extent_table->data_files_path,
822 extent_table->data_files_path_size,
823 path,
824 path_size,
825 error ) != 1 )
826 {
827 libcerror_error_set(
828 error,
829 LIBCERROR_ERROR_DOMAIN_CONVERSION,
830 LIBCERROR_CONVERSION_ERROR_GENERIC,
831 "%s: unable to set data files path.",
832 function );
833
834 return( -1 );
835 }
836 return( 1 );
837 }
838
839 /* Sets the data files path
840 * Returns 1 if successful or -1 on error
841 */
libvmdk_extent_table_set_data_files_path_wide(libvmdk_extent_table_t * extent_table,const wchar_t * path,size_t path_length,libcerror_error_t ** error)842 int libvmdk_extent_table_set_data_files_path_wide(
843 libvmdk_extent_table_t *extent_table,
844 const wchar_t *path,
845 size_t path_length,
846 libcerror_error_t **error )
847 {
848 static char *function = "libvmdk_extent_table_set_data_files_path_wide";
849
850 if( extent_table == NULL )
851 {
852 libcerror_error_set(
853 error,
854 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
855 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
856 "%s: invalid extent table.",
857 function );
858
859 return( -1 );
860 }
861 if( path == NULL )
862 {
863 libcerror_error_set(
864 error,
865 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
866 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
867 "%s: invalid path.",
868 function );
869
870 return( -1 );
871 }
872 if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
873 {
874 libcerror_error_set(
875 error,
876 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
877 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
878 "%s: invalid path length value exceeds maximum.",
879 function );
880
881 return( -1 );
882 }
883 if( extent_table->data_files_path != NULL )
884 {
885 memory_free(
886 extent_table->data_files_path );
887
888 extent_table->data_files_path = NULL;
889 extent_table->data_files_path_size = 0;
890 }
891 if( libvmdk_system_string_size_from_wide_string(
892 path,
893 path_length + 1,
894 &( extent_table->data_files_path_size ),
895 error ) != 1 )
896 {
897 libcerror_error_set(
898 error,
899 LIBCERROR_ERROR_DOMAIN_CONVERSION,
900 LIBCERROR_CONVERSION_ERROR_GENERIC,
901 "%s: unable to determine data files path size.",
902 function );
903
904 goto on_error;
905 }
906 extent_table->data_files_path = system_string_allocate(
907 extent_table->data_files_path_size );
908
909 if( extent_table->data_files_path == NULL )
910 {
911 libcerror_error_set(
912 error,
913 LIBCERROR_ERROR_DOMAIN_MEMORY,
914 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
915 "%s: unable to create data files path.",
916 function );
917
918 goto on_error;
919 }
920 if( libvmdk_system_string_copy_from_wide_string(
921 extent_table->data_files_path,
922 extent_table->data_files_path_size,
923 path,
924 path_length + 1,
925 error ) != 1 )
926 {
927 libcerror_error_set(
928 error,
929 LIBCERROR_ERROR_DOMAIN_CONVERSION,
930 LIBCERROR_CONVERSION_ERROR_GENERIC,
931 "%s: unable to set data files path.",
932 function );
933
934 goto on_error;
935 }
936 return( 1 );
937
938 on_error:
939 if( extent_table->data_files_path != NULL )
940 {
941 memory_free(
942 extent_table->data_files_path );
943
944 extent_table->data_files_path = NULL;
945 }
946 extent_table->data_files_path_size = 0;
947
948 return( -1 );
949 }
950
951 #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
952
953 /* Initializes the extents
954 * Returns 1 if successful or -1 on error
955 */
libvmdk_extent_table_initialize_extents(libvmdk_extent_table_t * extent_table,int number_of_extents,int disk_type,libcerror_error_t ** error)956 int libvmdk_extent_table_initialize_extents(
957 libvmdk_extent_table_t *extent_table,
958 int number_of_extents,
959 int disk_type,
960 libcerror_error_t **error )
961 {
962 static char *function = "libvmdk_extent_table_initialize_extents";
963 int result = 0;
964
965 if( extent_table == NULL )
966 {
967 libcerror_error_set(
968 error,
969 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
970 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
971 "%s: invalid extent table.",
972 function );
973
974 return( -1 );
975 }
976 if( ( disk_type != LIBVMDK_DISK_TYPE_FLAT_2GB_EXTENT )
977 && ( disk_type != LIBVMDK_DISK_TYPE_MONOLITHIC_FLAT )
978 && ( disk_type != LIBVMDK_DISK_TYPE_SPARSE_2GB_EXTENT )
979 && ( disk_type != LIBVMDK_DISK_TYPE_MONOLITHIC_SPARSE )
980 && ( disk_type != LIBVMDK_DISK_TYPE_STREAM_OPTIMIZED )
981 && ( disk_type != LIBVMDK_DISK_TYPE_VMFS_FLAT )
982 && ( disk_type != LIBVMDK_DISK_TYPE_VMFS_FLAT_PRE_ALLOCATED )
983 && ( disk_type != LIBVMDK_DISK_TYPE_VMFS_FLAT_ZEROED )
984 && ( disk_type != LIBVMDK_DISK_TYPE_VMFS_SPARSE )
985 && ( disk_type != LIBVMDK_DISK_TYPE_VMFS_SPARSE_THIN ) )
986 {
987 libcerror_error_set(
988 error,
989 LIBCERROR_ERROR_DOMAIN_RUNTIME,
990 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
991 "%s: unsupported disk type.",
992 function );
993
994 return( -1 );
995 }
996 if( ( disk_type == LIBVMDK_DISK_TYPE_FLAT_2GB_EXTENT )
997 || ( disk_type == LIBVMDK_DISK_TYPE_MONOLITHIC_FLAT )
998 || ( disk_type == LIBVMDK_DISK_TYPE_VMFS_FLAT )
999 || ( disk_type == LIBVMDK_DISK_TYPE_VMFS_FLAT_PRE_ALLOCATED )
1000 || ( disk_type == LIBVMDK_DISK_TYPE_VMFS_FLAT_ZEROED ) )
1001 {
1002 /* TODO add write support ? */
1003 result = libfdata_stream_initialize(
1004 &( extent_table->extent_files_stream ),
1005 (intptr_t *) extent_table->io_handle,
1006 NULL,
1007 NULL,
1008 NULL,
1009 (ssize_t (*)(intptr_t *, intptr_t *, int, int, uint8_t *, size_t, uint32_t, uint8_t, libcerror_error_t **)) &libvmdk_extent_file_read_segment_data,
1010 NULL,
1011 (off64_t (*)(intptr_t *, intptr_t *, int, int, off64_t, libcerror_error_t **)) &libvmdk_extent_file_seek_segment_offset,
1012 LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
1013 error );
1014
1015 if( result != 1 )
1016 {
1017 libcerror_error_set(
1018 error,
1019 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1020 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1021 "%s: unable to create extent files stream.",
1022 function );
1023
1024 goto on_error;
1025 }
1026 if( libfdata_stream_resize(
1027 extent_table->extent_files_stream,
1028 number_of_extents,
1029 error ) != 1 )
1030 {
1031 libcerror_error_set(
1032 error,
1033 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1034 LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
1035 "%s: unable to resize extents file stream.",
1036 function );
1037
1038 goto on_error;
1039 }
1040 }
1041 else if( ( disk_type == LIBVMDK_DISK_TYPE_SPARSE_2GB_EXTENT )
1042 || ( disk_type == LIBVMDK_DISK_TYPE_MONOLITHIC_SPARSE )
1043 || ( disk_type == LIBVMDK_DISK_TYPE_STREAM_OPTIMIZED )
1044 || ( disk_type == LIBVMDK_DISK_TYPE_VMFS_SPARSE )
1045 || ( disk_type == LIBVMDK_DISK_TYPE_VMFS_SPARSE_THIN ) )
1046 {
1047 /* TODO add write support ? */
1048 result = libfdata_list_initialize(
1049 &( extent_table->extent_files_list ),
1050 (intptr_t *) extent_table->io_handle,
1051 NULL,
1052 NULL,
1053 (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfdata_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libvmdk_extent_file_read_element_data,
1054 NULL,
1055 LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
1056 error );
1057
1058 if( result != 1 )
1059 {
1060 libcerror_error_set(
1061 error,
1062 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1063 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1064 "%s: unable to create extent files list.",
1065 function );
1066
1067 goto on_error;
1068 }
1069 if( libfdata_list_resize(
1070 extent_table->extent_files_list,
1071 number_of_extents,
1072 error ) != 1 )
1073 {
1074 libcerror_error_set(
1075 error,
1076 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1077 LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
1078 "%s: unable to resize extent files list.",
1079 function );
1080
1081 goto on_error;
1082 }
1083 result = libfcache_cache_initialize(
1084 &( extent_table->extent_files_cache ),
1085 LIBVMDK_MAXIMUM_CACHE_ENTRIES_EXTENT_FILES,
1086 error );
1087
1088 if( result != 1 )
1089 {
1090 libcerror_error_set(
1091 error,
1092 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1093 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1094 "%s: unable to create extent files cache.",
1095 function );
1096
1097 goto on_error;
1098 }
1099 }
1100 extent_table->disk_type = disk_type;
1101 extent_table->number_of_extents = number_of_extents;
1102
1103 return( 1 );
1104
1105 on_error:
1106 if( extent_table->extent_files_list != NULL )
1107 {
1108 libfdata_list_free(
1109 &( extent_table->extent_files_list ),
1110 NULL );
1111 }
1112 return( -1 );
1113 }
1114
1115 /* Retrieves the number of extents
1116 * Returns 1 if successful or -1 on error
1117 */
libvmdk_extent_table_get_number_of_extents(libvmdk_extent_table_t * extent_table,int * number_of_extents,libcerror_error_t ** error)1118 int libvmdk_extent_table_get_number_of_extents(
1119 libvmdk_extent_table_t *extent_table,
1120 int *number_of_extents,
1121 libcerror_error_t **error )
1122 {
1123 static char *function = "libvmdk_extent_table_get_number_of_extents";
1124
1125 if( extent_table == NULL )
1126 {
1127 libcerror_error_set(
1128 error,
1129 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1130 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1131 "%s: invalid extent table.",
1132 function );
1133
1134 return( -1 );
1135 }
1136 if( number_of_extents == NULL )
1137 {
1138 libcerror_error_set(
1139 error,
1140 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1141 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1142 "%s: invalid number of extents.",
1143 function );
1144
1145 return( -1 );
1146 }
1147 *number_of_extents = extent_table->number_of_extents;
1148
1149 return( 1 );
1150 }
1151
1152 /* Retrieves a specific extent from the extent table
1153 * Returns 1 if successful or -1 on error
1154 */
libvmdk_extent_table_get_extent_by_index(libvmdk_extent_table_t * extent_table,int extent_index,int * file_io_pool_entry,size64_t * extent_file_size,libcerror_error_t ** error)1155 int libvmdk_extent_table_get_extent_by_index(
1156 libvmdk_extent_table_t *extent_table,
1157 int extent_index,
1158 int *file_io_pool_entry,
1159 size64_t *extent_file_size,
1160 libcerror_error_t **error )
1161 {
1162 static char *function = "libvmdk_extent_table_get_extent_by_index";
1163 off64_t element_offset = 0;
1164 uint32_t element_flags = 0;
1165
1166 if( extent_table == NULL )
1167 {
1168 libcerror_error_set(
1169 error,
1170 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1171 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1172 "%s: invalid extent table.",
1173 function );
1174
1175 return( -1 );
1176 }
1177 if( libfdata_list_get_element_by_index(
1178 extent_table->extent_files_list,
1179 extent_index,
1180 file_io_pool_entry,
1181 &element_offset,
1182 extent_file_size,
1183 &element_flags,
1184 error ) != 1 )
1185 {
1186 libcerror_error_set(
1187 error,
1188 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1189 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1190 "%s: unable to retrieve element: %d from extent files list.",
1191 function,
1192 extent_index );
1193
1194 return( -1 );
1195 }
1196 return( 1 );
1197 }
1198
1199 /* Retrieves an extent at a specific offset from the extent table
1200 * Returns 1 if successful, 0 if not or -1 on error
1201 */
libvmdk_extent_table_get_extent_at_offset(libvmdk_extent_table_t * extent_table,off64_t offset,int * file_io_pool_entry,size64_t * extent_file_size,libcerror_error_t ** error)1202 int libvmdk_extent_table_get_extent_at_offset(
1203 libvmdk_extent_table_t *extent_table,
1204 off64_t offset,
1205 int *file_io_pool_entry,
1206 size64_t *extent_file_size,
1207 libcerror_error_t **error )
1208 {
1209 static char *function = "libvmdk_extent_table_get_extent_at_offset";
1210 off64_t element_offset = 0;
1211 off64_t extent_file_data_offset = 0;
1212 uint32_t element_flags = 0;
1213 int extent_index = 0;
1214 int result = 0;
1215
1216 if( extent_table == NULL )
1217 {
1218 libcerror_error_set(
1219 error,
1220 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1221 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1222 "%s: invalid extent table.",
1223 function );
1224
1225 return( -1 );
1226 }
1227 result = libfdata_list_get_element_at_offset(
1228 extent_table->extent_files_list,
1229 offset,
1230 &extent_index,
1231 &extent_file_data_offset,
1232 file_io_pool_entry,
1233 &element_offset,
1234 extent_file_size,
1235 &element_flags,
1236 error );
1237
1238 if( result == -1 )
1239 {
1240 libcerror_error_set(
1241 error,
1242 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1243 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1244 "%s: unable to retrieve element at offset: %" PRIi64 " from extent files list.",
1245 function,
1246 offset );
1247
1248 return( -1 );
1249 }
1250 return( result );
1251 }
1252
1253 /* Sets the extent storage media size for a specific extent in the extent table
1254 * Returns 1 if successful or -1 on error
1255 */
libvmdk_extent_table_set_extent_storage_media_size_by_index(libvmdk_extent_table_t * extent_table,int extent_index,size64_t storage_media_size,libcerror_error_t ** error)1256 int libvmdk_extent_table_set_extent_storage_media_size_by_index(
1257 libvmdk_extent_table_t *extent_table,
1258 int extent_index,
1259 size64_t storage_media_size,
1260 libcerror_error_t **error )
1261 {
1262 static char *function = "libvmdk_extent_table_set_extent_storage_media_size_by_index";
1263
1264 if( extent_table == NULL )
1265 {
1266 libcerror_error_set(
1267 error,
1268 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1269 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1270 "%s: invalid extent table.",
1271 function );
1272
1273 return( -1 );
1274 }
1275 if( libfdata_list_set_mapped_size_by_index(
1276 extent_table->extent_files_list,
1277 extent_index,
1278 storage_media_size,
1279 error ) != 1 )
1280 {
1281 libcerror_error_set(
1282 error,
1283 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1284 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1285 "%s: unable to set mapped size of element: %d in extent files list.",
1286 function,
1287 extent_index );
1288
1289 return( -1 );
1290 }
1291 return( 1 );
1292 }
1293
1294 /* Retrieves a specific extent file from the extent table
1295 * Returns 1 if successful or -1 on error
1296 */
libvmdk_extent_table_get_extent_file_by_index(libvmdk_extent_table_t * extent_table,int extent_index,libbfio_pool_t * file_io_pool,libvmdk_extent_file_t ** extent_file,libcerror_error_t ** error)1297 int libvmdk_extent_table_get_extent_file_by_index(
1298 libvmdk_extent_table_t *extent_table,
1299 int extent_index,
1300 libbfio_pool_t *file_io_pool,
1301 libvmdk_extent_file_t **extent_file,
1302 libcerror_error_t **error )
1303 {
1304 static char *function = "libvmdk_extent_table_get_extent_file_by_index";
1305
1306 if( extent_table == NULL )
1307 {
1308 libcerror_error_set(
1309 error,
1310 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1311 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1312 "%s: invalid extent table.",
1313 function );
1314
1315 return( -1 );
1316 }
1317 if( libfdata_list_get_element_value_by_index(
1318 extent_table->extent_files_list,
1319 (intptr_t *) file_io_pool,
1320 (libfdata_cache_t *) extent_table->extent_files_cache,
1321 extent_index,
1322 (intptr_t **) extent_file,
1323 0,
1324 error ) != 1 )
1325 {
1326 libcerror_error_set(
1327 error,
1328 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1329 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1330 "%s: unable to retrieve element value: %d from extent files list.",
1331 function,
1332 extent_index );
1333
1334 return( -1 );
1335 }
1336 return( 1 );
1337 }
1338
1339 /* Retrieves an extent file at a specific offset from the extent table
1340 * Returns 1 if successful, 0 if not or -1 on error
1341 */
libvmdk_extent_table_get_extent_file_at_offset(libvmdk_extent_table_t * extent_table,off64_t offset,libbfio_pool_t * file_io_pool,int * extent_index,off64_t * extent_file_data_offset,libvmdk_extent_file_t ** extent_file,libcerror_error_t ** error)1342 int libvmdk_extent_table_get_extent_file_at_offset(
1343 libvmdk_extent_table_t *extent_table,
1344 off64_t offset,
1345 libbfio_pool_t *file_io_pool,
1346 int *extent_index,
1347 off64_t *extent_file_data_offset,
1348 libvmdk_extent_file_t **extent_file,
1349 libcerror_error_t **error )
1350 {
1351 static char *function = "libvmdk_extent_table_get_extent_file_at_offset";
1352 int result = 0;
1353
1354 if( extent_table == NULL )
1355 {
1356 libcerror_error_set(
1357 error,
1358 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1359 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1360 "%s: invalid extent table.",
1361 function );
1362
1363 return( -1 );
1364 }
1365 result = libfdata_list_get_element_value_at_offset(
1366 extent_table->extent_files_list,
1367 (intptr_t *) file_io_pool,
1368 (libfdata_cache_t *) extent_table->extent_files_cache,
1369 offset,
1370 extent_index,
1371 extent_file_data_offset,
1372 (intptr_t **) extent_file,
1373 0,
1374 error );
1375
1376 if( result == -1 )
1377 {
1378 libcerror_error_set(
1379 error,
1380 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1381 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1382 "%s: unable to retrieve element at offset: %" PRIi64 " from extent files list.",
1383 function,
1384 offset );
1385
1386 return( -1 );
1387 }
1388 return( result );
1389 }
1390
1391 /* Sets a specific extent file in the extent table
1392 * Returns 1 if successful or -1 on error
1393 */
libvmdk_extent_table_set_extent_file_by_index(libvmdk_extent_table_t * extent_table,libbfio_pool_t * file_io_pool,int extent_index,libvmdk_extent_file_t * extent_file,libcerror_error_t ** error)1394 int libvmdk_extent_table_set_extent_file_by_index(
1395 libvmdk_extent_table_t *extent_table,
1396 libbfio_pool_t *file_io_pool,
1397 int extent_index,
1398 libvmdk_extent_file_t *extent_file,
1399 libcerror_error_t **error )
1400 {
1401 static char *function = "libvmdk_extent_table_set_extent_file_by_index";
1402
1403 if( extent_table == NULL )
1404 {
1405 libcerror_error_set(
1406 error,
1407 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1408 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1409 "%s: invalid extent table.",
1410 function );
1411
1412 return( -1 );
1413 }
1414 if( libfdata_list_set_element_value_by_index(
1415 extent_table->extent_files_list,
1416 (intptr_t *) file_io_pool,
1417 (libfdata_cache_t *) extent_table->extent_files_cache,
1418 extent_index,
1419 (intptr_t *) extent_file,
1420 (int (*)(intptr_t **, libcerror_error_t **)) &libvmdk_extent_file_free,
1421 LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
1422 error ) != 1 )
1423 {
1424 libcerror_error_set(
1425 error,
1426 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1427 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1428 "%s: unable to set element value: %d extent files list.",
1429 function,
1430 extent_index );
1431
1432 return( -1 );
1433 }
1434 return( 1 );
1435 }
1436
1437 /* Sets an extent in the extent table based on the extent descriptor
1438 * Returns 1 if successful or -1 on error
1439 */
libvmdk_extent_table_set_extent_by_extent_descriptor(libvmdk_extent_table_t * extent_table,libvmdk_internal_extent_descriptor_t * extent_descriptor,int extent_index,int file_io_pool_entry,size64_t extent_file_size,off64_t extent_offset,size64_t extent_size,libcerror_error_t ** error)1440 int libvmdk_extent_table_set_extent_by_extent_descriptor(
1441 libvmdk_extent_table_t *extent_table,
1442 libvmdk_internal_extent_descriptor_t *extent_descriptor,
1443 int extent_index,
1444 int file_io_pool_entry,
1445 size64_t extent_file_size,
1446 off64_t extent_offset,
1447 size64_t extent_size,
1448 libcerror_error_t **error )
1449 {
1450 static char *function = "libvmdk_extent_table_set_extent_by_extent_descriptor";
1451
1452 if( extent_table == NULL )
1453 {
1454 libcerror_error_set(
1455 error,
1456 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1457 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1458 "%s: invalid extent table.",
1459 function );
1460
1461 return( -1 );
1462 }
1463 if( extent_descriptor == NULL )
1464 {
1465 libcerror_error_set(
1466 error,
1467 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1468 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1469 "%s: invalid extent descriptor.",
1470 function );
1471
1472 return( -1 );
1473 }
1474 if( ( extent_index < 0 )
1475 || ( extent_index > extent_table->number_of_extents ) )
1476 {
1477 libcerror_error_set(
1478 error,
1479 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1480 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1481 "%s: invalid extent index value out of bounds.",
1482 function );
1483
1484 return( -1 );
1485 }
1486 if( extent_index == 0 )
1487 {
1488 if( extent_descriptor->type == LIBVMDK_EXTENT_TYPE_FLAT )
1489 {
1490 if( ( extent_table->disk_type != LIBVMDK_DISK_TYPE_FLAT_2GB_EXTENT )
1491 && ( extent_table->disk_type != LIBVMDK_DISK_TYPE_MONOLITHIC_FLAT ) )
1492 {
1493 libcerror_error_set(
1494 error,
1495 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1496 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1497 "%s: extent type not supported for disk type.",
1498 function );
1499
1500 return( -1 );
1501 }
1502 }
1503 else if( extent_descriptor->type == LIBVMDK_EXTENT_TYPE_SPARSE )
1504 {
1505 if( ( extent_table->disk_type != LIBVMDK_DISK_TYPE_SPARSE_2GB_EXTENT )
1506 && ( extent_table->disk_type != LIBVMDK_DISK_TYPE_MONOLITHIC_SPARSE )
1507 && ( extent_table->disk_type != LIBVMDK_DISK_TYPE_STREAM_OPTIMIZED ) )
1508 {
1509 libcerror_error_set(
1510 error,
1511 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1512 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1513 "%s: extent type not supported for disk type.",
1514 function );
1515
1516 return( -1 );
1517 }
1518 }
1519 else if( extent_descriptor->type == LIBVMDK_EXTENT_TYPE_VMFS_FLAT )
1520 {
1521 if( ( extent_table->disk_type != LIBVMDK_DISK_TYPE_VMFS_FLAT )
1522 && ( extent_table->disk_type != LIBVMDK_DISK_TYPE_VMFS_FLAT_PRE_ALLOCATED )
1523 && ( extent_table->disk_type != LIBVMDK_DISK_TYPE_VMFS_FLAT_ZEROED ) )
1524 {
1525 libcerror_error_set(
1526 error,
1527 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1528 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1529 "%s: extent type not supported for disk type.",
1530 function );
1531
1532 return( -1 );
1533 }
1534 }
1535 else if( extent_descriptor->type == LIBVMDK_EXTENT_TYPE_VMFS_SPARSE )
1536 {
1537 if( ( extent_table->disk_type != LIBVMDK_DISK_TYPE_VMFS_SPARSE )
1538 && ( extent_table->disk_type != LIBVMDK_DISK_TYPE_VMFS_SPARSE_THIN ) )
1539 {
1540 libcerror_error_set(
1541 error,
1542 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1543 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1544 "%s: extent type not supported for disk type.",
1545 function );
1546
1547 return( -1 );
1548 }
1549 }
1550 else
1551 {
1552 libcerror_error_set(
1553 error,
1554 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1555 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1556 "%s: unsupported extent type.",
1557 function );
1558
1559 return( -1 );
1560 }
1561 extent_table->extent_type = extent_descriptor->type;
1562 }
1563 else if( extent_table->extent_type != extent_descriptor->type )
1564 {
1565 libcerror_error_set(
1566 error,
1567 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1568 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1569 "%s: mixed extent types not supported.",
1570 function );
1571
1572 return( -1 );
1573 }
1574 if( ( extent_descriptor->type == LIBVMDK_EXTENT_TYPE_FLAT )
1575 || ( extent_descriptor->type == LIBVMDK_EXTENT_TYPE_VMFS_FLAT ) )
1576 {
1577 if( ( extent_offset < 0 )
1578 || ( (size64_t) extent_offset > extent_file_size ) )
1579 {
1580 libcerror_error_set(
1581 error,
1582 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1583 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1584 "%s: invalid extent offset value out of bounds.",
1585 function );
1586
1587 return( -1 );
1588 }
1589 if( extent_size > ( extent_file_size - (size64_t) extent_offset ) )
1590 {
1591 libcerror_error_set(
1592 error,
1593 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1594 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1595 "%s: invalid extent size value out of bounds.",
1596 function );
1597
1598 return( -1 );
1599 }
1600 if( libfdata_stream_set_segment_by_index(
1601 extent_table->extent_files_stream,
1602 extent_index,
1603 file_io_pool_entry,
1604 extent_offset,
1605 extent_size,
1606 0,
1607 error ) != 1 )
1608 {
1609 libcerror_error_set(
1610 error,
1611 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1612 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1613 "%s: unable to set segment: %d in extent files stream.",
1614 function,
1615 extent_index );
1616
1617 return( -1 );
1618 }
1619 }
1620 else if( ( extent_descriptor->type == LIBVMDK_EXTENT_TYPE_SPARSE )
1621 || ( extent_descriptor->type == LIBVMDK_EXTENT_TYPE_VMFS_SPARSE ) )
1622 {
1623 if( extent_offset != 0 )
1624 {
1625 libcerror_error_set(
1626 error,
1627 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1628 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1629 "%s: invalid extent offset value out of bounds.",
1630 function );
1631
1632 return( -1 );
1633 }
1634 if( libfdata_list_set_element_by_index_with_mapped_size(
1635 extent_table->extent_files_list,
1636 extent_index,
1637 file_io_pool_entry,
1638 0,
1639 extent_file_size,
1640 0,
1641 extent_size,
1642 error ) != 1 )
1643 {
1644 libcerror_error_set(
1645 error,
1646 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1647 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1648 "%s: unable to set element: %d in extent files list.",
1649 function,
1650 extent_index );
1651
1652 return( -1 );
1653 }
1654 }
1655 return( 1 );
1656 }
1657
1658