1 /*
2  * Date and time values functions
3  *
4  * Copyright (C) 2009-2018, Joachim Metz <joachim.metz@gmail.com>
5  *
6  * Refer to AUTHORS for acknowledgements.
7  *
8  * This software 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 software 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 software.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <common.h>
23 #include <memory.h>
24 #include <types.h>
25 
26 #include "libfdatetime_definitions.h"
27 #include "libfdatetime_date_time_values.h"
28 #include "libfdatetime_libcerror.h"
29 #include "libfdatetime_types.h"
30 
31 /* Creates date time values
32  * Make sure the value date_time_values is referencing, is set to NULL
33  * Returns 1 if successful or -1 on error
34  */
libfdatetime_date_time_values_initialize(libfdatetime_date_time_values_t ** date_time_values,libcerror_error_t ** error)35 int libfdatetime_date_time_values_initialize(
36      libfdatetime_date_time_values_t **date_time_values,
37      libcerror_error_t **error )
38 {
39 	static char *function = "libfdatetime_date_time_values_initialize";
40 
41 	if( date_time_values == NULL )
42 	{
43 		libcerror_error_set(
44 		 error,
45 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
46 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
47 		 "%s: invalid date time values.",
48 		 function );
49 
50 		return( -1 );
51 	}
52 	if( *date_time_values != NULL )
53 	{
54 		libcerror_error_set(
55 		 error,
56 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
57 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
58 		 "%s: invalid date time values value already set.",
59 		 function );
60 
61 		return( -1 );
62 	}
63 	*date_time_values = memory_allocate_structure(
64 	                     libfdatetime_date_time_values_t );
65 
66 	if( *date_time_values == NULL )
67 	{
68 		libcerror_error_set(
69 		 error,
70 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
71 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
72 		 "%s: unable to create date time values.",
73 		 function );
74 
75 		goto on_error;
76 	}
77 	if( memory_set(
78 	     *date_time_values,
79 	     0,
80 	     sizeof( libfdatetime_date_time_values_t ) ) == NULL )
81 	{
82 		libcerror_error_set(
83 		 error,
84 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
85 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
86 		 "%s: unable to clear date time values.",
87 		 function );
88 
89 		goto on_error;
90 	}
91 	return( 1 );
92 
93 on_error:
94 	if( *date_time_values != NULL )
95 	{
96 		memory_free(
97 		 *date_time_values );
98 
99 		*date_time_values = NULL;
100 	}
101 	return( -1 );
102 }
103 
104 /* Frees date time values
105  * Returns 1 if successful or -1 on error
106  */
libfdatetime_date_time_values_free(libfdatetime_date_time_values_t ** date_time_values,libcerror_error_t ** error)107 int libfdatetime_date_time_values_free(
108      libfdatetime_date_time_values_t **date_time_values,
109      libcerror_error_t **error )
110 {
111 	static char *function = "libfdatetime_date_time_values_free";
112 
113 	if( date_time_values == NULL )
114 	{
115 		libcerror_error_set(
116 		 error,
117 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
118 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
119 		 "%s: invalid date time values.",
120 		 function );
121 
122 		return( -1 );
123 	}
124 	if( *date_time_values != NULL )
125 	{
126 		memory_free(
127 		 *date_time_values );
128 
129 		*date_time_values = NULL;
130 	}
131 	return( 1 );
132 }
133 
134 /* Deterimes the size of the string for the date and time values
135  * The string size includes the end of string character
136  * Returns 1 if successful, 0 if the date and time values are not valid or -1 on error
137  */
libfdatetime_date_time_values_get_string_size(libfdatetime_date_time_values_t * date_time_values,size_t * string_size,uint32_t string_format_flags,libcerror_error_t ** error)138 int libfdatetime_date_time_values_get_string_size(
139      libfdatetime_date_time_values_t *date_time_values,
140      size_t *string_size,
141      uint32_t string_format_flags,
142      libcerror_error_t **error )
143 {
144 	static char *function       = "libfdatetime_date_time_values_get_string_size";
145 	uint32_t string_format_type = 0;
146 	uint32_t supported_flags    = 0;
147 	uint8_t days_in_month       = 0;
148 
149 	if( date_time_values == NULL )
150 	{
151 		libcerror_error_set(
152 		 error,
153 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
154 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
155 		 "%s: invalid date time values.",
156 		 function );
157 
158 		return( -1 );
159 	}
160 	if( string_size == NULL )
161 	{
162 		libcerror_error_set(
163 		 error,
164 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
165 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
166 		 "%s: invalid string size.",
167 		 function );
168 
169 		return( -1 );
170 	}
171 	supported_flags = 0x000000ffUL
172 	                | LIBFDATETIME_STRING_FORMAT_FLAG_DATE
173 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME
174 	                | LIBFDATETIME_STRING_FORMAT_FLAG_DURATION
175 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MILLI_SECONDS
176 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS
177 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS
178 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIMEZONE_INDICATOR;
179 
180 	if( ( string_format_flags & supported_flags ) == 0 )
181 	{
182 		libcerror_error_set(
183 		 error,
184 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
185 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
186 		 "%s: unsupported string format flags: 0x%08" PRIx32 ".",
187 		 function,
188 		 string_format_flags );
189 
190 		return( -1 );
191 	}
192 	string_format_type = string_format_flags & 0x000000ffUL;
193 
194 	if( ( string_format_type != LIBFDATETIME_STRING_FORMAT_TYPE_CTIME )
195 	 && ( string_format_type != LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 ) )
196 	{
197 		libcerror_error_set(
198 		 error,
199 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
200 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
201 		 "%s: unsupported string format type: 0x%08" PRIx32 ".",
202 		 function,
203 		 string_format_type );
204 
205 		return( -1 );
206 	}
207 	/* Validate the date and time if necessary
208 	 */
209 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_DATE ) != 0 )
210 	{
211 		if( date_time_values->year > 9999 )
212 		{
213 			return( 0 );
214 		}
215 		if( ( date_time_values->month == 0 )
216 		 || ( date_time_values->month > 12 ) )
217 		{
218 			return( 0 );
219 		}
220 		switch( date_time_values->month )
221 		{
222 			case 1:
223 			case 3:
224 			case 5:
225 			case 7:
226 			case 8:
227 			case 10:
228 			case 12:
229 				days_in_month = 31;
230 				break;
231 			case 4:
232 			case 6:
233 			case 9:
234 			case 11:
235 				days_in_month = 30;
236 				break;
237 			case 2:
238 				if( ( ( ( date_time_values->year % 4 ) == 0 )
239 				  &&  ( ( date_time_values->year % 100 ) != 0 ) )
240 				 || ( ( date_time_values->year % 400 ) == 0 ) )
241 				{
242 					days_in_month = 29;
243 				}
244 				else
245 				{
246 					days_in_month = 28;
247 				}
248 				break;
249 		}
250 		if( ( date_time_values->day == 0 )
251 		 || ( date_time_values->day > days_in_month ) )
252 		{
253 			return( 0 );
254 		}
255 	}
256 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME ) != 0 )
257 	{
258 		if( date_time_values->hours > 23 )
259 		{
260 			return( 0 );
261 		}
262 		if( date_time_values->minutes > 59 )
263 		{
264 			return( 0 );
265 		}
266 		if( date_time_values->seconds > 59 )
267 		{
268 			return( 0 );
269 		}
270 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MILLI_SECONDS ) != 0 )
271 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
272 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
273 		{
274 			if( date_time_values->milli_seconds > 999 )
275 			{
276 				return( 0 );
277 			}
278 		}
279 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
280 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
281 		{
282 			if( date_time_values->micro_seconds > 999 )
283 			{
284 				return( 0 );
285 			}
286 		}
287 		if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 )
288 		{
289 			if( date_time_values->nano_seconds > 999 )
290 			{
291 				return( 0 );
292 			}
293 		}
294 	}
295 	/* End of string character
296 	 */
297 	*string_size = 1;
298 
299 	/* Determine the size of the date and time string
300 	 */
301 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_DATE ) != 0 )
302 	{
303 		/* Example: Jan 01, 1970
304 		 */
305 		if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_CTIME )
306 		{
307 			*string_size += 12;
308 		}
309 		/* Example: 1970-01-01
310 		 */
311 		else if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 )
312 		{
313 			*string_size += 10;
314 		}
315 	}
316 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME ) != 0 )
317 	{
318 		/* Date and time separator
319 		 */
320 		if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_DATE ) != 0 )
321 		{
322 			*string_size += 1;
323 		}
324 		/* Example: 00:00:00
325 		 */
326 		*string_size += 8;
327 
328 		/* Example: .000
329 		 */
330 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MILLI_SECONDS ) != 0 )
331 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
332 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
333 		{
334 			*string_size += 4;
335 		}
336 		/* Example: .000000
337 		 */
338 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
339 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
340 		{
341 			*string_size += 3;
342 		}
343 		/* Example: .000000000
344 		 */
345 		if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 )
346 		{
347 			*string_size += 3;
348 		}
349 	}
350 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIMEZONE_INDICATOR ) != 0 )
351 	{
352 		/* Example: UTC
353 		 */
354 		if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_CTIME )
355 		{
356 			*string_size += 4;
357 		}
358 		/* Example: Z
359 		 */
360 		else if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 )
361 		{
362 			*string_size += 1;
363 		}
364 	}
365 	return( 1 );
366 }
367 
368 /* Converts the date and time values into an UTF-8 string
369  * The string size should include the end of string character
370  * Returns 1 if successful, 0 if the date and time values are not valid or -1 on error
371  */
libfdatetime_date_time_values_copy_to_utf8_string_with_index(libfdatetime_date_time_values_t * date_time_values,uint8_t * utf8_string,size_t utf8_string_size,size_t * utf8_string_index,uint32_t string_format_flags,libcerror_error_t ** error)372 int libfdatetime_date_time_values_copy_to_utf8_string_with_index(
373      libfdatetime_date_time_values_t *date_time_values,
374      uint8_t *utf8_string,
375      size_t utf8_string_size,
376      size_t *utf8_string_index,
377      uint32_t string_format_flags,
378      libcerror_error_t **error )
379 {
380 	char *month_string          = NULL;
381 	static char *function       = "libfdatetime_date_time_values_copy_to_utf8_string_with_index";
382 	size_t string_index         = 0;
383 	uint32_t string_format_type = 0;
384 	uint32_t supported_flags    = 0;
385 	uint16_t micro_seconds      = 0;
386 	uint16_t milli_seconds      = 0;
387 	uint16_t nano_seconds       = 0;
388 	uint16_t year_value         = 0;
389 	uint8_t days_in_month       = 0;
390 
391 	if( date_time_values == NULL )
392 	{
393 		libcerror_error_set(
394 		 error,
395 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
396 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
397 		 "%s: invalid date time values.",
398 		 function );
399 
400 		return( -1 );
401 	}
402 	if( utf8_string == NULL )
403 	{
404 		libcerror_error_set(
405 		 error,
406 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
407 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
408 		 "%s: invalid UTF-8 string.",
409 		 function );
410 
411 		return( -1 );
412 	}
413 	if( utf8_string_size > (size_t) SSIZE_MAX )
414 	{
415 		libcerror_error_set(
416 		 error,
417 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
418 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
419 		 "%s: invalid UTF-8 string size value exceeds maximum.",
420 		 function );
421 
422 		return( -1 );
423 	}
424 	if( utf8_string_index == NULL )
425 	{
426 		libcerror_error_set(
427 		 error,
428 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
429 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
430 		 "%s: invalid UTF-8 string index.",
431 		 function );
432 
433 		return( -1 );
434 	}
435 	supported_flags = 0x000000ffUL
436 	                | LIBFDATETIME_STRING_FORMAT_FLAG_DATE
437 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME
438 	                | LIBFDATETIME_STRING_FORMAT_FLAG_DURATION
439 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MILLI_SECONDS
440 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS
441 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS
442 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIMEZONE_INDICATOR;
443 
444 	if( ( string_format_flags & supported_flags ) == 0 )
445 	{
446 		libcerror_error_set(
447 		 error,
448 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
449 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
450 		 "%s: unsupported string format flags: 0x%08" PRIx32 ".",
451 		 function,
452 		 string_format_flags );
453 
454 		return( -1 );
455 	}
456 	string_format_type = string_format_flags & 0x000000ffUL;
457 
458 	if( ( string_format_type != LIBFDATETIME_STRING_FORMAT_TYPE_CTIME )
459 	 && ( string_format_type != LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 ) )
460 	{
461 		libcerror_error_set(
462 		 error,
463 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
464 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
465 		 "%s: unsupported string format type: 0x%08" PRIx32 ".",
466 		 function,
467 		 string_format_type );
468 
469 		return( -1 );
470 	}
471 	string_index = *utf8_string_index;
472 
473 	/* Validate the date and time if necessary
474 	 */
475 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_DATE ) != 0 )
476 	{
477 		if( date_time_values->year > 9999 )
478 		{
479 			return( 0 );
480 		}
481 		if( ( date_time_values->month == 0 )
482 		 || ( date_time_values->month > 12 ) )
483 		{
484 			return( 0 );
485 		}
486 		switch( date_time_values->month )
487 		{
488 			case 1:
489 			case 3:
490 			case 5:
491 			case 7:
492 			case 8:
493 			case 10:
494 			case 12:
495 				days_in_month = 31;
496 				break;
497 			case 4:
498 			case 6:
499 			case 9:
500 			case 11:
501 				days_in_month = 30;
502 				break;
503 			case 2:
504 				if( ( ( ( date_time_values->year % 4 ) == 0 )
505 				  &&  ( ( date_time_values->year % 100 ) != 0 ) )
506 				 || ( ( date_time_values->year % 400 ) == 0 ) )
507 				{
508 					days_in_month = 29;
509 				}
510 				else
511 				{
512 					days_in_month = 28;
513 				}
514 				break;
515 		}
516 		if( ( date_time_values->day == 0 )
517 		 || ( date_time_values->day > days_in_month ) )
518 		{
519 			return( 0 );
520 		}
521 	}
522 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME ) != 0 )
523 	{
524 		if( date_time_values->hours > 23 )
525 		{
526 			return( 0 );
527 		}
528 		if( date_time_values->minutes > 59 )
529 		{
530 			return( 0 );
531 		}
532 		if( date_time_values->seconds > 59 )
533 		{
534 			return( 0 );
535 		}
536 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MILLI_SECONDS ) != 0 )
537 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
538 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
539 		{
540 			if( date_time_values->milli_seconds > 999 )
541 			{
542 				return( 0 );
543 			}
544 		}
545 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
546 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
547 		{
548 			if( date_time_values->micro_seconds > 999 )
549 			{
550 				return( 0 );
551 			}
552 		}
553 		if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 )
554 		{
555 			if( date_time_values->nano_seconds > 999 )
556 			{
557 				return( 0 );
558 			}
559 		}
560 	}
561 	/* Create the date and time string
562 	 */
563 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_DATE ) != 0 )
564 	{
565 		if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_CTIME )
566 		{
567 			switch( date_time_values->month )
568 			{
569 				case 1:
570 					month_string = "Jan";
571 					break;
572 				case 2:
573 					month_string = "Feb";
574 					break;
575 				case 3:
576 					month_string = "Mar";
577 					break;
578 				case 4:
579 					month_string = "Apr";
580 					break;
581 				case 5:
582 					month_string = "May";
583 					break;
584 				case 6:
585 					month_string = "Jun";
586 					break;
587 				case 7:
588 					month_string = "Jul";
589 					break;
590 				case 8:
591 					month_string = "Aug";
592 					break;
593 				case 9:
594 					month_string = "Sep";
595 					break;
596 				case 10:
597 					month_string = "Oct";
598 					break;
599 				case 11:
600 					month_string = "Nov";
601 					break;
602 				case 12:
603 					month_string = "Dec";
604 					break;
605 			}
606 			if( ( string_index + 12 ) > utf8_string_size )
607 			{
608 				libcerror_error_set(
609 				 error,
610 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
611 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
612 				 "%s: UTF-8 string is too small.",
613 				 function );
614 
615 				return( -1 );
616 			}
617 			if( month_string == NULL )
618 			{
619 				libcerror_error_set(
620 				 error,
621 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
622 				 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
623 				 "%s: missing month string.",
624 				 function );
625 
626 				return( -1 );
627 			}
628 			/* Format: mmm dd, yyyy */
629 			utf8_string[ string_index++ ] = (uint8_t) month_string[ 0 ];
630 			utf8_string[ string_index++ ] = (uint8_t) month_string[ 1 ];
631 			utf8_string[ string_index++ ] = (uint8_t) month_string[ 2 ];
632 
633 			utf8_string[ string_index++ ] = (uint8_t) ' ';
634 
635 			utf8_string[ string_index++ ] = (uint8_t) '0' + ( date_time_values->day / 10 );
636 			utf8_string[ string_index++ ] = (uint8_t) '0' + ( date_time_values->day % 10 );
637 
638 			utf8_string[ string_index++ ] = (uint8_t) ',';
639 			utf8_string[ string_index++ ] = (uint8_t) ' ';
640 
641 			year_value                    = date_time_values->year;
642 			utf8_string[ string_index++ ] = (uint8_t) '0' + (uint8_t) ( year_value / 1000 );
643 			year_value                   %= 1000;
644 			utf8_string[ string_index++ ] = (uint8_t) '0' + (uint8_t) ( year_value / 100 );
645 			year_value                   %= 100;
646 			utf8_string[ string_index++ ] = (uint8_t) '0' + (uint8_t) ( year_value / 10 );
647 			year_value                   %= 10;
648 			utf8_string[ string_index++ ] = (uint8_t) '0' + (uint8_t) year_value;
649 
650 			if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME ) != 0 )
651 			{
652 				if( ( string_index + 1 ) > utf8_string_size )
653 				{
654 					libcerror_error_set(
655 					 error,
656 					 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
657 					 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
658 					 "%s: UTF-8 string is too small.",
659 					 function );
660 
661 					return( -1 );
662 				}
663 				utf8_string[ string_index++ ] = (uint8_t) ' ';
664 			}
665 		}
666 		else if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 )
667 		{
668 			if( ( string_index + 10 ) > utf8_string_size )
669 			{
670 				libcerror_error_set(
671 				 error,
672 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
673 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
674 				 "%s: UTF-8 string is too small.",
675 				 function );
676 
677 				return( -1 );
678 			}
679 			/* Format: yyyy-mm-dd */
680 			year_value                    = date_time_values->year;
681 			utf8_string[ string_index++ ] = (uint8_t) '0' + (uint8_t) ( year_value / 1000 );
682 			year_value                   %= 1000;
683 			utf8_string[ string_index++ ] = (uint8_t) '0' + (uint8_t) ( year_value / 100 );
684 			year_value                   %= 100;
685 			utf8_string[ string_index++ ] = (uint8_t) '0' + (uint8_t) ( year_value / 10 );
686 			year_value                   %= 10;
687 			utf8_string[ string_index++ ] = (uint8_t) '0' + (uint8_t) year_value;
688 
689 			utf8_string[ string_index++ ] = (uint8_t) '-';
690 
691 			utf8_string[ string_index++ ] = (uint8_t) '0' + ( date_time_values->month / 10 );
692 			utf8_string[ string_index++ ] = (uint8_t) '0' + ( date_time_values->month % 10 );
693 
694 			utf8_string[ string_index++ ] = (uint8_t) '-';
695 
696 			utf8_string[ string_index++ ] = (uint8_t) '0' + ( date_time_values->day / 10 );
697 			utf8_string[ string_index++ ] = (uint8_t) '0' + ( date_time_values->day % 10 );
698 
699 			if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME ) != 0 )
700 			{
701 				if( ( string_index + 1 ) > utf8_string_size )
702 				{
703 					libcerror_error_set(
704 					 error,
705 					 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
706 					 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
707 					 "%s: UTF-8 string is too small.",
708 					 function );
709 
710 					return( -1 );
711 				}
712 				utf8_string[ string_index++ ] = (uint8_t) 'T';
713 			}
714 		}
715 	}
716 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME ) != 0 )
717 	{
718 		if( ( string_index + 8 ) > utf8_string_size )
719 		{
720 			libcerror_error_set(
721 			 error,
722 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
723 			 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
724 			 "%s: UTF-8 string is too small.",
725 			 function );
726 
727 			return( -1 );
728 		}
729 		/* Format: HH:MM:SS */
730 		utf8_string[ string_index++ ] = (uint8_t) '0' + ( date_time_values->hours / 10 );
731 		utf8_string[ string_index++ ] = (uint8_t) '0' + ( date_time_values->hours % 10 );
732 
733 		utf8_string[ string_index++ ] = (uint8_t) ':';
734 
735 		utf8_string[ string_index++ ] = (uint8_t) '0' + ( date_time_values->minutes / 10 );
736 		utf8_string[ string_index++ ] = (uint8_t) '0' + ( date_time_values->minutes % 10 );
737 
738 		utf8_string[ string_index++ ] = (uint8_t) ':';
739 
740 		utf8_string[ string_index++ ] = (uint8_t) '0' + ( date_time_values->seconds / 10 );
741 		utf8_string[ string_index++ ] = (uint8_t) '0' + ( date_time_values->seconds % 10 );
742 
743 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MILLI_SECONDS ) != 0 )
744 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
745 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
746 		{
747 			if( ( string_index + 4 ) > utf8_string_size )
748 			{
749 				libcerror_error_set(
750 				 error,
751 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
752 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
753 				 "%s: UTF-8 string is too small.",
754 				 function );
755 
756 				return( -1 );
757 			}
758 			/* Format: .### */
759 			utf8_string[ string_index++ ] = (uint8_t) '.';
760 
761 			milli_seconds = date_time_values->milli_seconds;
762 
763 			utf8_string[ string_index + 2 ] = (uint8_t) '0' + (uint8_t) ( milli_seconds % 10 );
764 			milli_seconds                  /= 10;
765 
766 			utf8_string[ string_index + 1 ] = (uint8_t) '0' + (uint8_t) ( milli_seconds % 10 );
767 			milli_seconds                  /= 10;
768 
769 			utf8_string[ string_index ] = (uint8_t) '0' + (uint8_t) ( milli_seconds % 10 );
770 
771 			string_index += 3;
772 		}
773 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
774 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
775 		{
776 			if( ( string_index + 3 ) > utf8_string_size )
777 			{
778 				libcerror_error_set(
779 				 error,
780 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
781 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
782 				 "%s: UTF-8 string is too small.",
783 				 function );
784 
785 				return( -1 );
786 			}
787 			/* Format: ### */
788 			micro_seconds = date_time_values->micro_seconds;
789 
790 			utf8_string[ string_index + 2 ] = (uint8_t) '0' + (uint8_t) ( micro_seconds % 10 );
791 			micro_seconds                  /= 10;
792 
793 			utf8_string[ string_index + 1 ] = (uint8_t) '0' + (uint8_t) ( micro_seconds % 10 );
794 			micro_seconds                  /= 10;
795 
796 			utf8_string[ string_index ] = (uint8_t) '0' + (uint8_t) ( micro_seconds % 10 );
797 
798 			string_index += 3;
799 		}
800 		if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 )
801 		{
802 			if( ( string_index + 3 ) > utf8_string_size )
803 			{
804 				libcerror_error_set(
805 				 error,
806 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
807 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
808 				 "%s: UTF-8 string is too small.",
809 				 function );
810 
811 				return( -1 );
812 			}
813 			/* Format: ### */
814 			nano_seconds = date_time_values->nano_seconds;
815 
816 			utf8_string[ string_index + 2 ] = (uint8_t) '0' + (uint8_t) ( nano_seconds % 10 );
817 			nano_seconds                   /= 10;
818 
819 			utf8_string[ string_index + 1 ] = (uint8_t) '0' + (uint8_t) ( nano_seconds % 10 );
820 			nano_seconds                   /= 10;
821 
822 			utf8_string[ string_index ] = (uint8_t) '0' + (uint8_t) ( nano_seconds % 10 );
823 
824 			string_index += 3;
825 		}
826 	}
827 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIMEZONE_INDICATOR ) != 0 )
828 	{
829 		if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_CTIME )
830 		{
831 			if( ( string_index + 4 ) > utf8_string_size )
832 			{
833 				libcerror_error_set(
834 				 error,
835 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
836 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
837 				 "%s: UTF-8 string is too small.",
838 				 function );
839 
840 				return( -1 );
841 			}
842 			utf8_string[ string_index++ ] = (uint8_t) ' ';
843 			utf8_string[ string_index++ ] = (uint8_t) 'U';
844 			utf8_string[ string_index++ ] = (uint8_t) 'T';
845 			utf8_string[ string_index++ ] = (uint8_t) 'C';
846 		}
847 		else if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 )
848 		{
849 			if( ( string_index + 1 ) > utf8_string_size )
850 			{
851 				libcerror_error_set(
852 				 error,
853 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
854 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
855 				 "%s: UTF-8 string is too small.",
856 				 function );
857 
858 				return( -1 );
859 			}
860 			utf8_string[ string_index++ ] = (uint8_t) 'Z';
861 		}
862 	}
863 	if( ( string_index + 1 ) > utf8_string_size )
864 	{
865 		libcerror_error_set(
866 		 error,
867 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
868 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
869 		 "%s: UTF-8 string is too small.",
870 		 function );
871 
872 		return( -1 );
873 	}
874 	utf8_string[ string_index++ ] = 0;
875 
876 	*utf8_string_index = string_index;
877 
878 	return( 1 );
879 }
880 
881 /* Converts the date and time values into an UTF-16 string
882  * The string size should include the end of string character
883  * Returns 1 if successful, 0 if the date and time values are not valid or -1 on error
884  */
libfdatetime_date_time_values_copy_to_utf16_string_with_index(libfdatetime_date_time_values_t * date_time_values,uint16_t * utf16_string,size_t utf16_string_size,size_t * utf16_string_index,uint32_t string_format_flags,libcerror_error_t ** error)885 int libfdatetime_date_time_values_copy_to_utf16_string_with_index(
886      libfdatetime_date_time_values_t *date_time_values,
887      uint16_t *utf16_string,
888      size_t utf16_string_size,
889      size_t *utf16_string_index,
890      uint32_t string_format_flags,
891      libcerror_error_t **error )
892 {
893 	char *month_string          = NULL;
894 	static char *function       = "libfdatetime_date_time_values_copy_to_utf16_string_with_index";
895 	size_t string_index         = 0;
896 	uint32_t string_format_type = 0;
897 	uint32_t supported_flags    = 0;
898 	uint16_t micro_seconds      = 0;
899 	uint16_t milli_seconds      = 0;
900 	uint16_t nano_seconds       = 0;
901 	uint16_t year_value         = 0;
902 	uint8_t days_in_month       = 0;
903 
904 	if( date_time_values == NULL )
905 	{
906 		libcerror_error_set(
907 		 error,
908 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
909 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
910 		 "%s: invalid date time values.",
911 		 function );
912 
913 		return( -1 );
914 	}
915 	if( utf16_string == NULL )
916 	{
917 		libcerror_error_set(
918 		 error,
919 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
920 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
921 		 "%s: invalid UTF-16 string.",
922 		 function );
923 
924 		return( -1 );
925 	}
926 	if( utf16_string_size > (size_t) SSIZE_MAX )
927 	{
928 		libcerror_error_set(
929 		 error,
930 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
931 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
932 		 "%s: invalid UTF-16 string size value exceeds maximum.",
933 		 function );
934 
935 		return( -1 );
936 	}
937 	if( utf16_string_index == NULL )
938 	{
939 		libcerror_error_set(
940 		 error,
941 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
942 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
943 		 "%s: invalid UTF-16 string index.",
944 		 function );
945 
946 		return( -1 );
947 	}
948 	supported_flags = 0x000000ffUL
949 	                | LIBFDATETIME_STRING_FORMAT_FLAG_DATE
950 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME
951 	                | LIBFDATETIME_STRING_FORMAT_FLAG_DURATION
952 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MILLI_SECONDS
953 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS
954 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS
955 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIMEZONE_INDICATOR;
956 
957 	if( ( string_format_flags & supported_flags ) == 0 )
958 	{
959 		libcerror_error_set(
960 		 error,
961 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
962 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
963 		 "%s: unsupported string format flags: 0x%08" PRIx32 ".",
964 		 function,
965 		 string_format_flags );
966 
967 		return( -1 );
968 	}
969 	string_format_type = string_format_flags & 0x000000ffUL;
970 
971 	if( ( string_format_type != LIBFDATETIME_STRING_FORMAT_TYPE_CTIME )
972 	 && ( string_format_type != LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 ) )
973 	{
974 		libcerror_error_set(
975 		 error,
976 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
977 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
978 		 "%s: unsupported string format type: 0x%08" PRIx32 ".",
979 		 function,
980 		 string_format_type );
981 
982 		return( -1 );
983 	}
984 	string_index = *utf16_string_index;
985 
986 	/* Validate the date and time if necessary
987 	 */
988 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_DATE ) != 0 )
989 	{
990 		if( date_time_values->year > 9999 )
991 		{
992 			return( 0 );
993 		}
994 		if( ( date_time_values->month == 0 )
995 		 || ( date_time_values->month > 12 ) )
996 		{
997 			return( 0 );
998 		}
999 		switch( date_time_values->month )
1000 		{
1001 			case 1:
1002 			case 3:
1003 			case 5:
1004 			case 7:
1005 			case 8:
1006 			case 10:
1007 			case 12:
1008 				days_in_month = 31;
1009 				break;
1010 			case 4:
1011 			case 6:
1012 			case 9:
1013 			case 11:
1014 				days_in_month = 30;
1015 				break;
1016 			case 2:
1017 				if( ( ( ( date_time_values->year % 4 ) == 0 )
1018 				  &&  ( ( date_time_values->year % 100 ) != 0 ) )
1019 				 || ( ( date_time_values->year % 400 ) == 0 ) )
1020 				{
1021 					days_in_month = 29;
1022 				}
1023 				else
1024 				{
1025 					days_in_month = 28;
1026 				}
1027 				break;
1028 		}
1029 		if( ( date_time_values->day == 0 )
1030 		 || ( date_time_values->day > days_in_month ) )
1031 		{
1032 			return( 0 );
1033 		}
1034 	}
1035 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME ) != 0 )
1036 	{
1037 		if( date_time_values->hours > 23 )
1038 		{
1039 			return( 0 );
1040 		}
1041 		if( date_time_values->minutes > 59 )
1042 		{
1043 			return( 0 );
1044 		}
1045 		if( date_time_values->seconds > 59 )
1046 		{
1047 			return( 0 );
1048 		}
1049 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MILLI_SECONDS ) != 0 )
1050 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
1051 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
1052 		{
1053 			if( date_time_values->milli_seconds > 999 )
1054 			{
1055 				return( 0 );
1056 			}
1057 		}
1058 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
1059 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
1060 		{
1061 			if( date_time_values->micro_seconds > 999 )
1062 			{
1063 				return( 0 );
1064 			}
1065 		}
1066 		if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 )
1067 		{
1068 			if( date_time_values->nano_seconds > 999 )
1069 			{
1070 				return( 0 );
1071 			}
1072 		}
1073 	}
1074 	/* Create the date and time string
1075 	 */
1076 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_DATE ) != 0 )
1077 	{
1078 		if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_CTIME )
1079 		{
1080 			switch( date_time_values->month )
1081 			{
1082 				case 1:
1083 					month_string = "Jan";
1084 					break;
1085 				case 2:
1086 					month_string = "Feb";
1087 					break;
1088 				case 3:
1089 					month_string = "Mar";
1090 					break;
1091 				case 4:
1092 					month_string = "Apr";
1093 					break;
1094 				case 5:
1095 					month_string = "May";
1096 					break;
1097 				case 6:
1098 					month_string = "Jun";
1099 					break;
1100 				case 7:
1101 					month_string = "Jul";
1102 					break;
1103 				case 8:
1104 					month_string = "Aug";
1105 					break;
1106 				case 9:
1107 					month_string = "Sep";
1108 					break;
1109 				case 10:
1110 					month_string = "Oct";
1111 					break;
1112 				case 11:
1113 					month_string = "Nov";
1114 					break;
1115 				case 12:
1116 					month_string = "Dec";
1117 					break;
1118 			}
1119 			if( ( string_index + 12 ) > utf16_string_size )
1120 			{
1121 				libcerror_error_set(
1122 				 error,
1123 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1124 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1125 				 "%s: UTF-16 string is too small.",
1126 				 function );
1127 
1128 				return( -1 );
1129 			}
1130 			if( month_string == NULL )
1131 			{
1132 				libcerror_error_set(
1133 				 error,
1134 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1135 				 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1136 				 "%s: missing month string.",
1137 				 function );
1138 
1139 				return( -1 );
1140 			}
1141 			/* Format: mmm dd, yyyy */
1142 			utf16_string[ string_index++ ] = (uint16_t) month_string[ 0 ];
1143 			utf16_string[ string_index++ ] = (uint16_t) month_string[ 1 ];
1144 			utf16_string[ string_index++ ] = (uint16_t) month_string[ 2 ];
1145 
1146 			utf16_string[ string_index++ ] = (uint16_t) ' ';
1147 
1148 			utf16_string[ string_index++ ] = (uint16_t) '0' + ( date_time_values->day / 10 );
1149 			utf16_string[ string_index++ ] = (uint16_t) '0' + ( date_time_values->day % 10 );
1150 
1151 			utf16_string[ string_index++ ] = (uint16_t) ',';
1152 			utf16_string[ string_index++ ] = (uint16_t) ' ';
1153 
1154 			year_value                     = date_time_values->year;
1155 			utf16_string[ string_index++ ] = (uint16_t) '0' + ( year_value / 1000 );
1156 			year_value                    %= 1000;
1157 			utf16_string[ string_index++ ] = (uint16_t) '0' + ( year_value / 100 );
1158 			year_value                    %= 100;
1159 			utf16_string[ string_index++ ] = (uint16_t) '0' + ( year_value / 10 );
1160 			year_value                    %= 10;
1161 			utf16_string[ string_index++ ] = (uint16_t) '0' + year_value;
1162 
1163 			if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME ) != 0 )
1164 			{
1165 				if( ( string_index + 1 ) > utf16_string_size )
1166 				{
1167 					libcerror_error_set(
1168 					 error,
1169 					 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1170 					 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1171 					 "%s: UTF-16 string is too small.",
1172 					 function );
1173 
1174 					return( -1 );
1175 				}
1176 				utf16_string[ string_index++ ] = (uint16_t) ' ';
1177 			}
1178 		}
1179 		else if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 )
1180 		{
1181 			if( ( string_index + 10 ) > utf16_string_size )
1182 			{
1183 				libcerror_error_set(
1184 				 error,
1185 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1186 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1187 				 "%s: UTF-16 string is too small.",
1188 				 function );
1189 
1190 				return( -1 );
1191 			}
1192 			/* Format: yyyy-mm-dd */
1193 			year_value                     = date_time_values->year;
1194 			utf16_string[ string_index++ ] = (uint16_t) '0' + ( year_value / 1000 );
1195 			year_value                    %= 1000;
1196 			utf16_string[ string_index++ ] = (uint16_t) '0' + ( year_value / 100 );
1197 			year_value                    %= 100;
1198 			utf16_string[ string_index++ ] = (uint16_t) '0' + ( year_value / 10 );
1199 			year_value                    %= 10;
1200 			utf16_string[ string_index++ ] = (uint16_t) '0' + year_value;
1201 
1202 			utf16_string[ string_index++ ] = (uint16_t) '-';
1203 
1204 			utf16_string[ string_index++ ] = (uint16_t) '0' + ( date_time_values->month / 10 );
1205 			utf16_string[ string_index++ ] = (uint16_t) '0' + ( date_time_values->month % 10 );
1206 
1207 			utf16_string[ string_index++ ] = (uint16_t) '-';
1208 
1209 			utf16_string[ string_index++ ] = (uint16_t) '0' + ( date_time_values->day / 10 );
1210 			utf16_string[ string_index++ ] = (uint16_t) '0' + ( date_time_values->day % 10 );
1211 
1212 			if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME ) != 0 )
1213 			{
1214 				if( ( string_index + 1 ) > utf16_string_size )
1215 				{
1216 					libcerror_error_set(
1217 					 error,
1218 					 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1219 					 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1220 					 "%s: UTF-16 string is too small.",
1221 					 function );
1222 
1223 					return( -1 );
1224 				}
1225 				utf16_string[ string_index++ ] = (uint16_t) 'T';
1226 			}
1227 		}
1228 	}
1229 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME ) != 0 )
1230 	{
1231 		if( ( string_index + 8 ) > utf16_string_size )
1232 		{
1233 			libcerror_error_set(
1234 			 error,
1235 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1236 			 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1237 			 "%s: UTF-16 string is too small.",
1238 			 function );
1239 
1240 			return( -1 );
1241 		}
1242 		/* Format: HH:MM:SS */
1243 		utf16_string[ string_index++ ] = (uint16_t) '0' + ( date_time_values->hours / 10 );
1244 		utf16_string[ string_index++ ] = (uint16_t) '0' + ( date_time_values->hours % 10 );
1245 
1246 		utf16_string[ string_index++ ] = (uint16_t) ':';
1247 
1248 		utf16_string[ string_index++ ] = (uint16_t) '0' + ( date_time_values->minutes / 10 );
1249 		utf16_string[ string_index++ ] = (uint16_t) '0' + ( date_time_values->minutes % 10 );
1250 
1251 		utf16_string[ string_index++ ] = (uint16_t) ':';
1252 
1253 		utf16_string[ string_index++ ] = (uint16_t) '0' + ( date_time_values->seconds / 10 );
1254 		utf16_string[ string_index++ ] = (uint16_t) '0' + ( date_time_values->seconds % 10 );
1255 
1256 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MILLI_SECONDS ) != 0 )
1257 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
1258 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
1259 		{
1260 			if( ( string_index + 4 ) > utf16_string_size )
1261 			{
1262 				libcerror_error_set(
1263 				 error,
1264 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1265 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1266 				 "%s: UTF-16 string is too small.",
1267 				 function );
1268 
1269 				return( -1 );
1270 			}
1271 			/* Format: .### */
1272 			utf16_string[ string_index++ ] = (uint16_t) '.';
1273 
1274 			milli_seconds = date_time_values->milli_seconds;
1275 
1276 			utf16_string[ string_index + 2 ] = (uint16_t) '0' + (uint16_t) ( milli_seconds % 10 );
1277 			milli_seconds                   /= 10;
1278 
1279 			utf16_string[ string_index + 1 ] = (uint16_t) '0' + (uint16_t) ( milli_seconds % 10 );
1280 			milli_seconds                   /= 10;
1281 
1282 			utf16_string[ string_index ] = (uint16_t) '0' + (uint16_t) ( milli_seconds % 10 );
1283 
1284 			string_index += 3;
1285 		}
1286 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
1287 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
1288 		{
1289 			if( ( string_index + 3 ) > utf16_string_size )
1290 			{
1291 				libcerror_error_set(
1292 				 error,
1293 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1294 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1295 				 "%s: UTF-16 string is too small.",
1296 				 function );
1297 
1298 				return( -1 );
1299 			}
1300 			/* Format: ### */
1301 			micro_seconds = date_time_values->micro_seconds;
1302 
1303 			utf16_string[ string_index + 2 ] = (uint16_t) '0' + (uint16_t) ( micro_seconds % 10 );
1304 			micro_seconds                   /= 10;
1305 
1306 			utf16_string[ string_index + 1 ] = (uint16_t) '0' + (uint16_t) ( micro_seconds % 10 );
1307 			micro_seconds                   /= 10;
1308 
1309 			utf16_string[ string_index ] = (uint16_t) '0' + (uint16_t) ( micro_seconds % 10 );
1310 
1311 			string_index += 3;
1312 		}
1313 		if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 )
1314 		{
1315 			if( ( string_index + 3 ) > utf16_string_size )
1316 			{
1317 				libcerror_error_set(
1318 				 error,
1319 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1320 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1321 				 "%s: UTF-16 string is too small.",
1322 				 function );
1323 
1324 				return( -1 );
1325 			}
1326 			/* Format: ### */
1327 			nano_seconds = date_time_values->nano_seconds;
1328 
1329 			utf16_string[ string_index + 2 ] = (uint16_t) '0' + (uint16_t) ( nano_seconds % 10 );
1330 			nano_seconds                    /= 10;
1331 
1332 			utf16_string[ string_index + 1 ] = (uint16_t) '0' + (uint16_t) ( nano_seconds % 10 );
1333 			nano_seconds                    /= 10;
1334 
1335 			utf16_string[ string_index ] = (uint16_t) '0' + (uint16_t) ( nano_seconds % 10 );
1336 
1337 			string_index += 3;
1338 		}
1339 	}
1340 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIMEZONE_INDICATOR ) != 0 )
1341 	{
1342 		if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_CTIME )
1343 		{
1344 			if( ( string_index + 4 ) > utf16_string_size )
1345 			{
1346 				libcerror_error_set(
1347 				 error,
1348 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1349 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1350 				 "%s: UTF-16 string is too small.",
1351 				 function );
1352 
1353 				return( -1 );
1354 			}
1355 			utf16_string[ string_index++ ] = (uint16_t) ' ';
1356 			utf16_string[ string_index++ ] = (uint16_t) 'U';
1357 			utf16_string[ string_index++ ] = (uint16_t) 'T';
1358 			utf16_string[ string_index++ ] = (uint16_t) 'C';
1359 		}
1360 		else if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 )
1361 		{
1362 			if( ( string_index + 1 ) > utf16_string_size )
1363 			{
1364 				libcerror_error_set(
1365 				 error,
1366 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1367 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1368 				 "%s: UTF-16 string is too small.",
1369 				 function );
1370 
1371 				return( -1 );
1372 			}
1373 			utf16_string[ string_index++ ] = (uint16_t) 'Z';
1374 		}
1375 	}
1376 	if( ( string_index + 1 ) > utf16_string_size )
1377 	{
1378 		libcerror_error_set(
1379 		 error,
1380 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1381 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1382 		 "%s: UTF-16 string is too small.",
1383 		 function );
1384 
1385 		return( -1 );
1386 	}
1387 	utf16_string[ string_index++ ] = 0;
1388 
1389 	*utf16_string_index = string_index;
1390 
1391 	return( 1 );
1392 }
1393 
1394 /* Converts the date and time values into an UTF-32 string
1395  * The string size should include the end of string character
1396  * Returns 1 if successful, 0 if the date and time values are not valid or -1 on error
1397  */
libfdatetime_date_time_values_copy_to_utf32_string_with_index(libfdatetime_date_time_values_t * date_time_values,uint32_t * utf32_string,size_t utf32_string_size,size_t * utf32_string_index,uint32_t string_format_flags,libcerror_error_t ** error)1398 int libfdatetime_date_time_values_copy_to_utf32_string_with_index(
1399      libfdatetime_date_time_values_t *date_time_values,
1400      uint32_t *utf32_string,
1401      size_t utf32_string_size,
1402      size_t *utf32_string_index,
1403      uint32_t string_format_flags,
1404      libcerror_error_t **error )
1405 {
1406 	char *month_string          = NULL;
1407 	static char *function       = "libfdatetime_date_time_values_copy_to_utf32_string_with_index";
1408 	size_t string_index         = 0;
1409 	uint32_t string_format_type = 0;
1410 	uint32_t supported_flags    = 0;
1411 	uint16_t micro_seconds      = 0;
1412 	uint16_t milli_seconds      = 0;
1413 	uint16_t nano_seconds       = 0;
1414 	uint16_t year_value         = 0;
1415 	uint8_t days_in_month       = 0;
1416 
1417 	if( date_time_values == NULL )
1418 	{
1419 		libcerror_error_set(
1420 		 error,
1421 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1422 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1423 		 "%s: invalid date time values.",
1424 		 function );
1425 
1426 		return( -1 );
1427 	}
1428 	if( utf32_string == NULL )
1429 	{
1430 		libcerror_error_set(
1431 		 error,
1432 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1433 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1434 		 "%s: invalid UTF-32 string.",
1435 		 function );
1436 
1437 		return( -1 );
1438 	}
1439 	if( utf32_string_size > (size_t) SSIZE_MAX )
1440 	{
1441 		libcerror_error_set(
1442 		 error,
1443 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1444 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1445 		 "%s: invalid UTF-32 string size value exceeds maximum.",
1446 		 function );
1447 
1448 		return( -1 );
1449 	}
1450 	if( utf32_string_index == NULL )
1451 	{
1452 		libcerror_error_set(
1453 		 error,
1454 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1455 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1456 		 "%s: invalid UTF-32 string index.",
1457 		 function );
1458 
1459 		return( -1 );
1460 	}
1461 	supported_flags = 0x000000ffUL
1462 	                | LIBFDATETIME_STRING_FORMAT_FLAG_DATE
1463 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME
1464 	                | LIBFDATETIME_STRING_FORMAT_FLAG_DURATION
1465 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MILLI_SECONDS
1466 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS
1467 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS
1468 	                | LIBFDATETIME_STRING_FORMAT_FLAG_TIMEZONE_INDICATOR;
1469 
1470 	if( ( string_format_flags & supported_flags ) == 0 )
1471 	{
1472 		libcerror_error_set(
1473 		 error,
1474 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1475 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1476 		 "%s: unsupported string format flags: 0x%08" PRIx32 ".",
1477 		 function,
1478 		 string_format_flags );
1479 
1480 		return( -1 );
1481 	}
1482 	string_format_type = string_format_flags & 0x000000ffUL;
1483 
1484 	if( ( string_format_type != LIBFDATETIME_STRING_FORMAT_TYPE_CTIME )
1485 	 && ( string_format_type != LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 ) )
1486 	{
1487 		libcerror_error_set(
1488 		 error,
1489 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1490 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1491 		 "%s: unsupported string format type: 0x%08" PRIx32 ".",
1492 		 function,
1493 		 string_format_type );
1494 
1495 		return( -1 );
1496 	}
1497 	string_index = *utf32_string_index;
1498 
1499 	/* Validate the date and time if necessary
1500 	 */
1501 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_DATE ) != 0 )
1502 	{
1503 		if( date_time_values->year > 9999 )
1504 		{
1505 			return( 0 );
1506 		}
1507 		if( ( date_time_values->month == 0 )
1508 		 || ( date_time_values->month > 12 ) )
1509 		{
1510 			return( 0 );
1511 		}
1512 		switch( date_time_values->month )
1513 		{
1514 			case 1:
1515 			case 3:
1516 			case 5:
1517 			case 7:
1518 			case 8:
1519 			case 10:
1520 			case 12:
1521 				days_in_month = 31;
1522 				break;
1523 			case 4:
1524 			case 6:
1525 			case 9:
1526 			case 11:
1527 				days_in_month = 30;
1528 				break;
1529 			case 2:
1530 				if( ( ( ( date_time_values->year % 4 ) == 0 )
1531 				  &&  ( ( date_time_values->year % 100 ) != 0 ) )
1532 				 || ( ( date_time_values->year % 400 ) == 0 ) )
1533 				{
1534 					days_in_month = 29;
1535 				}
1536 				else
1537 				{
1538 					days_in_month = 28;
1539 				}
1540 				break;
1541 		}
1542 		if( ( date_time_values->day == 0 )
1543 		 || ( date_time_values->day > days_in_month ) )
1544 		{
1545 			return( 0 );
1546 		}
1547 	}
1548 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME ) != 0 )
1549 	{
1550 		if( date_time_values->hours > 23 )
1551 		{
1552 			return( 0 );
1553 		}
1554 		if( date_time_values->minutes > 59 )
1555 		{
1556 			return( 0 );
1557 		}
1558 		if( date_time_values->seconds > 59 )
1559 		{
1560 			return( 0 );
1561 		}
1562 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MILLI_SECONDS ) != 0 )
1563 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
1564 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
1565 		{
1566 			if( date_time_values->milli_seconds > 999 )
1567 			{
1568 				return( 0 );
1569 			}
1570 		}
1571 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
1572 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
1573 		{
1574 			if( date_time_values->micro_seconds > 999 )
1575 			{
1576 				return( 0 );
1577 			}
1578 		}
1579 		if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 )
1580 		{
1581 			if( date_time_values->nano_seconds > 999 )
1582 			{
1583 				return( 0 );
1584 			}
1585 		}
1586 	}
1587 	/* Create the date and time string
1588 	 */
1589 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_DATE ) != 0 )
1590 	{
1591 		if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_CTIME )
1592 		{
1593 			switch( date_time_values->month )
1594 			{
1595 				case 1:
1596 					month_string = "Jan";
1597 					break;
1598 				case 2:
1599 					month_string = "Feb";
1600 					break;
1601 				case 3:
1602 					month_string = "Mar";
1603 					break;
1604 				case 4:
1605 					month_string = "Apr";
1606 					break;
1607 				case 5:
1608 					month_string = "May";
1609 					break;
1610 				case 6:
1611 					month_string = "Jun";
1612 					break;
1613 				case 7:
1614 					month_string = "Jul";
1615 					break;
1616 				case 8:
1617 					month_string = "Aug";
1618 					break;
1619 				case 9:
1620 					month_string = "Sep";
1621 					break;
1622 				case 10:
1623 					month_string = "Oct";
1624 					break;
1625 				case 11:
1626 					month_string = "Nov";
1627 					break;
1628 				case 12:
1629 					month_string = "Dec";
1630 					break;
1631 			}
1632 			if( ( string_index + 12 ) > utf32_string_size )
1633 			{
1634 				libcerror_error_set(
1635 				 error,
1636 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1637 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1638 				 "%s: UTF-32 string is too small.",
1639 				 function );
1640 
1641 				return( -1 );
1642 			}
1643 			if( month_string == NULL )
1644 			{
1645 				libcerror_error_set(
1646 				 error,
1647 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1648 				 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1649 				 "%s: missing month string.",
1650 				 function );
1651 
1652 				return( -1 );
1653 			}
1654 			/* Format: mmm dd, yyyy */
1655 			utf32_string[ string_index++ ] = (uint32_t) month_string[ 0 ];
1656 			utf32_string[ string_index++ ] = (uint32_t) month_string[ 1 ];
1657 			utf32_string[ string_index++ ] = (uint32_t) month_string[ 2 ];
1658 
1659 			utf32_string[ string_index++ ] = (uint32_t) ' ';
1660 
1661 			utf32_string[ string_index++ ] = (uint32_t) '0' + ( date_time_values->day / 10 );
1662 			utf32_string[ string_index++ ] = (uint32_t) '0' + ( date_time_values->day % 10 );
1663 
1664 			utf32_string[ string_index++ ] = (uint32_t) ',';
1665 			utf32_string[ string_index++ ] = (uint32_t) ' ';
1666 
1667 			year_value                     = date_time_values->year;
1668 			utf32_string[ string_index++ ] = (uint32_t) '0' + ( year_value / 1000 );
1669 			year_value                    %= 1000;
1670 			utf32_string[ string_index++ ] = (uint32_t) '0' + ( year_value / 100 );
1671 			year_value                    %= 100;
1672 			utf32_string[ string_index++ ] = (uint32_t) '0' + ( year_value / 10 );
1673 			year_value                    %= 10;
1674 			utf32_string[ string_index++ ] = (uint32_t) '0' + year_value;
1675 
1676 			if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME ) != 0 )
1677 			{
1678 				if( ( string_index + 1 ) > utf32_string_size )
1679 				{
1680 					libcerror_error_set(
1681 					 error,
1682 					 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1683 					 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1684 					 "%s: UTF-32 string is too small.",
1685 					 function );
1686 
1687 					return( -1 );
1688 				}
1689 				utf32_string[ string_index++ ] = (uint32_t) ' ';
1690 			}
1691 		}
1692 		else if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 )
1693 		{
1694 			if( ( string_index + 10 ) > utf32_string_size )
1695 			{
1696 				libcerror_error_set(
1697 				 error,
1698 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1699 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1700 				 "%s: UTF-32 string is too small.",
1701 				 function );
1702 
1703 				return( -1 );
1704 			}
1705 			/* Format: yyyy-mm-dd */
1706 			year_value                     = date_time_values->year;
1707 			utf32_string[ string_index++ ] = (uint32_t) '0' + ( year_value / 1000 );
1708 			year_value                    %= 1000;
1709 			utf32_string[ string_index++ ] = (uint32_t) '0' + ( year_value / 100 );
1710 			year_value                    %= 100;
1711 			utf32_string[ string_index++ ] = (uint32_t) '0' + ( year_value / 10 );
1712 			year_value                    %= 10;
1713 			utf32_string[ string_index++ ] = (uint32_t) '0' + year_value;
1714 
1715 			utf32_string[ string_index++ ] = (uint32_t) '-';
1716 
1717 			utf32_string[ string_index++ ] = (uint32_t) '0' + ( date_time_values->month / 10 );
1718 			utf32_string[ string_index++ ] = (uint32_t) '0' + ( date_time_values->month % 10 );
1719 
1720 			utf32_string[ string_index++ ] = (uint32_t) '-';
1721 
1722 			utf32_string[ string_index++ ] = (uint32_t) '0' + ( date_time_values->day / 10 );
1723 			utf32_string[ string_index++ ] = (uint32_t) '0' + ( date_time_values->day % 10 );
1724 
1725 			if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME ) != 0 )
1726 			{
1727 				if( ( string_index + 1 ) > utf32_string_size )
1728 				{
1729 					libcerror_error_set(
1730 					 error,
1731 					 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1732 					 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1733 					 "%s: UTF-32 string is too small.",
1734 					 function );
1735 
1736 					return( -1 );
1737 				}
1738 				utf32_string[ string_index++ ] = (uint32_t) 'T';
1739 			}
1740 		}
1741 	}
1742 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME ) != 0 )
1743 	{
1744 		if( ( string_index + 8 ) > utf32_string_size )
1745 		{
1746 			libcerror_error_set(
1747 			 error,
1748 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1749 			 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1750 			 "%s: UTF-32 string is too small.",
1751 			 function );
1752 
1753 			return( -1 );
1754 		}
1755 		/* Format: HH:MM:SS */
1756 		utf32_string[ string_index++ ] = (uint32_t) '0' + ( date_time_values->hours / 10 );
1757 		utf32_string[ string_index++ ] = (uint32_t) '0' + ( date_time_values->hours % 10 );
1758 
1759 		utf32_string[ string_index++ ] = (uint32_t) ':';
1760 
1761 		utf32_string[ string_index++ ] = (uint32_t) '0' + ( date_time_values->minutes / 10 );
1762 		utf32_string[ string_index++ ] = (uint32_t) '0' + ( date_time_values->minutes % 10 );
1763 
1764 		utf32_string[ string_index++ ] = (uint32_t) ':';
1765 
1766 		utf32_string[ string_index++ ] = (uint32_t) '0' + ( date_time_values->seconds / 10 );
1767 		utf32_string[ string_index++ ] = (uint32_t) '0' + ( date_time_values->seconds % 10 );
1768 
1769 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MILLI_SECONDS ) != 0 )
1770 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
1771 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
1772 		{
1773 			if( ( string_index + 4 ) > utf32_string_size )
1774 			{
1775 				libcerror_error_set(
1776 				 error,
1777 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1778 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1779 				 "%s: UTF-32 string is too small.",
1780 				 function );
1781 
1782 				return( -1 );
1783 			}
1784 			/* Format: .### */
1785 			utf32_string[ string_index++ ] = (uint32_t) '.';
1786 
1787 			milli_seconds = date_time_values->milli_seconds;
1788 
1789 			utf32_string[ string_index + 2 ] = (uint32_t) '0' + (uint32_t) ( milli_seconds % 10 );
1790 			milli_seconds                   /= 10;
1791 
1792 			utf32_string[ string_index + 1 ] = (uint32_t) '0' + (uint32_t) ( milli_seconds % 10 );
1793 			milli_seconds                   /= 10;
1794 
1795 			utf32_string[ string_index ] = (uint32_t) '0' + (uint32_t) ( milli_seconds % 10 );
1796 
1797 			string_index += 3;
1798 		}
1799 		if( ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_MICRO_SECONDS ) != 0 )
1800 		 || ( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 ) )
1801 		{
1802 			if( ( string_index + 3 ) > utf32_string_size )
1803 			{
1804 				libcerror_error_set(
1805 				 error,
1806 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1807 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1808 				 "%s: UTF-32 string is too small.",
1809 				 function );
1810 
1811 				return( -1 );
1812 			}
1813 			/* Format: ### */
1814 			micro_seconds = date_time_values->micro_seconds;
1815 
1816 			utf32_string[ string_index + 2 ] = (uint32_t) '0' + (uint32_t) ( micro_seconds % 10 );
1817 			micro_seconds                   /= 10;
1818 
1819 			utf32_string[ string_index + 1 ] = (uint32_t) '0' + (uint32_t) ( micro_seconds % 10 );
1820 			micro_seconds                   /= 10;
1821 
1822 			utf32_string[ string_index ] = (uint32_t) '0' + (uint32_t) ( micro_seconds % 10 );
1823 
1824 			string_index += 3;
1825 		}
1826 		if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIME_NANO_SECONDS ) != 0 )
1827 		{
1828 			if( ( string_index + 3 ) > utf32_string_size )
1829 			{
1830 				libcerror_error_set(
1831 				 error,
1832 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1833 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1834 				 "%s: UTF-32 string is too small.",
1835 				 function );
1836 
1837 				return( -1 );
1838 			}
1839 			/* Format: ### */
1840 			nano_seconds = date_time_values->nano_seconds;
1841 
1842 			utf32_string[ string_index + 2 ] = (uint32_t) '0' + (uint32_t) ( nano_seconds % 10 );
1843 			nano_seconds                    /= 10;
1844 
1845 			utf32_string[ string_index + 1 ] = (uint32_t) '0' + (uint32_t) ( nano_seconds % 10 );
1846 			nano_seconds                    /= 10;
1847 
1848 			utf32_string[ string_index ] = (uint32_t) '0' + (uint32_t) ( nano_seconds % 10 );
1849 
1850 			string_index += 3;
1851 		}
1852 	}
1853 	if( ( string_format_flags & LIBFDATETIME_STRING_FORMAT_FLAG_TIMEZONE_INDICATOR ) != 0 )
1854 	{
1855 		if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_CTIME )
1856 		{
1857 			if( ( string_index + 4 ) > utf32_string_size )
1858 			{
1859 				libcerror_error_set(
1860 				 error,
1861 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1862 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1863 				 "%s: UTF-32 string is too small.",
1864 				 function );
1865 
1866 				return( -1 );
1867 			}
1868 			utf32_string[ string_index++ ] = (uint32_t) ' ';
1869 			utf32_string[ string_index++ ] = (uint32_t) 'U';
1870 			utf32_string[ string_index++ ] = (uint32_t) 'T';
1871 			utf32_string[ string_index++ ] = (uint32_t) 'C';
1872 		}
1873 		else if( string_format_type == LIBFDATETIME_STRING_FORMAT_TYPE_ISO8601 )
1874 		{
1875 			if( ( string_index + 1 ) > utf32_string_size )
1876 			{
1877 				libcerror_error_set(
1878 				 error,
1879 				 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1880 				 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1881 				 "%s: UTF-32 string is too small.",
1882 				 function );
1883 
1884 				return( -1 );
1885 			}
1886 			utf32_string[ string_index++ ] = (uint32_t) 'Z';
1887 		}
1888 	}
1889 	if( ( string_index + 1 ) > utf32_string_size )
1890 	{
1891 		libcerror_error_set(
1892 		 error,
1893 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1894 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1895 		 "%s: UTF-32 string is too small.",
1896 		 function );
1897 
1898 		return( -1 );
1899 	}
1900 	utf32_string[ string_index++ ] = 0;
1901 
1902 	*utf32_string_index = string_index;
1903 
1904 	return( 1 );
1905 }
1906 
1907