1 /*
2 * Descriptor file 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 <file_stream.h>
24 #include <memory.h>
25 #include <narrow_string.h>
26 #include <types.h>
27
28 #include "libvmdk_definitions.h"
29 #include "libvmdk_descriptor_file.h"
30 #include "libvmdk_extent_descriptor.h"
31 #include "libvmdk_libcdata.h"
32 #include "libvmdk_libcerror.h"
33 #include "libvmdk_libclocale.h"
34 #include "libvmdk_libcnotify.h"
35 #include "libvmdk_libcsplit.h"
36 #include "libvmdk_libfvalue.h"
37 #include "libvmdk_libuna.h"
38
39 const char *vmdk_descriptor_file_signature = "# Disk DescriptorFile";
40 const char *vmdk_descriptor_file_extent_section_signature = "# Extent description";
41 const char *vmdk_descriptor_file_change_tracking_file_signature = "# Change Tracking File";
42 const char *vmdk_descriptor_file_disk_database_section_signature = "# The Disk Data Base";
43
44 /* Creates a descriptor file
45 * Make sure the value descriptor_file is referencing, is set to NULL
46 * Returns 1 if successful or -1 on error
47 */
libvmdk_descriptor_file_initialize(libvmdk_descriptor_file_t ** descriptor_file,libcerror_error_t ** error)48 int libvmdk_descriptor_file_initialize(
49 libvmdk_descriptor_file_t **descriptor_file,
50 libcerror_error_t **error )
51 {
52 static char *function = "libvmdk_descriptor_file_initialize";
53
54 if( descriptor_file == NULL )
55 {
56 libcerror_error_set(
57 error,
58 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
59 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
60 "%s: invalid descriptor file.",
61 function );
62
63 return( -1 );
64 }
65 if( *descriptor_file != NULL )
66 {
67 libcerror_error_set(
68 error,
69 LIBCERROR_ERROR_DOMAIN_RUNTIME,
70 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
71 "%s: invalid descriptor file value already set.",
72 function );
73
74 return( -1 );
75 }
76 *descriptor_file = memory_allocate_structure(
77 libvmdk_descriptor_file_t );
78
79 if( *descriptor_file == NULL )
80 {
81 libcerror_error_set(
82 error,
83 LIBCERROR_ERROR_DOMAIN_MEMORY,
84 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
85 "%s: unable to create descriptor file.",
86 function );
87
88 goto on_error;
89 }
90 if( memory_set(
91 *descriptor_file,
92 0,
93 sizeof( libvmdk_descriptor_file_t ) ) == NULL )
94 {
95 libcerror_error_set(
96 error,
97 LIBCERROR_ERROR_DOMAIN_MEMORY,
98 LIBCERROR_MEMORY_ERROR_SET_FAILED,
99 "%s: unable to clear descriptor file.",
100 function );
101
102 memory_free(
103 *descriptor_file );
104
105 *descriptor_file = NULL;
106
107 return( -1 );
108 }
109 if( libcdata_array_initialize(
110 &( ( *descriptor_file )->extents_array ),
111 0,
112 error ) != 1 )
113 {
114 libcerror_error_set(
115 error,
116 LIBCERROR_ERROR_DOMAIN_RUNTIME,
117 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
118 "%s: unable to create extents array.",
119 function );
120
121 goto on_error;
122 }
123 return( 1 );
124
125 on_error:
126 if( *descriptor_file != NULL )
127 {
128 memory_free(
129 *descriptor_file );
130
131 *descriptor_file = NULL;
132 }
133 return( -1 );
134 }
135
136 /* Frees a descriptor file
137 * Returns 1 if successful or -1 on error
138 */
libvmdk_descriptor_file_free(libvmdk_descriptor_file_t ** descriptor_file,libcerror_error_t ** error)139 int libvmdk_descriptor_file_free(
140 libvmdk_descriptor_file_t **descriptor_file,
141 libcerror_error_t **error )
142 {
143 static char *function = "libvmdk_descriptor_file_free";
144 int result = 1;
145
146 if( descriptor_file == NULL )
147 {
148 libcerror_error_set(
149 error,
150 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
151 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
152 "%s: invalid descriptor file.",
153 function );
154
155 return( -1 );
156 }
157 if( *descriptor_file != NULL )
158 {
159 if( ( *descriptor_file )->parent_filename != NULL )
160 {
161 memory_free(
162 ( *descriptor_file )->parent_filename );
163 }
164 if( libcdata_array_free(
165 &( ( *descriptor_file )->extents_array ),
166 (int (*)(intptr_t **, libcerror_error_t **)) &libvmdk_internal_extent_descriptor_free,
167 error ) != 1 )
168 {
169 libcerror_error_set(
170 error,
171 LIBCERROR_ERROR_DOMAIN_RUNTIME,
172 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
173 "%s: unable to free extents array.",
174 function );
175
176 result = -1;
177 }
178 memory_free(
179 *descriptor_file );
180
181 *descriptor_file = NULL;
182 }
183 return( result );
184 }
185
186 /* Reads the descriptor file
187 * Returns the 1 if succesful or -1 on error
188 */
libvmdk_descriptor_file_read(libvmdk_descriptor_file_t * descriptor_file,libbfio_handle_t * file_io_handle,libcerror_error_t ** error)189 int libvmdk_descriptor_file_read(
190 libvmdk_descriptor_file_t *descriptor_file,
191 libbfio_handle_t *file_io_handle,
192 libcerror_error_t **error )
193 {
194 uint8_t *descriptor_data = NULL;
195 static char *function = "libvmdk_descriptor_file_read";
196 size64_t file_size = 0;
197 ssize_t read_count = 0;
198
199 if( descriptor_file == NULL )
200 {
201 libcerror_error_set(
202 error,
203 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
204 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
205 "%s: invalid descriptor file.",
206 function );
207
208 return( -1 );
209 }
210 if( libbfio_handle_get_size(
211 file_io_handle,
212 &file_size,
213 error ) == -1 )
214 {
215 libcerror_error_set(
216 error,
217 LIBCERROR_ERROR_DOMAIN_RUNTIME,
218 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
219 "%s: unable to determine size of file IO handle entry.",
220 function );
221
222 goto on_error;
223 }
224 if( ( file_size == 0 )
225 || ( file_size > (size64_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
226 {
227 libcerror_error_set(
228 error,
229 LIBCERROR_ERROR_DOMAIN_RUNTIME,
230 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
231 "%s: invalid file size value out of bounds.",
232 function );
233
234 goto on_error;
235 }
236 descriptor_data = (uint8_t *) memory_allocate(
237 sizeof( uint8_t ) * (size_t) file_size );
238
239 if( descriptor_data == NULL )
240 {
241 libcerror_error_set(
242 error,
243 LIBCERROR_ERROR_DOMAIN_MEMORY,
244 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
245 "%s: unable to create descriptor data.",
246 function );
247
248 goto on_error;
249 }
250 read_count = libbfio_handle_read_buffer_at_offset(
251 file_io_handle,
252 descriptor_data,
253 (size_t) file_size,
254 0,
255 error );
256
257 if( read_count != (ssize_t) file_size )
258 {
259 libcerror_error_set(
260 error,
261 LIBCERROR_ERROR_DOMAIN_IO,
262 LIBCERROR_IO_ERROR_READ_FAILED,
263 "%s: unable to read data at offset: 0 (0x00000000).",
264 function );
265
266 goto on_error;
267 }
268 if( libvmdk_descriptor_file_read_string(
269 descriptor_file,
270 (char *) descriptor_data,
271 (size_t) file_size,
272 error ) != 1 )
273 {
274 libcerror_error_set(
275 error,
276 LIBCERROR_ERROR_DOMAIN_IO,
277 LIBCERROR_IO_ERROR_READ_FAILED,
278 "%s: unable to read descriptor from string.",
279 function );
280
281 goto on_error;
282 }
283 memory_free(
284 descriptor_data );
285
286 descriptor_data = NULL;
287
288 return( 1 );
289
290 on_error:
291 if( descriptor_data != NULL )
292 {
293 memory_free(
294 descriptor_data );
295 }
296 return( -1 );
297 }
298
299 /* Reads the descriptor file from a string
300 * Returns the 1 if succesful or -1 on error
301 */
libvmdk_descriptor_file_read_string(libvmdk_descriptor_file_t * descriptor_file,const char * value_string,size_t value_string_size,libcerror_error_t ** error)302 int libvmdk_descriptor_file_read_string(
303 libvmdk_descriptor_file_t *descriptor_file,
304 const char *value_string,
305 size_t value_string_size,
306 libcerror_error_t **error )
307 {
308 libcsplit_narrow_split_string_t *lines = NULL;
309 static char *function = "libvmdk_descriptor_file_read_string";
310 int line_index = 0;
311 int number_of_lines = 0;
312 int result = 0;
313
314 if( descriptor_file == NULL )
315 {
316 libcerror_error_set(
317 error,
318 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
319 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
320 "%s: invalid descriptor file.",
321 function );
322
323 return( -1 );
324 }
325 if( libcsplit_narrow_string_split(
326 value_string,
327 value_string_size,
328 '\n',
329 &lines,
330 error ) != 1 )
331 {
332 libcerror_error_set(
333 error,
334 LIBCERROR_ERROR_DOMAIN_RUNTIME,
335 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
336 "%s: unable to split file data into lines.",
337 function );
338
339 goto on_error;
340 }
341 if( libcsplit_narrow_split_string_get_number_of_segments(
342 lines,
343 &number_of_lines,
344 error ) != 1 )
345 {
346 libcerror_error_set(
347 error,
348 LIBCERROR_ERROR_DOMAIN_RUNTIME,
349 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
350 "%s: unable to retrieve number of lines.",
351 function );
352
353 goto on_error;
354 }
355 if( libvmdk_descriptor_file_read_signature(
356 lines,
357 number_of_lines,
358 &line_index,
359 error ) != 1 )
360 {
361 libcerror_error_set(
362 error,
363 LIBCERROR_ERROR_DOMAIN_IO,
364 LIBCERROR_IO_ERROR_READ_FAILED,
365 "%s: unable to read descriptor file signature.",
366 function );
367
368 goto on_error;
369 }
370 if( libvmdk_descriptor_file_read_header(
371 descriptor_file,
372 lines,
373 number_of_lines,
374 &line_index,
375 error ) != 1 )
376 {
377 libcerror_error_set(
378 error,
379 LIBCERROR_ERROR_DOMAIN_IO,
380 LIBCERROR_IO_ERROR_READ_FAILED,
381 "%s: unable to read descriptor file header.",
382 function );
383
384 goto on_error;
385 }
386 if( libvmdk_descriptor_file_read_extents(
387 descriptor_file,
388 lines,
389 number_of_lines,
390 &line_index,
391 error ) != 1 )
392 {
393 libcerror_error_set(
394 error,
395 LIBCERROR_ERROR_DOMAIN_IO,
396 LIBCERROR_IO_ERROR_READ_FAILED,
397 "%s: unable to read extents.",
398 function );
399
400 goto on_error;
401 }
402 result = libvmdk_descriptor_file_read_change_tracking_file(
403 descriptor_file,
404 lines,
405 number_of_lines,
406 &line_index,
407 error );
408
409 if( result == -1 )
410 {
411 libcerror_error_set(
412 error,
413 LIBCERROR_ERROR_DOMAIN_IO,
414 LIBCERROR_IO_ERROR_READ_FAILED,
415 "%s: unable to read change tracking file.",
416 function );
417
418 goto on_error;
419 }
420 if( libvmdk_descriptor_file_read_disk_database(
421 descriptor_file,
422 lines,
423 number_of_lines,
424 &line_index,
425 error ) != 1 )
426 {
427 libcerror_error_set(
428 error,
429 LIBCERROR_ERROR_DOMAIN_IO,
430 LIBCERROR_IO_ERROR_READ_FAILED,
431 "%s: unable to read disk database.",
432 function );
433
434 goto on_error;
435 }
436 if( libcsplit_narrow_split_string_free(
437 &lines,
438 error ) != 1 )
439 {
440 libcerror_error_set(
441 error,
442 LIBCERROR_ERROR_DOMAIN_RUNTIME,
443 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
444 "%s: unable to free lines.",
445 function );
446
447 goto on_error;
448 }
449 return( 1 );
450
451 on_error:
452 if( lines != NULL )
453 {
454 libcsplit_narrow_split_string_free(
455 &lines,
456 NULL );
457 }
458 return( -1 );
459 }
460
461 /* Reads the signature from the descriptor file
462 * Returns the 1 if succesful, 0 if no signature was found or -1 on error
463 */
libvmdk_descriptor_file_read_signature(libcsplit_narrow_split_string_t * lines,int number_of_lines,int * line_index,libcerror_error_t ** error)464 int libvmdk_descriptor_file_read_signature(
465 libcsplit_narrow_split_string_t *lines,
466 int number_of_lines,
467 int *line_index,
468 libcerror_error_t **error )
469 {
470 static char *function = "libvmdk_descriptor_file_read_signature";
471 char *line_string_segment = NULL;
472 size_t line_string_segment_index = 0;
473 size_t line_string_segment_size = 0;
474 int result = 0;
475 int safe_line_index = 0;
476
477 if( line_index == NULL )
478 {
479 libcerror_error_set(
480 error,
481 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
482 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
483 "%s: invalid line index.",
484 function );
485
486 return( -1 );
487 }
488 if( number_of_lines <= 0 )
489 {
490 libcerror_error_set(
491 error,
492 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
493 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
494 "%s: invalid number of lines value out of bounds.",
495 function );
496
497 return( -1 );
498 }
499 while( safe_line_index < number_of_lines )
500 {
501 if( libcsplit_narrow_split_string_get_segment_by_index(
502 lines,
503 safe_line_index,
504 &line_string_segment,
505 &line_string_segment_size,
506 error ) != 1 )
507 {
508 libcerror_error_set(
509 error,
510 LIBCERROR_ERROR_DOMAIN_RUNTIME,
511 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
512 "%s: unable to retrieve line: %d.",
513 function,
514 safe_line_index );
515
516 return( -1 );
517 }
518 if( line_string_segment == NULL )
519 {
520 libcerror_error_set(
521 error,
522 LIBCERROR_ERROR_DOMAIN_RUNTIME,
523 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
524 "%s: missing line string segment: %d.",
525 function,
526 safe_line_index );
527
528 return( -1 );
529 }
530 if( line_string_segment_size < 2 )
531 {
532 safe_line_index++;
533
534 continue;
535 }
536 /* Ignore trailing white space
537 */
538 line_string_segment_index = line_string_segment_size - 2;
539
540 while( line_string_segment_index > 0 )
541 {
542 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
543 && ( line_string_segment[ line_string_segment_index ] != '\n' )
544 && ( line_string_segment[ line_string_segment_index ] != '\f' )
545 && ( line_string_segment[ line_string_segment_index ] != '\v' )
546 && ( line_string_segment[ line_string_segment_index ] != '\r' )
547 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
548 {
549 break;
550 }
551 line_string_segment_index--;
552 line_string_segment_size--;
553 }
554 /* Ignore leading white space
555 */
556 line_string_segment_index = 0;
557
558 while( line_string_segment_index < line_string_segment_size )
559 {
560 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
561 && ( line_string_segment[ line_string_segment_index ] != '\n' )
562 && ( line_string_segment[ line_string_segment_index ] != '\f' )
563 && ( line_string_segment[ line_string_segment_index ] != '\v' )
564 && ( line_string_segment[ line_string_segment_index ] != '\r' )
565 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
566 {
567 break;
568 }
569 line_string_segment_index++;
570 line_string_segment_size--;
571 }
572 /* Only allow comment or empty lines
573 */
574 if( line_string_segment_size > 1 )
575 {
576 if( line_string_segment[ line_string_segment_index ] == '#' )
577 {
578 if( ( line_string_segment_size == 22 )
579 && ( narrow_string_compare_no_case(
580 &( line_string_segment[ line_string_segment_index ] ),
581 vmdk_descriptor_file_signature,
582 21 ) == 0 ) )
583 {
584 result = 1;
585
586 break;
587 }
588 }
589 else if( line_string_segment[ line_string_segment_index ] != 0 )
590 {
591 break;
592 }
593 }
594 safe_line_index++;
595 }
596 *line_index = safe_line_index;
597
598 return( result );
599 }
600
601 /* Reads the header from the descriptor file
602 * Returns the 1 if succesful or -1 on error
603 */
libvmdk_descriptor_file_read_header(libvmdk_descriptor_file_t * descriptor_file,libcsplit_narrow_split_string_t * lines,int number_of_lines,int * line_index,libcerror_error_t ** error)604 int libvmdk_descriptor_file_read_header(
605 libvmdk_descriptor_file_t *descriptor_file,
606 libcsplit_narrow_split_string_t *lines,
607 int number_of_lines,
608 int *line_index,
609 libcerror_error_t **error )
610 {
611 char *line_string_segment = NULL;
612 char *value = NULL;
613 char *value_identifier = NULL;
614 static char *function = "libvmdk_descriptor_file_read_header";
615 size_t line_string_segment_index = 0;
616 size_t line_string_segment_size = 0;
617 size_t value_identifier_length = 0;
618 size_t value_length = 0;
619 uint64_t value_64bit = 0;
620 int safe_line_index = 0;
621
622 if( descriptor_file == NULL )
623 {
624 libcerror_error_set(
625 error,
626 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
627 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
628 "%s: invalid descriptor file.",
629 function );
630
631 return( -1 );
632 }
633 if( line_index == NULL )
634 {
635 libcerror_error_set(
636 error,
637 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
638 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
639 "%s: invalid line index.",
640 function );
641
642 return( -1 );
643 }
644 if( number_of_lines <= 0 )
645 {
646 libcerror_error_set(
647 error,
648 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
649 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
650 "%s: invalid number of lines value out of bounds.",
651 function );
652
653 return( -1 );
654 }
655 safe_line_index = *line_index;
656
657 if( ( safe_line_index < 0 )
658 || ( safe_line_index >= number_of_lines ) )
659 {
660 libcerror_error_set(
661 error,
662 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
663 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
664 "%s: invalid line index value out of bounds.",
665 function );
666
667 return( -1 );
668 }
669 while( safe_line_index < number_of_lines )
670 {
671 if( libcsplit_narrow_split_string_get_segment_by_index(
672 lines,
673 safe_line_index,
674 &line_string_segment,
675 &line_string_segment_size,
676 error ) != 1 )
677 {
678 libcerror_error_set(
679 error,
680 LIBCERROR_ERROR_DOMAIN_RUNTIME,
681 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
682 "%s: unable to retrieve line: %d.",
683 function,
684 safe_line_index );
685
686 goto on_error;
687 }
688 if( line_string_segment == NULL )
689 {
690 libcerror_error_set(
691 error,
692 LIBCERROR_ERROR_DOMAIN_RUNTIME,
693 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
694 "%s: missing line string segment: %d.",
695 function,
696 safe_line_index );
697
698 goto on_error;
699 }
700 if( line_string_segment_size < 2 )
701 {
702 safe_line_index++;
703
704 continue;
705 }
706 /* Ignore trailing white space
707 */
708 line_string_segment_index = line_string_segment_size - 2;
709
710 while( line_string_segment_index > 0 )
711 {
712 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
713 && ( line_string_segment[ line_string_segment_index ] != '\n' )
714 && ( line_string_segment[ line_string_segment_index ] != '\f' )
715 && ( line_string_segment[ line_string_segment_index ] != '\v' )
716 && ( line_string_segment[ line_string_segment_index ] != '\r' )
717 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
718 {
719 break;
720 }
721 line_string_segment_index--;
722 line_string_segment_size--;
723 }
724 /* Ignore leading white space
725 */
726 line_string_segment_index = 0;
727
728 while( line_string_segment_index < line_string_segment_size )
729 {
730 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
731 && ( line_string_segment[ line_string_segment_index ] != '\n' )
732 && ( line_string_segment[ line_string_segment_index ] != '\f' )
733 && ( line_string_segment[ line_string_segment_index ] != '\v' )
734 && ( line_string_segment[ line_string_segment_index ] != '\r' )
735 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
736 {
737 break;
738 }
739 line_string_segment_index++;
740 }
741 /* Skip an empty line
742 */
743 if( ( line_string_segment_index >= line_string_segment_size )
744 || ( line_string_segment[ line_string_segment_index ] == 0 ) )
745 {
746 safe_line_index++;
747
748 continue;
749 }
750 if( ( line_string_segment_size - line_string_segment_index ) == 21 )
751 {
752 /* Check for the end of the header
753 */
754 if( narrow_string_compare_no_case(
755 &( line_string_segment[ line_string_segment_index ] ),
756 vmdk_descriptor_file_extent_section_signature,
757 20 ) == 0 )
758 {
759 break;
760 }
761 }
762 /* Determine the value identifier
763 */
764 value_identifier = &( line_string_segment[ line_string_segment_index ] );
765 value_identifier_length = 0;
766
767 while( line_string_segment_index < line_string_segment_size )
768 {
769 if( ( line_string_segment[ line_string_segment_index ] == '\t' )
770 || ( line_string_segment[ line_string_segment_index ] == '\n' )
771 || ( line_string_segment[ line_string_segment_index ] == '\f' )
772 || ( line_string_segment[ line_string_segment_index ] == '\v' )
773 || ( line_string_segment[ line_string_segment_index ] == '\r' )
774 || ( line_string_segment[ line_string_segment_index ] == ' ' )
775 || ( line_string_segment[ line_string_segment_index ] == '=' ) )
776 {
777 break;
778 }
779 value_identifier_length++;
780
781 line_string_segment_index++;
782 }
783 /* Skip a line not containing a value
784 */
785 if( ( line_string_segment_index >= line_string_segment_size )
786 || ( line_string_segment[ line_string_segment_index ] == 0 ) )
787 {
788 safe_line_index++;
789
790 continue;
791 }
792 /* Make sure the value identifier is terminated by an end of string
793 */
794 line_string_segment[ line_string_segment_index ] = 0;
795
796 line_string_segment_index++;
797
798 /* Ignore whitespace
799 */
800 while( line_string_segment_index < line_string_segment_size )
801 {
802 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
803 && ( line_string_segment[ line_string_segment_index ] != '\n' )
804 && ( line_string_segment[ line_string_segment_index ] != '\f' )
805 && ( line_string_segment[ line_string_segment_index ] != '\v' )
806 && ( line_string_segment[ line_string_segment_index ] != '\r' )
807 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
808 {
809 break;
810 }
811 line_string_segment_index++;
812 }
813 if( line_string_segment[ line_string_segment_index ] == '=' )
814 {
815 line_string_segment_index++;
816
817 while( line_string_segment_index < line_string_segment_size )
818 {
819 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
820 && ( line_string_segment[ line_string_segment_index ] != '\n' )
821 && ( line_string_segment[ line_string_segment_index ] != '\f' )
822 && ( line_string_segment[ line_string_segment_index ] != '\v' )
823 && ( line_string_segment[ line_string_segment_index ] != '\r' )
824 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
825 {
826 break;
827 }
828 line_string_segment_index++;
829 }
830 }
831 /* Skip a line not containing a value
832 */
833 if( ( line_string_segment_index >= line_string_segment_size )
834 || ( line_string_segment[ line_string_segment_index ] == 0 ) )
835 {
836 safe_line_index++;
837
838 continue;
839 }
840 /* Determine the value
841 */
842 value = &( line_string_segment[ line_string_segment_index ] );
843 value_length = line_string_segment_size - 1;
844
845 /* Ingore quotes at the beginning of the value data
846 */
847 if( ( line_string_segment[ line_string_segment_index ] == '"' )
848 || ( line_string_segment[ line_string_segment_index ] == '\'' ) )
849 {
850 line_string_segment_index++;
851 value++;
852 value_length--;
853 }
854 /* Ingore quotes at the end of the value data
855 */
856 if( ( line_string_segment[ value_length - 1 ] == '"' )
857 || ( line_string_segment[ value_length - 1 ] == '\'' ) )
858 {
859 value_length--;
860 }
861 /* Make sure the value is terminated by an end of string
862 */
863 line_string_segment[ value_length ] = 0;
864
865 value_length -= line_string_segment_index;
866
867 if( value_identifier_length == 3 )
868 {
869 if( narrow_string_compare_no_case(
870 value_identifier,
871 "CID",
872 3 ) == 0 )
873 {
874 #if defined( HAVE_DEBUG_OUTPUT )
875 if( libcnotify_verbose != 0 )
876 {
877 libcnotify_printf(
878 "%s: content identifier\t\t\t: %s\n",
879 function,
880 value );
881 }
882 #endif
883 if( libfvalue_utf8_string_copy_to_integer(
884 (uint8_t *) value,
885 value_length,
886 &value_64bit,
887 64,
888 LIBFVALUE_INTEGER_FORMAT_TYPE_HEXADECIMAL | LIBFVALUE_INTEGER_FORMAT_FLAG_NO_BASE_INDICATOR,
889 error ) != 1 )
890 {
891 libcerror_error_set(
892 error,
893 LIBCERROR_ERROR_DOMAIN_RUNTIME,
894 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
895 "%s: unable to determine content identifier value from string.",
896 function );
897
898 goto on_error;
899 }
900 if( value_64bit > (uint64_t) UINT32_MAX )
901 {
902 libcerror_error_set(
903 error,
904 LIBCERROR_ERROR_DOMAIN_RUNTIME,
905 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
906 "%s: invalid content identifier value exceeds maximum.",
907 function );
908
909 goto on_error;
910 }
911 descriptor_file->content_identifier = (uint32_t) value_64bit;
912 }
913 }
914 else if( value_identifier_length == 7 )
915 {
916 if( narrow_string_compare_no_case(
917 value_identifier,
918 "version",
919 7 ) == 0 )
920 {
921 #if defined( HAVE_DEBUG_OUTPUT )
922 if( libcnotify_verbose != 0 )
923 {
924 libcnotify_printf(
925 "%s: version\t\t\t\t: %s\n",
926 function,
927 value );
928 }
929 #endif
930 if( libfvalue_utf8_string_copy_to_integer(
931 (uint8_t *) value,
932 value_length,
933 &value_64bit,
934 64,
935 LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED,
936 error ) != 1 )
937 {
938 libcerror_error_set(
939 error,
940 LIBCERROR_ERROR_DOMAIN_RUNTIME,
941 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
942 "%s: unable to determine version value from string.",
943 function );
944
945 goto on_error;
946 }
947 if( value_64bit > (uint64_t) INT_MAX )
948 {
949 libcerror_error_set(
950 error,
951 LIBCERROR_ERROR_DOMAIN_RUNTIME,
952 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
953 "%s: invalid version value exceeds maximum.",
954 function );
955
956 goto on_error;
957 }
958 descriptor_file->version = (int) value_64bit;
959 }
960 }
961 else if( value_identifier_length == 8 )
962 {
963 if( narrow_string_compare_no_case(
964 value_identifier,
965 "encoding",
966 8 ) == 0 )
967 {
968 #if defined( HAVE_DEBUG_OUTPUT )
969 if( libcnotify_verbose != 0 )
970 {
971 libcnotify_printf(
972 "%s: encoding\t\t\t\t: %s\n",
973 function,
974 value );
975 }
976 #endif
977 if( ( value_length == 3 )
978 && ( value[ 0 ] == 'G' )
979 && ( value[ 1 ] == 'B' )
980 && ( value[ 2 ] == 'K' ) )
981 {
982 descriptor_file->encoding = LIBUNA_CODEPAGE_WINDOWS_936;
983 }
984 else if( ( value_length == 4 )
985 && ( value[ 0 ] == 'B' )
986 && ( value[ 1 ] == 'i' )
987 && ( value[ 2 ] == 'g' )
988 && ( value[ 3 ] == '5' ) )
989 {
990 descriptor_file->encoding = LIBUNA_CODEPAGE_WINDOWS_950;
991 }
992 else if( ( value_length == 5 )
993 && ( value[ 0 ] == 'U' )
994 && ( value[ 1 ] == 'T' )
995 && ( value[ 2 ] == 'F' )
996 && ( value[ 3 ] == '-' )
997 && ( value[ 4 ] == '8' ) )
998 {
999 descriptor_file->encoding = 0;
1000 }
1001 else if( libclocale_codepage_copy_from_string(
1002 &( descriptor_file->encoding ),
1003 value,
1004 value_length,
1005 LIBCLOCALE_CODEPAGE_FEATURE_FLAG_HAVE_WINDOWS,
1006 error ) != 1 )
1007 {
1008 libcerror_error_set(
1009 error,
1010 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1011 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1012 "%s: unable to determine codepage value from string.",
1013 function );
1014
1015 goto on_error;
1016 }
1017 }
1018 }
1019 else if( value_identifier_length == 9 )
1020 {
1021 if( narrow_string_compare_no_case(
1022 value_identifier,
1023 "parentCID",
1024 9 ) == 0 )
1025 {
1026 #if defined( HAVE_DEBUG_OUTPUT )
1027 if( libcnotify_verbose != 0 )
1028 {
1029 libcnotify_printf(
1030 "%s: parent content identifier\t\t: %s\n",
1031 function,
1032 value );
1033 }
1034 #endif
1035 if( libfvalue_utf8_string_copy_to_integer(
1036 (uint8_t *) value,
1037 value_length,
1038 &value_64bit,
1039 64,
1040 LIBFVALUE_INTEGER_FORMAT_TYPE_HEXADECIMAL | LIBFVALUE_INTEGER_FORMAT_FLAG_NO_BASE_INDICATOR,
1041 error ) != 1 )
1042 {
1043 libcerror_error_set(
1044 error,
1045 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1046 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1047 "%s: unable to determine parent content identifier value from string.",
1048 function );
1049
1050 goto on_error;
1051 }
1052 if( value_64bit > (uint64_t) UINT32_MAX )
1053 {
1054 libcerror_error_set(
1055 error,
1056 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1057 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
1058 "%s: invalid content parent identifier value exceeds maximum.",
1059 function );
1060
1061 goto on_error;
1062 }
1063 descriptor_file->parent_content_identifier = (uint32_t) value_64bit;
1064 descriptor_file->parent_content_identifier_set = 1;
1065 }
1066 }
1067 else if( value_identifier_length == 10 )
1068 {
1069 if( narrow_string_compare_no_case(
1070 value_identifier,
1071 "createType",
1072 10 ) == 0 )
1073 {
1074 #if defined( HAVE_DEBUG_OUTPUT )
1075 if( libcnotify_verbose != 0 )
1076 {
1077 libcnotify_printf(
1078 "%s: disk type\t\t\t\t: %s\n",
1079 function,
1080 value );
1081 }
1082 #endif
1083 if( value_length == 4 )
1084 {
1085 if( narrow_string_compare_no_case(
1086 value,
1087 "vmfs",
1088 4 ) == 0 )
1089 {
1090 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_VMFS_FLAT;
1091 }
1092 }
1093 else if( value_length == 6 )
1094 {
1095 if( narrow_string_compare_no_case(
1096 value,
1097 "custom",
1098 6 ) == 0 )
1099 {
1100 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_CUSTOM;
1101 }
1102 }
1103 else if( value_length == 7 )
1104 {
1105 if( narrow_string_compare_no_case(
1106 value,
1107 "vmfsRaw",
1108 7 ) == 0 )
1109 {
1110 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_VMFS_RAW;
1111 }
1112 else if( narrow_string_compare_no_case(
1113 value,
1114 "vmfsRDM",
1115 7 ) == 0 )
1116 {
1117 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_VMFS_RDM;
1118 }
1119 }
1120 else if( value_length == 8 )
1121 {
1122 if( narrow_string_compare_no_case(
1123 value,
1124 "vmfsRDMP",
1125 8 ) == 0 )
1126 {
1127 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_VMFS_RDMP;
1128 }
1129 else if( narrow_string_compare_no_case(
1130 value,
1131 "vmfsThin",
1132 8 ) == 0 )
1133 {
1134 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_VMFS_SPARSE_THIN;
1135 }
1136 }
1137 else if( value_length == 10 )
1138 {
1139 if( narrow_string_compare_no_case(
1140 value,
1141 "fullDevice",
1142 10 ) == 0 )
1143 {
1144 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_DEVICE;
1145 }
1146 else if( narrow_string_compare_no_case(
1147 value,
1148 "vmfsSparse",
1149 10 ) == 0 )
1150 {
1151 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_VMFS_SPARSE;
1152 }
1153 }
1154 else if( value_length == 14 )
1155 {
1156 if( narrow_string_compare_no_case(
1157 value,
1158 "monolithicFlat",
1159 14 ) == 0 )
1160 {
1161 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_MONOLITHIC_FLAT;
1162 }
1163 }
1164 else if( value_length == 15 )
1165 {
1166 if( narrow_string_compare_no_case(
1167 value,
1168 "streamOptimized",
1169 15 ) == 0 )
1170 {
1171 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_STREAM_OPTIMIZED;
1172 }
1173 }
1174 else if( value_length == 16 )
1175 {
1176 if( narrow_string_compare_no_case(
1177 value,
1178 "2GbMaxExtentFlat",
1179 16 ) == 0 )
1180 {
1181 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_FLAT_2GB_EXTENT;
1182 }
1183 else if( narrow_string_compare_no_case(
1184 value,
1185 "monolithicSparse",
1186 16 ) == 0 )
1187 {
1188 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_MONOLITHIC_SPARSE;
1189 }
1190 else if( narrow_string_compare_no_case(
1191 value,
1192 "vmfsPreallocated",
1193 16 ) == 0 )
1194 {
1195 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_VMFS_FLAT_PRE_ALLOCATED;
1196 }
1197 else if( narrow_string_compare_no_case(
1198 value,
1199 "vmfsRawDeviceMap",
1200 16 ) == 0 )
1201 {
1202 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_VMFS_RDM;
1203 }
1204 }
1205 else if( value_length == 17 )
1206 {
1207 if( narrow_string_compare_no_case(
1208 value,
1209 "partitionedDevice",
1210 17 ) == 0 )
1211 {
1212 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_DEVICE_PARITIONED;
1213 }
1214 }
1215 else if( value_length == 18 )
1216 {
1217 if( narrow_string_compare_no_case(
1218 value,
1219 "2GbMaxExtentSparse",
1220 18 ) == 0 )
1221 {
1222 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_SPARSE_2GB_EXTENT;
1223 }
1224 else if( narrow_string_compare_no_case(
1225 value,
1226 "twoGbMaxExtentFlat",
1227 18 ) == 0 )
1228 {
1229 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_FLAT_2GB_EXTENT;
1230 }
1231 }
1232 else if( value_length == 20 )
1233 {
1234 if( narrow_string_compare_no_case(
1235 value,
1236 "twoGbMaxExtentSparse",
1237 20 ) == 0 )
1238 {
1239 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_SPARSE_2GB_EXTENT;
1240 }
1241 else if( narrow_string_compare_no_case(
1242 value,
1243 "vmfsEagerZeroedThick",
1244 20 ) == 0 )
1245 {
1246 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_VMFS_FLAT_ZEROED;
1247 }
1248 }
1249 else if( value_length == 27 )
1250 {
1251 if( narrow_string_compare_no_case(
1252 value,
1253 "vmfsPassthroughRawDeviceMap",
1254 27 ) == 0 )
1255 {
1256 descriptor_file->disk_type = LIBVMDK_DISK_TYPE_VMFS_RDMP;
1257 }
1258 }
1259 }
1260 }
1261 else if( value_identifier_length == 18 )
1262 {
1263 if( narrow_string_compare_no_case(
1264 value_identifier,
1265 "parentFileNameHint",
1266 18 ) == 0 )
1267 {
1268 if( descriptor_file->parent_filename != NULL )
1269 {
1270 memory_free(
1271 descriptor_file->parent_filename );
1272
1273 descriptor_file->parent_filename = NULL;
1274 descriptor_file->parent_filename_size = 0;
1275 }
1276 if( value_length > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 1 ) )
1277 {
1278 libcerror_error_set(
1279 error,
1280 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1281 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
1282 "%s: invalid parent filename length exceeds maximum allocation size.",
1283 function );
1284
1285 goto on_error;
1286 }
1287 descriptor_file->parent_filename = (uint8_t *) memory_allocate(
1288 sizeof( uint8_t ) * ( value_length + 1 ) );
1289
1290 if( descriptor_file->parent_filename == NULL )
1291 {
1292 libcerror_error_set(
1293 error,
1294 LIBCERROR_ERROR_DOMAIN_MEMORY,
1295 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1296 "%s: unable to create parent filename.",
1297 function );
1298
1299 goto on_error;
1300 }
1301 if( memory_copy(
1302 descriptor_file->parent_filename,
1303 value,
1304 value_length ) == NULL )
1305 {
1306 libcerror_error_set(
1307 error,
1308 LIBCERROR_ERROR_DOMAIN_MEMORY,
1309 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1310 "%s: unable to copy parent filename.",
1311 function );
1312
1313 goto on_error;
1314 }
1315 descriptor_file->parent_filename[ value_length ] = 0;
1316
1317 descriptor_file->parent_filename_size = value_length + 1;
1318
1319 #if defined( HAVE_DEBUG_OUTPUT )
1320 if( libcnotify_verbose != 0 )
1321 {
1322 libcnotify_printf(
1323 "%s: parent filename\t\t\t: %s\n",
1324 function,
1325 descriptor_file->parent_filename );
1326 }
1327 #endif
1328 }
1329 }
1330 #if defined( HAVE_DEBUG_OUTPUT )
1331 else if( libcnotify_verbose != 0 )
1332 {
1333 libcnotify_printf(
1334 "%s: value: %d\t\t\t\t: %s = %s\n",
1335 function,
1336 safe_line_index,
1337 value_identifier,
1338 value );
1339 }
1340 #endif
1341 safe_line_index++;
1342 }
1343 #if defined( HAVE_DEBUG_OUTPUT )
1344 if( libcnotify_verbose != 0 )
1345 {
1346 libcnotify_printf(
1347 "\n" );
1348 }
1349 #endif
1350 *line_index = safe_line_index;
1351
1352 return( 1 );
1353
1354 on_error:
1355 if( descriptor_file->parent_filename != NULL )
1356 {
1357 memory_free(
1358 descriptor_file->parent_filename );
1359
1360 descriptor_file->parent_filename = NULL;
1361 }
1362 descriptor_file->parent_filename_size = 0;
1363
1364 return( -1 );
1365 }
1366
1367 /* Reads the extents from the descriptor file
1368 * Returns the 1 if succesful or -1 on error
1369 */
libvmdk_descriptor_file_read_extents(libvmdk_descriptor_file_t * descriptor_file,libcsplit_narrow_split_string_t * lines,int number_of_lines,int * line_index,libcerror_error_t ** error)1370 int libvmdk_descriptor_file_read_extents(
1371 libvmdk_descriptor_file_t *descriptor_file,
1372 libcsplit_narrow_split_string_t *lines,
1373 int number_of_lines,
1374 int *line_index,
1375 libcerror_error_t **error )
1376 {
1377 libvmdk_extent_descriptor_t *extent_descriptor = NULL;
1378 static char *function = "libvmdk_descriptor_file_read_extents";
1379 char *line_string_segment = NULL;
1380 size_t line_string_segment_index = 0;
1381 size_t line_string_segment_size = 0;
1382 int entry_index = 0;
1383 int safe_line_index = 0;
1384
1385 if( descriptor_file == NULL )
1386 {
1387 libcerror_error_set(
1388 error,
1389 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1390 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1391 "%s: invalid descriptor file.",
1392 function );
1393
1394 return( -1 );
1395 }
1396 if( line_index == NULL )
1397 {
1398 libcerror_error_set(
1399 error,
1400 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1401 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1402 "%s: invalid line index.",
1403 function );
1404
1405 return( -1 );
1406 }
1407 if( number_of_lines <= 0 )
1408 {
1409 libcerror_error_set(
1410 error,
1411 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1412 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1413 "%s: invalid number of lines value out of bounds.",
1414 function );
1415
1416 return( -1 );
1417 }
1418 safe_line_index = *line_index;
1419
1420 if( ( safe_line_index < 0 )
1421 || ( safe_line_index >= number_of_lines ) )
1422 {
1423 libcerror_error_set(
1424 error,
1425 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1426 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1427 "%s: invalid line index value out of bounds.",
1428 function );
1429
1430 return( -1 );
1431 }
1432 if( libcsplit_narrow_split_string_get_segment_by_index(
1433 lines,
1434 safe_line_index,
1435 &line_string_segment,
1436 &line_string_segment_size,
1437 error ) != 1 )
1438 {
1439 libcerror_error_set(
1440 error,
1441 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1442 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1443 "%s: unable to retrieve line: %d.",
1444 function,
1445 safe_line_index );
1446
1447 goto on_error;
1448 }
1449 if( line_string_segment == NULL )
1450 {
1451 libcerror_error_set(
1452 error,
1453 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1454 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1455 "%s: missing line string segment: %d.",
1456 function,
1457 safe_line_index );
1458
1459 goto on_error;
1460 }
1461 if( line_string_segment_size < 2 )
1462 {
1463 libcerror_error_set(
1464 error,
1465 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1466 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1467 "%s: invalid line string segment: %d size value out of bounds.",
1468 function,
1469 safe_line_index );
1470
1471 goto on_error;
1472 }
1473 /* Ignore trailing white space
1474 */
1475 line_string_segment_index = line_string_segment_size - 2;
1476
1477 while( line_string_segment_index > 0 )
1478 {
1479 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
1480 && ( line_string_segment[ line_string_segment_index ] != '\n' )
1481 && ( line_string_segment[ line_string_segment_index ] != '\f' )
1482 && ( line_string_segment[ line_string_segment_index ] != '\v' )
1483 && ( line_string_segment[ line_string_segment_index ] != '\r' )
1484 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
1485 {
1486 break;
1487 }
1488 line_string_segment_index--;
1489 line_string_segment_size--;
1490 }
1491 /* Ignore leading white space
1492 */
1493 line_string_segment_index = 0;
1494
1495 while( line_string_segment_index < line_string_segment_size )
1496 {
1497 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
1498 && ( line_string_segment[ line_string_segment_index ] != '\n' )
1499 && ( line_string_segment[ line_string_segment_index ] != '\f' )
1500 && ( line_string_segment[ line_string_segment_index ] != '\v' )
1501 && ( line_string_segment[ line_string_segment_index ] != '\r' )
1502 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
1503 {
1504 break;
1505 }
1506 line_string_segment_index++;
1507 }
1508 if( ( ( line_string_segment_size - line_string_segment_index ) != 21 )
1509 || ( narrow_string_compare_no_case(
1510 &( line_string_segment[ line_string_segment_index ] ),
1511 vmdk_descriptor_file_extent_section_signature,
1512 20 ) != 0 ) )
1513 {
1514 libcerror_error_set(
1515 error,
1516 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1517 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1518 "%s: unsupported extent section signature.",
1519 function );
1520
1521 goto on_error;
1522 }
1523 safe_line_index++;
1524
1525 if( libcdata_array_empty(
1526 descriptor_file->extents_array,
1527 (int (*)(intptr_t **, libcerror_error_t **)) &libvmdk_internal_extent_descriptor_free,
1528 error ) != 1 )
1529 {
1530 libcerror_error_set(
1531 error,
1532 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1533 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1534 "%s: unable to empty extents array.",
1535 function );
1536
1537 goto on_error;
1538 }
1539 descriptor_file->media_size = 0;
1540
1541 while( safe_line_index < number_of_lines )
1542 {
1543 if( libcsplit_narrow_split_string_get_segment_by_index(
1544 lines,
1545 safe_line_index,
1546 &line_string_segment,
1547 &line_string_segment_size,
1548 error ) != 1 )
1549 {
1550 libcerror_error_set(
1551 error,
1552 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1553 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1554 "%s: unable to retrieve line: %d.",
1555 function,
1556 safe_line_index );
1557
1558 goto on_error;
1559 }
1560 if( line_string_segment == NULL )
1561 {
1562 libcerror_error_set(
1563 error,
1564 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1565 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1566 "%s: missing line string segment: %d.",
1567 function,
1568 safe_line_index );
1569
1570 goto on_error;
1571 }
1572 if( line_string_segment_size < 2 )
1573 {
1574 safe_line_index++;
1575
1576 continue;
1577 }
1578 /* Ignore trailing white space
1579 */
1580 line_string_segment_index = line_string_segment_size - 2;
1581
1582 while( line_string_segment_index > 0 )
1583 {
1584 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
1585 && ( line_string_segment[ line_string_segment_index ] != '\n' )
1586 && ( line_string_segment[ line_string_segment_index ] != '\f' )
1587 && ( line_string_segment[ line_string_segment_index ] != '\v' )
1588 && ( line_string_segment[ line_string_segment_index ] != '\r' )
1589 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
1590 {
1591 break;
1592 }
1593 line_string_segment_index--;
1594 line_string_segment_size--;
1595 }
1596 /* Ignore leading white space
1597 */
1598 line_string_segment_index = 0;
1599
1600 while( line_string_segment_index < line_string_segment_size )
1601 {
1602 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
1603 && ( line_string_segment[ line_string_segment_index ] != '\n' )
1604 && ( line_string_segment[ line_string_segment_index ] != '\f' )
1605 && ( line_string_segment[ line_string_segment_index ] != '\v' )
1606 && ( line_string_segment[ line_string_segment_index ] != '\r' )
1607 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
1608 {
1609 break;
1610 }
1611 line_string_segment_index++;
1612 }
1613 /* Skip an empty line
1614 */
1615 if( ( line_string_segment_index >= line_string_segment_size )
1616 || ( line_string_segment[ line_string_segment_index ] == 0 ) )
1617 {
1618 safe_line_index++;
1619
1620 continue;
1621 }
1622 if( ( line_string_segment_size - line_string_segment_index ) == 21 )
1623 {
1624 /* Check for the end of the section
1625 */
1626 if( narrow_string_compare_no_case(
1627 &( line_string_segment[ line_string_segment_index ] ),
1628 vmdk_descriptor_file_disk_database_section_signature,
1629 20 ) == 0 )
1630 {
1631 break;
1632 }
1633 }
1634 else if( ( line_string_segment_size - line_string_segment_index ) == 23 )
1635 {
1636 if( narrow_string_compare_no_case(
1637 &( line_string_segment[ line_string_segment_index ] ),
1638 vmdk_descriptor_file_change_tracking_file_signature,
1639 22 ) == 0 )
1640 {
1641 break;
1642 }
1643 }
1644 /* Make sure the string is terminated by an end of string
1645 */
1646 line_string_segment[ line_string_segment_size - 1 ] = 0;
1647
1648 if( libvmdk_extent_descriptor_initialize(
1649 &extent_descriptor,
1650 error ) != 1 )
1651 {
1652 libcerror_error_set(
1653 error,
1654 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1655 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1656 "%s: unable to create extent descriptor.",
1657 function );
1658
1659 goto on_error;
1660 }
1661 if( libvmdk_extent_descriptor_read(
1662 extent_descriptor,
1663 &( line_string_segment[ line_string_segment_index ] ),
1664 line_string_segment_size - line_string_segment_index,
1665 descriptor_file->encoding,
1666 error ) != 1 )
1667 {
1668 libcerror_error_set(
1669 error,
1670 LIBCERROR_ERROR_DOMAIN_IO,
1671 LIBCERROR_IO_ERROR_READ_FAILED,
1672 "%s: unable to read extent descriptor from line: %d.",
1673 function,
1674 safe_line_index );
1675
1676 goto on_error;
1677 }
1678 /* TODO refactor by get_size function */
1679 descriptor_file->media_size += ( (libvmdk_internal_extent_descriptor_t *) extent_descriptor )->size;
1680
1681 if( libcdata_array_append_entry(
1682 descriptor_file->extents_array,
1683 &entry_index,
1684 (intptr_t *) extent_descriptor,
1685 error ) != 1 )
1686 {
1687 libcerror_error_set(
1688 error,
1689 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1690 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1691 "%s: unable to append extent descriptor to extents array.",
1692 function );
1693
1694 goto on_error;
1695 }
1696 extent_descriptor = NULL;
1697
1698 safe_line_index++;
1699 }
1700 *line_index = safe_line_index;
1701
1702 return( 1 );
1703
1704 on_error:
1705 if( extent_descriptor != NULL )
1706 {
1707 libvmdk_internal_extent_descriptor_free(
1708 (libvmdk_internal_extent_descriptor_t **) &extent_descriptor,
1709 NULL );
1710 }
1711 libcdata_array_empty(
1712 descriptor_file->extents_array,
1713 (int (*)(intptr_t **, libcerror_error_t **)) &libvmdk_internal_extent_descriptor_free,
1714 NULL );
1715
1716 return( -1 );
1717 }
1718
1719 /* Reads the change tracking file from the descriptor file
1720 * Returns the 1 if succesful, 0 if no such value or -1 on error
1721 */
libvmdk_descriptor_file_read_change_tracking_file(libvmdk_descriptor_file_t * descriptor_file,libcsplit_narrow_split_string_t * lines,int number_of_lines,int * line_index,libcerror_error_t ** error)1722 int libvmdk_descriptor_file_read_change_tracking_file(
1723 libvmdk_descriptor_file_t *descriptor_file,
1724 libcsplit_narrow_split_string_t *lines,
1725 int number_of_lines,
1726 int *line_index,
1727 libcerror_error_t **error )
1728 {
1729 char *line_string_segment = NULL;
1730 char *value = NULL;
1731 char *value_identifier = NULL;
1732 static char *function = "libvmdk_descriptor_file_read_change_tracking_file";
1733 size_t line_string_segment_index = 0;
1734 size_t line_string_segment_size = 0;
1735 size_t value_identifier_length = 0;
1736 size_t value_length = 0;
1737 int safe_line_index = 0;
1738
1739 if( descriptor_file == NULL )
1740 {
1741 libcerror_error_set(
1742 error,
1743 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1744 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1745 "%s: invalid descriptor file.",
1746 function );
1747
1748 return( -1 );
1749 }
1750 if( line_index == NULL )
1751 {
1752 libcerror_error_set(
1753 error,
1754 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1755 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1756 "%s: invalid line index.",
1757 function );
1758
1759 return( -1 );
1760 }
1761 if( number_of_lines <= 0 )
1762 {
1763 libcerror_error_set(
1764 error,
1765 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1766 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1767 "%s: invalid number of lines value out of bounds.",
1768 function );
1769
1770 return( -1 );
1771 }
1772 safe_line_index = *line_index;
1773
1774 if( ( safe_line_index < 0 )
1775 || ( safe_line_index >= number_of_lines ) )
1776 {
1777 libcerror_error_set(
1778 error,
1779 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1780 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1781 "%s: invalid line index value out of bounds.",
1782 function );
1783
1784 return( -1 );
1785 }
1786 if( libcsplit_narrow_split_string_get_segment_by_index(
1787 lines,
1788 safe_line_index,
1789 &line_string_segment,
1790 &line_string_segment_size,
1791 error ) != 1 )
1792 {
1793 libcerror_error_set(
1794 error,
1795 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1796 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1797 "%s: unable to retrieve line: %d.",
1798 function,
1799 safe_line_index );
1800
1801 return( -1 );
1802 }
1803 if( line_string_segment == NULL )
1804 {
1805 libcerror_error_set(
1806 error,
1807 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1808 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1809 "%s: missing line string segment: %d.",
1810 function,
1811 safe_line_index );
1812
1813 return( -1 );
1814 }
1815 if( line_string_segment_size < 2 )
1816 {
1817 libcerror_error_set(
1818 error,
1819 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1820 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1821 "%s: invalid line string segment: %d size value out of bounds.",
1822 function,
1823 safe_line_index );
1824
1825 return( -1 );
1826 }
1827 /* Ignore trailing white space
1828 */
1829 line_string_segment_index = line_string_segment_size - 2;
1830
1831 while( line_string_segment_index > 0 )
1832 {
1833 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
1834 && ( line_string_segment[ line_string_segment_index ] != '\n' )
1835 && ( line_string_segment[ line_string_segment_index ] != '\f' )
1836 && ( line_string_segment[ line_string_segment_index ] != '\v' )
1837 && ( line_string_segment[ line_string_segment_index ] != '\r' )
1838 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
1839 {
1840 break;
1841 }
1842 line_string_segment_index--;
1843 line_string_segment_size--;
1844 }
1845 /* Ignore leading white space
1846 */
1847 line_string_segment_index = 0;
1848
1849 while( line_string_segment_index < line_string_segment_size )
1850 {
1851 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
1852 && ( line_string_segment[ line_string_segment_index ] != '\n' )
1853 && ( line_string_segment[ line_string_segment_index ] != '\f' )
1854 && ( line_string_segment[ line_string_segment_index ] != '\v' )
1855 && ( line_string_segment[ line_string_segment_index ] != '\r' )
1856 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
1857 {
1858 break;
1859 }
1860 line_string_segment_index++;
1861 }
1862 if( ( ( line_string_segment_size - line_string_segment_index ) != 23 )
1863 || ( narrow_string_compare_no_case(
1864 &( line_string_segment[ line_string_segment_index ] ),
1865 vmdk_descriptor_file_change_tracking_file_signature,
1866 22 ) != 0 ) )
1867 {
1868 return( 0 );
1869 }
1870 safe_line_index++;
1871
1872 while( safe_line_index < number_of_lines )
1873 {
1874 if( libcsplit_narrow_split_string_get_segment_by_index(
1875 lines,
1876 safe_line_index,
1877 &line_string_segment,
1878 &line_string_segment_size,
1879 error ) != 1 )
1880 {
1881 libcerror_error_set(
1882 error,
1883 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1884 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1885 "%s: unable to retrieve line: %d.",
1886 function,
1887 safe_line_index );
1888
1889 return( -1 );
1890 }
1891 if( line_string_segment == NULL )
1892 {
1893 libcerror_error_set(
1894 error,
1895 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1896 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1897 "%s: missing line string segment: %d.",
1898 function,
1899 safe_line_index );
1900
1901 return( -1 );
1902 }
1903 if( line_string_segment_size < 2 )
1904 {
1905 safe_line_index++;
1906
1907 continue;
1908 }
1909 /* Ignore trailing white space
1910 */
1911 line_string_segment_index = line_string_segment_size - 2;
1912
1913 while( line_string_segment_index > 0 )
1914 {
1915 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
1916 && ( line_string_segment[ line_string_segment_index ] != '\n' )
1917 && ( line_string_segment[ line_string_segment_index ] != '\f' )
1918 && ( line_string_segment[ line_string_segment_index ] != '\v' )
1919 && ( line_string_segment[ line_string_segment_index ] != '\r' )
1920 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
1921 {
1922 break;
1923 }
1924 line_string_segment_index--;
1925 line_string_segment_size--;
1926 }
1927 /* Ignore leading white space
1928 */
1929 line_string_segment_index = 0;
1930
1931 while( line_string_segment_index < line_string_segment_size )
1932 {
1933 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
1934 && ( line_string_segment[ line_string_segment_index ] != '\n' )
1935 && ( line_string_segment[ line_string_segment_index ] != '\f' )
1936 && ( line_string_segment[ line_string_segment_index ] != '\v' )
1937 && ( line_string_segment[ line_string_segment_index ] != '\r' )
1938 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
1939 {
1940 break;
1941 }
1942 line_string_segment_index++;
1943 }
1944 /* Skip an empty line
1945 */
1946 if( ( line_string_segment_index >= line_string_segment_size )
1947 || ( line_string_segment[ line_string_segment_index ] == 0 ) )
1948 {
1949 safe_line_index++;
1950
1951 continue;
1952 }
1953 if( ( line_string_segment_size - line_string_segment_index ) == 21 )
1954 {
1955 /* Check for the end of the section
1956 */
1957 if( narrow_string_compare_no_case(
1958 &( line_string_segment[ line_string_segment_index ] ),
1959 vmdk_descriptor_file_disk_database_section_signature,
1960 20 ) == 0 )
1961 {
1962 break;
1963 }
1964 }
1965 /* Determine the value identifier
1966 */
1967 value_identifier = &( line_string_segment[ line_string_segment_index ] );
1968 value_identifier_length = 0;
1969
1970 while( line_string_segment_index < line_string_segment_size )
1971 {
1972 if( ( line_string_segment[ line_string_segment_index ] == '\t' )
1973 || ( line_string_segment[ line_string_segment_index ] == '\n' )
1974 || ( line_string_segment[ line_string_segment_index ] == '\f' )
1975 || ( line_string_segment[ line_string_segment_index ] == '\v' )
1976 || ( line_string_segment[ line_string_segment_index ] == '\r' )
1977 || ( line_string_segment[ line_string_segment_index ] == ' ' )
1978 || ( line_string_segment[ line_string_segment_index ] == '=' ) )
1979 {
1980 break;
1981 }
1982 value_identifier_length++;
1983
1984 line_string_segment_index++;
1985 }
1986 /* Skip a line not containing a value
1987 */
1988 if( ( line_string_segment_index >= line_string_segment_size )
1989 || ( line_string_segment[ line_string_segment_index ] == 0 ) )
1990 {
1991 safe_line_index++;
1992
1993 continue;
1994 }
1995 /* Make sure the value identifier is terminated by an end of string
1996 */
1997 line_string_segment[ line_string_segment_index ] = 0;
1998
1999 line_string_segment_index++;
2000
2001 /* Ignore whitespace
2002 */
2003 while( line_string_segment_index < line_string_segment_size )
2004 {
2005 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
2006 && ( line_string_segment[ line_string_segment_index ] != '\n' )
2007 && ( line_string_segment[ line_string_segment_index ] != '\f' )
2008 && ( line_string_segment[ line_string_segment_index ] != '\v' )
2009 && ( line_string_segment[ line_string_segment_index ] != '\r' )
2010 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
2011 {
2012 break;
2013 }
2014 line_string_segment_index++;
2015 }
2016 if( line_string_segment[ line_string_segment_index ] == '=' )
2017 {
2018 line_string_segment_index++;
2019
2020 while( line_string_segment_index < line_string_segment_size )
2021 {
2022 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
2023 && ( line_string_segment[ line_string_segment_index ] != '\n' )
2024 && ( line_string_segment[ line_string_segment_index ] != '\f' )
2025 && ( line_string_segment[ line_string_segment_index ] != '\v' )
2026 && ( line_string_segment[ line_string_segment_index ] != '\r' )
2027 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
2028 {
2029 break;
2030 }
2031 line_string_segment_index++;
2032 }
2033 }
2034 /* Skip a line not containing a value
2035 */
2036 if( ( line_string_segment_index >= line_string_segment_size )
2037 || ( line_string_segment[ line_string_segment_index ] == 0 ) )
2038 {
2039 safe_line_index++;
2040
2041 continue;
2042 }
2043 /* Determine the value
2044 */
2045 value = &( line_string_segment[ line_string_segment_index ] );
2046 value_length = line_string_segment_size - 1;
2047
2048 /* Ingore quotes at the beginning of the value data
2049 */
2050 if( ( line_string_segment[ line_string_segment_index ] == '"' )
2051 || ( line_string_segment[ line_string_segment_index ] == '\'' ) )
2052 {
2053 line_string_segment_index++;
2054 value++;
2055 value_length--;
2056 }
2057 /* Ingore quotes at the end of the value data
2058 */
2059 if( ( line_string_segment[ value_length - 1 ] == '"' )
2060 || ( line_string_segment[ value_length - 1 ] == '\'' ) )
2061 {
2062 value_length--;
2063 }
2064 /* Make sure the value is terminated by an end of string
2065 */
2066 line_string_segment[ value_length ] = 0;
2067
2068 value_length -= line_string_segment_index;
2069
2070 if( value_identifier_length == 15 )
2071 {
2072 if( narrow_string_compare_no_case(
2073 value_identifier,
2074 "changeTrackPath",
2075 15 ) == 0 )
2076 {
2077 /* TODO */
2078 }
2079 }
2080 #if defined( HAVE_DEBUG_OUTPUT )
2081 else if( libcnotify_verbose != 0 )
2082 {
2083 libcnotify_printf(
2084 "%s: value: %d\t\t\t\t: %s = %s\n",
2085 function,
2086 safe_line_index,
2087 value_identifier,
2088 value );
2089 }
2090 #endif
2091 safe_line_index++;
2092 }
2093 #if defined( HAVE_DEBUG_OUTPUT )
2094 if( libcnotify_verbose != 0 )
2095 {
2096 libcnotify_printf(
2097 "\n" );
2098 }
2099 #endif
2100 *line_index = safe_line_index;
2101
2102 return( 1 );
2103 }
2104
2105 /* Reads the disk database from the descriptor file
2106 * Returns the 1 if succesful or -1 on error
2107 */
libvmdk_descriptor_file_read_disk_database(libvmdk_descriptor_file_t * descriptor_file,libcsplit_narrow_split_string_t * lines,int number_of_lines,int * line_index,libcerror_error_t ** error)2108 int libvmdk_descriptor_file_read_disk_database(
2109 libvmdk_descriptor_file_t *descriptor_file,
2110 libcsplit_narrow_split_string_t *lines,
2111 int number_of_lines,
2112 int *line_index,
2113 libcerror_error_t **error )
2114 {
2115 char *line_string_segment = NULL;
2116 char *value = NULL;
2117 char *value_identifier = NULL;
2118 static char *function = "libvmdk_descriptor_file_read_disk_database";
2119 size_t line_string_segment_index = 0;
2120 size_t line_string_segment_size = 0;
2121 size_t value_identifier_length = 0;
2122 size_t value_length = 0;
2123 int safe_line_index = 0;
2124
2125 if( descriptor_file == NULL )
2126 {
2127 libcerror_error_set(
2128 error,
2129 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2130 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2131 "%s: invalid descriptor file.",
2132 function );
2133
2134 return( -1 );
2135 }
2136 if( line_index == NULL )
2137 {
2138 libcerror_error_set(
2139 error,
2140 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2141 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2142 "%s: invalid line index.",
2143 function );
2144
2145 return( -1 );
2146 }
2147 if( number_of_lines <= 0 )
2148 {
2149 libcerror_error_set(
2150 error,
2151 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2152 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
2153 "%s: invalid number of lines value out of bounds.",
2154 function );
2155
2156 return( -1 );
2157 }
2158 safe_line_index = *line_index;
2159
2160 if( ( safe_line_index < 0 )
2161 || ( safe_line_index >= number_of_lines ) )
2162 {
2163 libcerror_error_set(
2164 error,
2165 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2166 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
2167 "%s: invalid line index value out of bounds.",
2168 function );
2169
2170 return( -1 );
2171 }
2172 if( libcsplit_narrow_split_string_get_segment_by_index(
2173 lines,
2174 safe_line_index,
2175 &line_string_segment,
2176 &line_string_segment_size,
2177 error ) != 1 )
2178 {
2179 libcerror_error_set(
2180 error,
2181 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2182 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2183 "%s: unable to retrieve line: %d.",
2184 function,
2185 safe_line_index );
2186
2187 return( -1 );
2188 }
2189 if( line_string_segment == NULL )
2190 {
2191 libcerror_error_set(
2192 error,
2193 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2194 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2195 "%s: missing line string segment: %d.",
2196 function,
2197 safe_line_index );
2198
2199 return( -1 );
2200 }
2201 if( line_string_segment_size < 2 )
2202 {
2203 libcerror_error_set(
2204 error,
2205 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2206 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
2207 "%s: invalid line string segment: %d size value out of bounds.",
2208 function,
2209 safe_line_index );
2210
2211 return( -1 );
2212 }
2213 /* Ignore trailing white space
2214 */
2215 line_string_segment_index = line_string_segment_size - 2;
2216
2217 while( line_string_segment_index > 0 )
2218 {
2219 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
2220 && ( line_string_segment[ line_string_segment_index ] != '\n' )
2221 && ( line_string_segment[ line_string_segment_index ] != '\f' )
2222 && ( line_string_segment[ line_string_segment_index ] != '\v' )
2223 && ( line_string_segment[ line_string_segment_index ] != '\r' )
2224 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
2225 {
2226 break;
2227 }
2228 line_string_segment_index--;
2229 line_string_segment_size--;
2230 }
2231 /* Ignore leading white space
2232 */
2233 line_string_segment_index = 0;
2234
2235 while( line_string_segment_index < line_string_segment_size )
2236 {
2237 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
2238 && ( line_string_segment[ line_string_segment_index ] != '\n' )
2239 && ( line_string_segment[ line_string_segment_index ] != '\f' )
2240 && ( line_string_segment[ line_string_segment_index ] != '\v' )
2241 && ( line_string_segment[ line_string_segment_index ] != '\r' )
2242 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
2243 {
2244 break;
2245 }
2246 line_string_segment_index++;
2247 }
2248 if( ( ( line_string_segment_size - line_string_segment_index ) != 21 )
2249 || ( narrow_string_compare_no_case(
2250 &( line_string_segment[ line_string_segment_index ] ),
2251 vmdk_descriptor_file_disk_database_section_signature,
2252 20 ) != 0 ) )
2253 {
2254 libcerror_error_set(
2255 error,
2256 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2257 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2258 "%s: unsupported disk database section signature.",
2259 function );
2260
2261 return( -1 );
2262 }
2263 safe_line_index++;
2264
2265 while( safe_line_index < number_of_lines )
2266 {
2267 if( libcsplit_narrow_split_string_get_segment_by_index(
2268 lines,
2269 safe_line_index,
2270 &line_string_segment,
2271 &line_string_segment_size,
2272 error ) != 1 )
2273 {
2274 libcerror_error_set(
2275 error,
2276 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2277 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2278 "%s: unable to retrieve line: %d.",
2279 function,
2280 safe_line_index );
2281
2282 return( -1 );
2283 }
2284 if( line_string_segment == NULL )
2285 {
2286 libcerror_error_set(
2287 error,
2288 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2289 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2290 "%s: missing line string segment: %d.",
2291 function,
2292 safe_line_index );
2293
2294 return( -1 );
2295 }
2296 if( line_string_segment_size < 2 )
2297 {
2298 safe_line_index++;
2299
2300 continue;
2301 }
2302 /* Ignore trailing white space
2303 */
2304 line_string_segment_index = line_string_segment_size - 2;
2305
2306 while( line_string_segment_index > 0 )
2307 {
2308 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
2309 && ( line_string_segment[ line_string_segment_index ] != '\n' )
2310 && ( line_string_segment[ line_string_segment_index ] != '\f' )
2311 && ( line_string_segment[ line_string_segment_index ] != '\v' )
2312 && ( line_string_segment[ line_string_segment_index ] != '\r' )
2313 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
2314 {
2315 break;
2316 }
2317 line_string_segment_index--;
2318 line_string_segment_size--;
2319 }
2320 /* Ignore leading white space
2321 */
2322 line_string_segment_index = 0;
2323
2324 while( line_string_segment_index < line_string_segment_size )
2325 {
2326 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
2327 && ( line_string_segment[ line_string_segment_index ] != '\n' )
2328 && ( line_string_segment[ line_string_segment_index ] != '\f' )
2329 && ( line_string_segment[ line_string_segment_index ] != '\v' )
2330 && ( line_string_segment[ line_string_segment_index ] != '\r' )
2331 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
2332 {
2333 break;
2334 }
2335 line_string_segment_index++;
2336 }
2337 /* Skip an empty line
2338 */
2339 if( ( line_string_segment_index >= line_string_segment_size )
2340 || ( line_string_segment[ line_string_segment_index ] == 0 ) )
2341 {
2342 safe_line_index++;
2343
2344 continue;
2345 }
2346 /* Determine the value identifier
2347 */
2348 value_identifier = &( line_string_segment[ line_string_segment_index ] );
2349 value_identifier_length = 0;
2350
2351 while( line_string_segment_index < line_string_segment_size )
2352 {
2353 if( ( line_string_segment[ line_string_segment_index ] == '\t' )
2354 || ( line_string_segment[ line_string_segment_index ] == '\n' )
2355 || ( line_string_segment[ line_string_segment_index ] == '\f' )
2356 || ( line_string_segment[ line_string_segment_index ] == '\v' )
2357 || ( line_string_segment[ line_string_segment_index ] == '\r' )
2358 || ( line_string_segment[ line_string_segment_index ] == ' ' )
2359 || ( line_string_segment[ line_string_segment_index ] == '=' ) )
2360 {
2361 break;
2362 }
2363 value_identifier_length++;
2364
2365 line_string_segment_index++;
2366 }
2367 /* Skip a line not containing a value
2368 */
2369 if( ( line_string_segment_index >= line_string_segment_size )
2370 || ( line_string_segment[ line_string_segment_index ] == 0 ) )
2371 {
2372 safe_line_index++;
2373
2374 continue;
2375 }
2376 /* Make sure the value identifier is terminated by an end of string
2377 */
2378 line_string_segment[ line_string_segment_index ] = 0;
2379
2380 line_string_segment_index++;
2381
2382 /* Ignore whitespace
2383 */
2384 while( line_string_segment_index < line_string_segment_size )
2385 {
2386 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
2387 && ( line_string_segment[ line_string_segment_index ] != '\n' )
2388 && ( line_string_segment[ line_string_segment_index ] != '\f' )
2389 && ( line_string_segment[ line_string_segment_index ] != '\v' )
2390 && ( line_string_segment[ line_string_segment_index ] != '\r' )
2391 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
2392 {
2393 break;
2394 }
2395 line_string_segment_index++;
2396 }
2397 if( line_string_segment[ line_string_segment_index ] == '=' )
2398 {
2399 line_string_segment_index++;
2400
2401 while( line_string_segment_index < line_string_segment_size )
2402 {
2403 if( ( line_string_segment[ line_string_segment_index ] != '\t' )
2404 && ( line_string_segment[ line_string_segment_index ] != '\n' )
2405 && ( line_string_segment[ line_string_segment_index ] != '\f' )
2406 && ( line_string_segment[ line_string_segment_index ] != '\v' )
2407 && ( line_string_segment[ line_string_segment_index ] != '\r' )
2408 && ( line_string_segment[ line_string_segment_index ] != ' ' ) )
2409 {
2410 break;
2411 }
2412 line_string_segment_index++;
2413 }
2414 }
2415 /* Skip a line not containing a value
2416 */
2417 if( ( line_string_segment_index >= line_string_segment_size )
2418 || ( line_string_segment[ line_string_segment_index ] == 0 ) )
2419 {
2420 safe_line_index++;
2421
2422 continue;
2423 }
2424 /* Determine the value
2425 */
2426 value = &( line_string_segment[ line_string_segment_index ] );
2427 value_length = line_string_segment_size - 1;
2428
2429 /* Ingore quotes at the beginning of the value data
2430 */
2431 if( ( line_string_segment[ line_string_segment_index ] == '"' )
2432 || ( line_string_segment[ line_string_segment_index ] == '\'' ) )
2433 {
2434 line_string_segment_index++;
2435 value++;
2436 value_length--;
2437 }
2438 /* Ingore quotes at the end of the value data
2439 */
2440 if( ( line_string_segment[ value_length - 1 ] == '"' )
2441 || ( line_string_segment[ value_length - 1 ] == '\'' ) )
2442 {
2443 value_length--;
2444 }
2445 /* Make sure the value is terminated by an end of string
2446 */
2447 line_string_segment[ value_length ] = 0;
2448
2449 value_length -= line_string_segment_index;
2450
2451 if( value_identifier_length == 15 )
2452 {
2453 if( narrow_string_compare_no_case(
2454 value_identifier,
2455 "ddb.adapterType",
2456 15 ) == 0 )
2457 {
2458 /* TODO */
2459 }
2460 }
2461 else if( value_identifier_length == 16 )
2462 {
2463 if( narrow_string_compare_no_case(
2464 value_identifier,
2465 "ddb.toolsVersion",
2466 16 ) == 0 )
2467 {
2468 /* TODO */
2469 }
2470 }
2471 else if( value_identifier_length == 18 )
2472 {
2473 if( narrow_string_compare_no_case(
2474 value_identifier,
2475 "ddb.geometry.heads",
2476 18 ) == 0 )
2477 {
2478 /* TODO */
2479 }
2480 }
2481 else if( value_identifier_length == 20 )
2482 {
2483 if( narrow_string_compare_no_case(
2484 value_identifier,
2485 "ddb.geometry.sectors",
2486 20 ) == 0 )
2487 {
2488 /* TODO */
2489 }
2490 else if( narrow_string_compare_no_case(
2491 value_identifier,
2492 "ddb.virtualHWVersion",
2493 20 ) == 0 )
2494 {
2495 /* TODO */
2496 }
2497 }
2498 else if( value_identifier_length == 22 )
2499 {
2500 if( narrow_string_compare_no_case(
2501 value_identifier,
2502 "ddb.geometry.cylinders",
2503 22 ) == 0 )
2504 {
2505 /* TODO */
2506 }
2507 }
2508 #if defined( HAVE_DEBUG_OUTPUT )
2509 else if( libcnotify_verbose != 0 )
2510 {
2511 libcnotify_printf(
2512 "%s: value: %d\t\t\t: %s = %s\n",
2513 function,
2514 safe_line_index,
2515 value_identifier,
2516 value );
2517 }
2518 #endif
2519 safe_line_index++;
2520 }
2521 #if defined( HAVE_DEBUG_OUTPUT )
2522 if( libcnotify_verbose != 0 )
2523 {
2524 libcnotify_printf(
2525 "\n" );
2526 }
2527 #endif
2528 *line_index = safe_line_index;
2529
2530 return( 1 );
2531 }
2532
2533 /* Retrieves the number of extents
2534 * Returns 1 if successful or -1 on error
2535 */
libvmdk_descriptor_file_get_number_of_extents(libvmdk_descriptor_file_t * descriptor_file,int * number_of_extents,libcerror_error_t ** error)2536 int libvmdk_descriptor_file_get_number_of_extents(
2537 libvmdk_descriptor_file_t *descriptor_file,
2538 int *number_of_extents,
2539 libcerror_error_t **error )
2540 {
2541 static char *function = "libvmdk_descriptor_file_get_number_of_extents";
2542
2543 if( descriptor_file == NULL )
2544 {
2545 libcerror_error_set(
2546 error,
2547 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2548 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2549 "%s: invalid descriptor file.",
2550 function );
2551
2552 return( -1 );
2553 }
2554 if( libcdata_array_get_number_of_entries(
2555 descriptor_file->extents_array,
2556 number_of_extents,
2557 error ) != 1 )
2558 {
2559 libcerror_error_set(
2560 error,
2561 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2562 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2563 "%s: unable to retrieve number of entries in extents array.",
2564 function );
2565
2566 return( -1 );
2567 }
2568 return( 1 );
2569 }
2570
2571 /* Retrieves a specific extent
2572 * Returns 1 if successful or -1 on error
2573 */
libvmdk_descriptor_file_get_extent_by_index(libvmdk_descriptor_file_t * descriptor_file,int extent_index,libvmdk_internal_extent_descriptor_t ** extent_descriptor,libcerror_error_t ** error)2574 int libvmdk_descriptor_file_get_extent_by_index(
2575 libvmdk_descriptor_file_t *descriptor_file,
2576 int extent_index,
2577 libvmdk_internal_extent_descriptor_t **extent_descriptor,
2578 libcerror_error_t **error )
2579 {
2580 static char *function = "libvmdk_descriptor_file_get_extent_by_index";
2581
2582 if( descriptor_file == NULL )
2583 {
2584 libcerror_error_set(
2585 error,
2586 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2587 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2588 "%s: invalid descriptor file.",
2589 function );
2590
2591 return( -1 );
2592 }
2593 if( libcdata_array_get_entry_by_index(
2594 descriptor_file->extents_array,
2595 extent_index,
2596 (intptr_t **) extent_descriptor,
2597 error ) != 1 )
2598 {
2599 libcerror_error_set(
2600 error,
2601 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2602 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2603 "%s: unable to retrieve entry: %d from extents array.",
2604 function,
2605 extent_index );
2606
2607 return( -1 );
2608 }
2609 return( 1 );
2610 }
2611
2612 /* Retrieves the parent content identifier
2613 * Returns 1 if successful, 0 if not available or -1 on error
2614 */
libvmdk_descriptor_file_get_parent_content_identifier(libvmdk_descriptor_file_t * descriptor_file,uint32_t * parent_content_identifier,libcerror_error_t ** error)2615 int libvmdk_descriptor_file_get_parent_content_identifier(
2616 libvmdk_descriptor_file_t *descriptor_file,
2617 uint32_t *parent_content_identifier,
2618 libcerror_error_t **error )
2619 {
2620 static char *function = "libvmdk_descriptor_file_get_parent_content_identifier";
2621
2622 if( descriptor_file == NULL )
2623 {
2624 libcerror_error_set(
2625 error,
2626 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2627 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2628 "%s: invalid descriptor file.",
2629 function );
2630
2631 return( -1 );
2632 }
2633 if( parent_content_identifier == NULL )
2634 {
2635 libcerror_error_set(
2636 error,
2637 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2638 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2639 "%s: invalid parent content identifier.",
2640 function );
2641
2642 return( -1 );
2643 }
2644 if( descriptor_file->parent_content_identifier_set == 0 )
2645 {
2646 return( 0 );
2647 }
2648 *parent_content_identifier = descriptor_file->parent_content_identifier;
2649
2650 return( 1 );
2651 }
2652
2653 /* Retrieves the size of the UTF-8 encoded parent filename
2654 * The returned size includes the end of string character
2655 * Returns 1 if successful, 0 if not available or -1 on error
2656 */
libvmdk_descriptor_file_get_utf8_parent_filename_size(libvmdk_descriptor_file_t * descriptor_file,size_t * utf8_string_size,libcerror_error_t ** error)2657 int libvmdk_descriptor_file_get_utf8_parent_filename_size(
2658 libvmdk_descriptor_file_t *descriptor_file,
2659 size_t *utf8_string_size,
2660 libcerror_error_t **error )
2661 {
2662 static char *function = "libvmdk_descriptor_file_get_utf8_parent_filename_size";
2663
2664 if( descriptor_file == NULL )
2665 {
2666 libcerror_error_set(
2667 error,
2668 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2669 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2670 "%s: invalid descriptor file.",
2671 function );
2672
2673 return( -1 );
2674 }
2675 if( ( descriptor_file->parent_filename == NULL )
2676 || ( descriptor_file->parent_filename_size == 0 ) )
2677 {
2678 return( 0 );
2679 }
2680 if( libuna_utf8_string_size_from_utf8_stream(
2681 descriptor_file->parent_filename,
2682 descriptor_file->parent_filename_size,
2683 utf8_string_size,
2684 error ) != 1 )
2685 {
2686 libcerror_error_set(
2687 error,
2688 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2689 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2690 "%s: unable to retrieve UTF-8 string size.",
2691 function );
2692
2693 return( -1 );
2694 }
2695 return( 1 );
2696 }
2697
2698 /* Retrieves the UTF-8 encoded parent filename
2699 * The size should include the end of string character
2700 * Returns 1 if successful, 0 if not available or -1 on error
2701 */
libvmdk_descriptor_file_get_utf8_parent_filename(libvmdk_descriptor_file_t * descriptor_file,uint8_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)2702 int libvmdk_descriptor_file_get_utf8_parent_filename(
2703 libvmdk_descriptor_file_t *descriptor_file,
2704 uint8_t *utf8_string,
2705 size_t utf8_string_size,
2706 libcerror_error_t **error )
2707 {
2708 static char *function = "libvmdk_descriptor_file_get_utf8_parent_filename";
2709
2710 if( descriptor_file == NULL )
2711 {
2712 libcerror_error_set(
2713 error,
2714 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2715 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2716 "%s: invalid descriptor file.",
2717 function );
2718
2719 return( -1 );
2720 }
2721 if( ( descriptor_file->parent_filename == NULL )
2722 || ( descriptor_file->parent_filename_size == 0 ) )
2723 {
2724 return( 0 );
2725 }
2726 if( libuna_utf8_string_copy_from_utf8_stream(
2727 utf8_string,
2728 utf8_string_size,
2729 descriptor_file->parent_filename,
2730 descriptor_file->parent_filename_size,
2731 error ) != 1 )
2732 {
2733 libcerror_error_set(
2734 error,
2735 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2736 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
2737 "%s: unable to copy parent filename to UTF-8 string.",
2738 function );
2739
2740 return( -1 );
2741 }
2742 return( 1 );
2743 }
2744
2745 /* Retrieves the size of the UTF-16 encoded parent filename
2746 * The returned size includes the end of string character
2747 * Returns 1 if successful, 0 if not available or -1 on error
2748 */
libvmdk_descriptor_file_get_utf16_parent_filename_size(libvmdk_descriptor_file_t * descriptor_file,size_t * utf16_string_size,libcerror_error_t ** error)2749 int libvmdk_descriptor_file_get_utf16_parent_filename_size(
2750 libvmdk_descriptor_file_t *descriptor_file,
2751 size_t *utf16_string_size,
2752 libcerror_error_t **error )
2753 {
2754 static char *function = "libvmdk_descriptor_file_get_utf16_parent_filename_size";
2755
2756 if( descriptor_file == NULL )
2757 {
2758 libcerror_error_set(
2759 error,
2760 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2761 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2762 "%s: invalid descriptor file.",
2763 function );
2764
2765 return( -1 );
2766 }
2767 if( ( descriptor_file->parent_filename == NULL )
2768 || ( descriptor_file->parent_filename_size == 0 ) )
2769 {
2770 return( 0 );
2771 }
2772 if( libuna_utf16_string_size_from_utf8_stream(
2773 descriptor_file->parent_filename,
2774 descriptor_file->parent_filename_size,
2775 utf16_string_size,
2776 error ) != 1 )
2777 {
2778 libcerror_error_set(
2779 error,
2780 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2781 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2782 "%s: unable to retrieve UTF-16 string size.",
2783 function );
2784
2785 return( -1 );
2786 }
2787 return( 1 );
2788 }
2789
2790 /* Retrieves the UTF-16 encoded parent filename
2791 * The size should include the end of string character
2792 * Returns 1 if successful, 0 if not available or -1 on error
2793 */
libvmdk_descriptor_file_get_utf16_parent_filename(libvmdk_descriptor_file_t * descriptor_file,uint16_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)2794 int libvmdk_descriptor_file_get_utf16_parent_filename(
2795 libvmdk_descriptor_file_t *descriptor_file,
2796 uint16_t *utf16_string,
2797 size_t utf16_string_size,
2798 libcerror_error_t **error )
2799 {
2800 static char *function = "libvmdk_descriptor_file_get_utf16_parent_filename";
2801
2802 if( descriptor_file == NULL )
2803 {
2804 libcerror_error_set(
2805 error,
2806 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2807 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2808 "%s: invalid descriptor file.",
2809 function );
2810
2811 return( -1 );
2812 }
2813 if( ( descriptor_file->parent_filename == NULL )
2814 || ( descriptor_file->parent_filename_size == 0 ) )
2815 {
2816 return( 0 );
2817 }
2818 if( libuna_utf16_string_copy_from_utf8_stream(
2819 utf16_string,
2820 utf16_string_size,
2821 descriptor_file->parent_filename,
2822 descriptor_file->parent_filename_size,
2823 error ) != 1 )
2824 {
2825 libcerror_error_set(
2826 error,
2827 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2828 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
2829 "%s: unable to copy parent filename to UTF-16 string.",
2830 function );
2831
2832 return( -1 );
2833 }
2834 return( 1 );
2835 }
2836
2837