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