1 /*
2  * FAT date and time 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 <byte_stream.h>
24 #include <memory.h>
25 #include <types.h>
26 
27 #include "libfdatetime_definitions.h"
28 #include "libfdatetime_date_time_values.h"
29 #include "libfdatetime_fat_date_time.h"
30 #include "libfdatetime_libcerror.h"
31 #include "libfdatetime_types.h"
32 
33 /* Creates a FAT date and time
34  * Make sure the value fat_date_time is referencing, is set to NULL
35  * Returns 1 if successful or -1 on error
36  */
libfdatetime_fat_date_time_initialize(libfdatetime_fat_date_time_t ** fat_date_time,libcerror_error_t ** error)37 int libfdatetime_fat_date_time_initialize(
38      libfdatetime_fat_date_time_t **fat_date_time,
39      libcerror_error_t **error )
40 {
41 	libfdatetime_internal_fat_date_time_t *internal_fat_date_time = NULL;
42 	static char *function                                         = "libfdatetime_fat_date_time_initialize";
43 
44 	if( fat_date_time == NULL )
45 	{
46 		libcerror_error_set(
47 		 error,
48 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
49 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
50 		 "%s: invalid FAT date time.",
51 		 function );
52 
53 		return( -1 );
54 	}
55 	if( *fat_date_time != NULL )
56 	{
57 		libcerror_error_set(
58 		 error,
59 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
60 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
61 		 "%s: invalid FAT date time value already set.",
62 		 function );
63 
64 		return( -1 );
65 	}
66 	internal_fat_date_time = memory_allocate_structure(
67 	                          libfdatetime_internal_fat_date_time_t );
68 
69 	if( internal_fat_date_time == NULL )
70 	{
71 		libcerror_error_set(
72 		 error,
73 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
74 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
75 		 "%s: unable to create FAT date time.",
76 		 function );
77 
78 		goto on_error;
79 	}
80 	if( memory_set(
81 	     internal_fat_date_time,
82 	     0,
83 	     sizeof( libfdatetime_internal_fat_date_time_t ) ) == NULL )
84 	{
85 		libcerror_error_set(
86 		 error,
87 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
88 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
89 		 "%s: unable to clear FAT date time.",
90 		 function );
91 
92 		goto on_error;
93 	}
94 	*fat_date_time = (libfdatetime_fat_date_time_t *) internal_fat_date_time;
95 
96 	return( 1 );
97 
98 on_error:
99 	if( internal_fat_date_time != NULL )
100 	{
101 		memory_free(
102 		 internal_fat_date_time );
103 	}
104 	return( -1 );
105 }
106 
107 /* Frees a FAT date and time
108  * Returns 1 if successful or -1 on error
109  */
libfdatetime_fat_date_time_free(libfdatetime_fat_date_time_t ** fat_date_time,libcerror_error_t ** error)110 int libfdatetime_fat_date_time_free(
111      libfdatetime_fat_date_time_t **fat_date_time,
112      libcerror_error_t **error )
113 {
114 	libfdatetime_internal_fat_date_time_t *internal_fat_date_time = NULL;
115 	static char *function                                         = "libfdatetime_fat_date_time_free";
116 
117 	if( fat_date_time == NULL )
118 	{
119 		libcerror_error_set(
120 		 error,
121 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
122 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
123 		 "%s: invalid FAT date time.",
124 		 function );
125 
126 		return( -1 );
127 	}
128 	if( *fat_date_time != NULL )
129 	{
130 		internal_fat_date_time = (libfdatetime_internal_fat_date_time_t *) *fat_date_time;
131 		*fat_date_time         = NULL;
132 
133 		memory_free(
134 		 internal_fat_date_time );
135 	}
136 	return( 1 );
137 }
138 
139 /* Converts a byte stream into a FAT date and time
140  * Returns 1 if successful or -1 on error
141  */
libfdatetime_fat_date_time_copy_from_byte_stream(libfdatetime_fat_date_time_t * fat_date_time,const uint8_t * byte_stream,size_t byte_stream_size,int byte_order,libcerror_error_t ** error)142 int libfdatetime_fat_date_time_copy_from_byte_stream(
143      libfdatetime_fat_date_time_t *fat_date_time,
144      const uint8_t *byte_stream,
145      size_t byte_stream_size,
146      int byte_order,
147      libcerror_error_t **error )
148 {
149 	libfdatetime_internal_fat_date_time_t *internal_fat_date_time = NULL;
150 	static char *function                                         = "libfdatetime_fat_date_time_copy_from_byte_stream";
151 
152 	if( fat_date_time == NULL )
153 	{
154 		libcerror_error_set(
155 		 error,
156 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
157 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
158 		 "%s: invalid FAT date time.",
159 		 function );
160 
161 		return( -1 );
162 	}
163 	internal_fat_date_time = (libfdatetime_internal_fat_date_time_t *) fat_date_time;
164 
165 	if( byte_stream == NULL )
166 	{
167 		libcerror_error_set(
168 		 error,
169 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
170 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
171 		 "%s: invalid byte stream.",
172 		 function );
173 
174 		return( -1 );
175 	}
176 	if( byte_stream_size < 4 )
177 	{
178 		libcerror_error_set(
179 		 error,
180 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
181 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
182 		 "%s: byte stream too small.",
183 		 function );
184 
185 		return( -1 );
186 	}
187 	if( byte_stream_size > (size_t) SSIZE_MAX )
188 	{
189 		libcerror_error_set(
190 		 error,
191 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
192 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
193 		 "%s: byte stream size exceeds maximum.",
194 		 function );
195 
196 		return( -1 );
197 	}
198 	if( ( byte_order != LIBFDATETIME_ENDIAN_BIG )
199 	 && ( byte_order != LIBFDATETIME_ENDIAN_LITTLE ) )
200 	{
201 		libcerror_error_set(
202 		 error,
203 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
204 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
205 		 "%s: unsupported byte order.",
206 		 function );
207 
208 		return( -1 );
209 	}
210 	if( byte_order == LIBFDATETIME_ENDIAN_LITTLE )
211 	{
212 		byte_stream_copy_to_uint16_little_endian(
213 		 byte_stream,
214 		 internal_fat_date_time->date );
215 
216 		byte_stream += 2;
217 
218 		byte_stream_copy_to_uint16_little_endian(
219 		byte_stream,
220 		internal_fat_date_time->time );
221 	}
222 	else if( byte_order == LIBFDATETIME_ENDIAN_BIG )
223 	{
224 		byte_stream_copy_to_uint16_big_endian(
225 		 byte_stream,
226 		 internal_fat_date_time->date );
227 
228 		byte_stream += 2;
229 
230 		byte_stream_copy_to_uint16_big_endian(
231 		byte_stream,
232 		internal_fat_date_time->time );
233 	}
234 	return( 1 );
235 }
236 
237 /* Converts a 32-bit value into a FAT date and time
238  * Returns 1 if successful or -1 on error
239  */
libfdatetime_fat_date_time_copy_from_32bit(libfdatetime_fat_date_time_t * fat_date_time,uint32_t value_32bit,libcerror_error_t ** error)240 int libfdatetime_fat_date_time_copy_from_32bit(
241      libfdatetime_fat_date_time_t *fat_date_time,
242      uint32_t value_32bit,
243      libcerror_error_t **error )
244 {
245 	libfdatetime_internal_fat_date_time_t *internal_fat_date_time = NULL;
246 	static char *function                                         = "libfdatetime_fat_date_time_copy_from_32bit";
247 
248 	if( fat_date_time == NULL )
249 	{
250 		libcerror_error_set(
251 		 error,
252 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
253 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
254 		 "%s: invalid FAT date time.",
255 		 function );
256 
257 		return( -1 );
258 	}
259 	internal_fat_date_time = (libfdatetime_internal_fat_date_time_t *) fat_date_time;
260 
261 	internal_fat_date_time->date = (uint16_t) ( value_32bit & 0x0ffffL );
262 	internal_fat_date_time->time = (uint16_t) ( value_32bit >> 16 );
263 
264 	return( 1 );
265 }
266 
267 /* Converts a FAT date and time into a 32-bit value
268  * Returns 1 if successful or -1 on error
269  */
libfdatetime_fat_date_time_copy_to_32bit(libfdatetime_fat_date_time_t * fat_date_time,uint32_t * value_32bit,libcerror_error_t ** error)270 int libfdatetime_fat_date_time_copy_to_32bit(
271      libfdatetime_fat_date_time_t *fat_date_time,
272      uint32_t *value_32bit,
273      libcerror_error_t **error )
274 {
275 	libfdatetime_internal_fat_date_time_t *internal_fat_date_time = NULL;
276 	static char *function                                         = "libfdatetime_fat_date_time_copy_to_32bit";
277 
278 	if( fat_date_time == NULL )
279 	{
280 		libcerror_error_set(
281 		 error,
282 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
283 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
284 		 "%s: invalid FAT date time.",
285 		 function );
286 
287 		return( -1 );
288 	}
289 	internal_fat_date_time = (libfdatetime_internal_fat_date_time_t *) fat_date_time;
290 
291 	if( value_32bit == NULL )
292 	{
293 		libcerror_error_set(
294 		 error,
295 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
296 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
297 		 "%s: invalid 32-bit value.",
298 		 function );
299 
300 		return( -1 );
301 	}
302 	*value_32bit   = internal_fat_date_time->time;
303 	*value_32bit <<= 16;
304 	*value_32bit  |= internal_fat_date_time->date;
305 
306 	return( 1 );
307 }
308 
309 /* Converts a FAT date and time into date time values
310  * Returns 1 if successful or -1 on error
311  */
libfdatetime_internal_fat_date_time_copy_to_date_time_values(libfdatetime_internal_fat_date_time_t * internal_fat_date_time,libfdatetime_date_time_values_t * date_time_values,libcerror_error_t ** error)312 int libfdatetime_internal_fat_date_time_copy_to_date_time_values(
313      libfdatetime_internal_fat_date_time_t *internal_fat_date_time,
314      libfdatetime_date_time_values_t *date_time_values,
315      libcerror_error_t **error )
316 {
317 	static char *function = "libfdatetime_internal_fat_date_time_copy_to_date_time_values";
318 
319 	if( internal_fat_date_time == NULL )
320 	{
321 		libcerror_error_set(
322 		 error,
323 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
324 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
325 		 "%s: invalid FAT date time.",
326 		 function );
327 
328 		return( -1 );
329 	}
330 	if( date_time_values == NULL )
331 	{
332 		libcerror_error_set(
333 		 error,
334 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
335 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
336 		 "%s: invalid date time values.",
337 		 function );
338 
339 		return( -1 );
340 	}
341 	/* The year value is stored in bits 9 - 15 of the date (7 bits)
342 	 * A year value of 0 represents 1980
343 	 */
344 	date_time_values->year = (uint16_t) ( 1980 + ( ( internal_fat_date_time->date >> 9 ) & 0x7f ) );
345 
346 	/* The month value is stored in bits 5 - 8 of the date (4 bits)
347 	 * A month value of 1 represents January
348 	 */
349 	date_time_values->month = (uint8_t) ( ( internal_fat_date_time->date >> 5 ) & 0x0f );
350 
351 	/* The day value is stored in bits 0 - 4 of the date (5 bits)
352 	 */
353 	date_time_values->day = (uint8_t) ( internal_fat_date_time->date & 0x1f );
354 
355 	/* The hours value is stored in bits 11 - 15 of the time (5 bits)
356 	 */
357 	date_time_values->hours = (uint8_t) ( ( internal_fat_date_time->time >> 11 ) & 0x1f );
358 
359 	/* The minutes value is stored in bits 5 - 10 of the time (6 bits)
360 	 */
361 	date_time_values->minutes = (uint8_t) ( ( internal_fat_date_time->time >> 5 ) & 0x3f );
362 
363 	/* The seconds value is stored in bits 0 - 4 of the time (5 bits)
364 	 * The seconds are stored as 2 second intervals
365 	 */
366 	date_time_values->seconds = (uint8_t) ( internal_fat_date_time->time & 0x1f ) * 2;
367 
368         date_time_values->milli_seconds = 0;
369         date_time_values->micro_seconds = 0;
370         date_time_values->nano_seconds  = 0;
371 
372 	return( 1 );
373 }
374 
375 /* Deterimes the size of the string for the FAT date time
376  * The string size includes the end of string character
377  * Returns 1 if successful or -1 on error
378  */
libfdatetime_fat_date_time_get_string_size(libfdatetime_fat_date_time_t * fat_date_time,size_t * string_size,uint32_t string_format_flags,libcerror_error_t ** error)379 int libfdatetime_fat_date_time_get_string_size(
380      libfdatetime_fat_date_time_t *fat_date_time,
381      size_t *string_size,
382      uint32_t string_format_flags,
383      libcerror_error_t **error )
384 {
385 	libfdatetime_date_time_values_t date_time_values;
386 
387 	static char *function = "libfdatetime_fat_date_time_get_string_size";
388 	int result            = 0;
389 
390 	if( fat_date_time == NULL )
391 	{
392 		libcerror_error_set(
393 		 error,
394 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
395 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
396 		 "%s: invalid FAT date time.",
397 		 function );
398 
399 		return( -1 );
400 	}
401 	if( string_size == NULL )
402 	{
403 		libcerror_error_set(
404 		 error,
405 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
406 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
407 		 "%s: invalid string size.",
408 		 function );
409 
410 		return( -1 );
411 	}
412 	result = libfdatetime_internal_fat_date_time_copy_to_date_time_values(
413 	          (libfdatetime_internal_fat_date_time_t *) fat_date_time,
414 	          &date_time_values,
415 	          error );
416 
417 	if( result != 1 )
418 	{
419 #if defined( HAVE_DEBUG_OUTPUT )
420 		libcerror_error_set(
421 		 error,
422 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
423 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
424 		 "%s: unable to set date time values.",
425 		 function );
426 
427 /* TODO debug print error */
428 
429 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
430 
431 		if( ( error != NULL )
432 		 && ( *error != NULL ) )
433 		{
434 			libcerror_error_free(
435 			 error );
436 		}
437 	}
438 	else
439 	{
440 		result = libfdatetime_date_time_values_get_string_size(
441 		          &date_time_values,
442 		          string_size,
443 		          string_format_flags,
444 		          error );
445 
446 		if( result == -1 )
447 		{
448 			libcerror_error_set(
449 			 error,
450 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
451 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
452 			 "%s: unable to get string size.",
453 			 function );
454 
455 			return( -1 );
456 		}
457 	}
458 	if( result != 1 )
459 	{
460 		/* Make sure the string can hold the hexadecimal representation of the FAT date time
461 		 */
462 		*string_size = 16;
463 	}
464 	return( 1 );
465 }
466 
467 /* Converts the FAT date and time into an UTF-8 string in hexadecimal representation
468  * The string size should include the end of string character
469  * Returns 1 if successful or -1 on error
470  */
libfdatetime_internal_fat_date_time_copy_to_utf8_string_in_hexadecimal(libfdatetime_internal_fat_date_time_t * internal_fat_date_time,uint8_t * utf8_string,size_t utf8_string_size,size_t * utf8_string_index,libcerror_error_t ** error)471 int libfdatetime_internal_fat_date_time_copy_to_utf8_string_in_hexadecimal(
472      libfdatetime_internal_fat_date_time_t *internal_fat_date_time,
473      uint8_t *utf8_string,
474      size_t utf8_string_size,
475      size_t *utf8_string_index,
476      libcerror_error_t **error )
477 {
478 	static char *function = "libfdatetime_internal_fat_date_time_copy_to_utf8_string_in_hexadecimal";
479 	size_t string_index   = 0;
480 	uint8_t byte_value    = 0;
481 	int8_t byte_shift     = 0;
482 
483 	if( internal_fat_date_time == NULL )
484 	{
485 		libcerror_error_set(
486 		 error,
487 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
488 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
489 		 "%s: invalid FAT date time.",
490 		 function );
491 
492 		return( -1 );
493 	}
494 	if( utf8_string == NULL )
495 	{
496 		libcerror_error_set(
497 		 error,
498 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
499 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
500 		 "%s: invalid UTF-8 string.",
501 		 function );
502 
503 		return( -1 );
504 	}
505 	if( utf8_string_size > (size_t) SSIZE_MAX )
506 	{
507 		libcerror_error_set(
508 		 error,
509 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
510 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
511 		 "%s: invalid UTF-8 string size value exceeds maximum.",
512 		 function );
513 
514 		return( -1 );
515 	}
516 	if( utf8_string_index == NULL )
517 	{
518 		libcerror_error_set(
519 		 error,
520 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
521 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
522 		 "%s: invalid UTF-8 string index.",
523 		 function );
524 
525 		return( -1 );
526 	}
527 	if( ( utf8_string_size < 16 )
528 	 || ( *utf8_string_index > ( utf8_string_size - 16 ) ) )
529 	{
530 		libcerror_error_set(
531 		 error,
532 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
533 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
534 		 "%s: UTF-8 string is too small.",
535 		 function );
536 
537 		return( -1 );
538 	}
539 	string_index = *utf8_string_index;
540 
541 	utf8_string[ string_index++ ] = (uint8_t) '(';
542 	utf8_string[ string_index++ ] = (uint8_t) '0';
543 	utf8_string[ string_index++ ] = (uint8_t) 'x';
544 
545 	byte_shift = 12;
546 
547 	do
548 	{
549 		byte_value = ( internal_fat_date_time->date >> byte_shift ) & 0x0f;
550 
551 		if( byte_value <= 9 )
552 		{
553 			utf8_string[ string_index++ ] = (uint8_t) '0' + byte_value;
554 		}
555 		else
556 		{
557 			utf8_string[ string_index++ ] = (uint8_t) 'a' + byte_value - 10;
558 		}
559 		byte_shift -= 4;
560 	}
561 	while( byte_shift >= 0 );
562 
563 	utf8_string[ string_index++ ] = (uint8_t) ' ';
564 	utf8_string[ string_index++ ] = (uint8_t) '0';
565 	utf8_string[ string_index++ ] = (uint8_t) 'x';
566 
567 	byte_shift = 12;
568 
569 	do
570 	{
571 		byte_value = ( internal_fat_date_time->time >> byte_shift ) & 0x0f;
572 
573 		if( byte_value <= 9 )
574 		{
575 			utf8_string[ string_index++ ] = (uint8_t) '0' + byte_value;
576 		}
577 		else
578 		{
579 			utf8_string[ string_index++ ] = (uint8_t) 'a' + byte_value - 10;
580 		}
581 		byte_shift -= 4;
582 	}
583 	while( byte_shift >= 0 );
584 
585 	utf8_string[ string_index++ ] = (uint8_t) ')';
586 
587 	utf8_string[ string_index++ ] = 0;
588 
589 	*utf8_string_index = string_index;
590 
591 	return( 1 );
592 }
593 
594 /* Converts the FAT date and time into an UTF-8 string
595  * The string size should include the end of string character
596  * Returns 1 if successful or -1 on error
597  */
libfdatetime_fat_date_time_copy_to_utf8_string(libfdatetime_fat_date_time_t * fat_date_time,uint8_t * utf8_string,size_t utf8_string_size,uint32_t string_format_flags,libcerror_error_t ** error)598 int libfdatetime_fat_date_time_copy_to_utf8_string(
599      libfdatetime_fat_date_time_t *fat_date_time,
600      uint8_t *utf8_string,
601      size_t utf8_string_size,
602      uint32_t string_format_flags,
603      libcerror_error_t **error )
604 {
605 	static char *function    = "libfdatetime_fat_date_time_copy_to_utf8_string";
606 	size_t utf8_string_index = 0;
607 
608 	if( libfdatetime_fat_date_time_copy_to_utf8_string_with_index(
609 	     fat_date_time,
610 	     utf8_string,
611 	     utf8_string_size,
612 	     &utf8_string_index,
613 	     string_format_flags,
614 	     error ) != 1 )
615 	{
616 		libcerror_error_set(
617 		 error,
618 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
619 		 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
620 		 "%s: unable to copy FAT date time to UTF-8 string.",
621 		 function );
622 
623 		return( -1 );
624 	}
625 	return( 1 );
626 }
627 
628 /* Converts the FAT date and time into an UTF-8 string
629  * The string size should include the end of string character
630  * Returns 1 if successful or -1 on error
631  */
libfdatetime_fat_date_time_copy_to_utf8_string_with_index(libfdatetime_fat_date_time_t * fat_date_time,uint8_t * utf8_string,size_t utf8_string_size,size_t * utf8_string_index,uint32_t string_format_flags,libcerror_error_t ** error)632 int libfdatetime_fat_date_time_copy_to_utf8_string_with_index(
633      libfdatetime_fat_date_time_t *fat_date_time,
634      uint8_t *utf8_string,
635      size_t utf8_string_size,
636      size_t *utf8_string_index,
637      uint32_t string_format_flags,
638      libcerror_error_t **error )
639 {
640 	libfdatetime_date_time_values_t date_time_values;
641 
642 	libfdatetime_internal_fat_date_time_t *internal_fat_date_time = NULL;
643 	static char *function                                         = "libfdatetime_fat_date_time_copy_to_utf8_string_with_index";
644 	int result                                                    = 0;
645 
646 	if( fat_date_time == NULL )
647 	{
648 		libcerror_error_set(
649 		 error,
650 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
651 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
652 		 "%s: invalid FAT date time.",
653 		 function );
654 
655 		return( -1 );
656 	}
657 	internal_fat_date_time = (libfdatetime_internal_fat_date_time_t *) fat_date_time;
658 
659 	result = libfdatetime_internal_fat_date_time_copy_to_date_time_values(
660 	          internal_fat_date_time,
661 	          &date_time_values,
662 	          error );
663 
664 	if( result != 1 )
665 	{
666 #if defined( HAVE_DEBUG_OUTPUT )
667 		libcerror_error_set(
668 		 error,
669 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
670 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
671 		 "%s: unable to set date time values.",
672 		 function );
673 
674 /* TODO debug print error */
675 
676 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
677 
678 		if( ( error != NULL )
679 		 && ( *error != NULL ) )
680 		{
681 			libcerror_error_free(
682 			 error );
683 		}
684 	}
685 	else
686 	{
687 		result = libfdatetime_date_time_values_copy_to_utf8_string_with_index(
688 		          &date_time_values,
689 		          utf8_string,
690 		          utf8_string_size,
691 		          utf8_string_index,
692 		          string_format_flags,
693 		          error );
694 
695 		if( result == -1 )
696 		{
697 			libcerror_error_set(
698 			 error,
699 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
700 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
701 			 "%s: unable to copy date time values to UTF-8 string.",
702 			 function );
703 
704 			return( -1 );
705 		}
706 	}
707 	if( result != 1 )
708 	{
709 		result = libfdatetime_internal_fat_date_time_copy_to_utf8_string_in_hexadecimal(
710 		          internal_fat_date_time,
711 		          utf8_string,
712 		          utf8_string_size,
713 		          utf8_string_index,
714 		          error );
715 
716 		if( result == -1 )
717 		{
718 			libcerror_error_set(
719 			 error,
720 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
721 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
722 			 "%s: unable to FAT date time values to hexadecimal UTF-8 string.",
723 			 function );
724 
725 			return( -1 );
726 		}
727 	}
728 	return( 1 );
729 }
730 
731 /* Converts the FAT date and time into an UTF-16 string in hexadecimal representation
732  * The string size should include the end of string character
733  * Returns 1 if successful or -1 on error
734  */
libfdatetime_internal_fat_date_time_copy_to_utf16_string_in_hexadecimal(libfdatetime_internal_fat_date_time_t * internal_fat_date_time,uint16_t * utf16_string,size_t utf16_string_size,size_t * utf16_string_index,libcerror_error_t ** error)735 int libfdatetime_internal_fat_date_time_copy_to_utf16_string_in_hexadecimal(
736      libfdatetime_internal_fat_date_time_t *internal_fat_date_time,
737      uint16_t *utf16_string,
738      size_t utf16_string_size,
739      size_t *utf16_string_index,
740      libcerror_error_t **error )
741 {
742 	static char *function = "libfdatetime_internal_fat_date_time_copy_to_utf16_string_in_hexadecimal";
743 	size_t string_index   = 0;
744 	uint8_t byte_value    = 0;
745 	int8_t byte_shift     = 0;
746 
747 	if( internal_fat_date_time == NULL )
748 	{
749 		libcerror_error_set(
750 		 error,
751 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
752 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
753 		 "%s: invalid FAT date time.",
754 		 function );
755 
756 		return( -1 );
757 	}
758 	if( utf16_string == NULL )
759 	{
760 		libcerror_error_set(
761 		 error,
762 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
763 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
764 		 "%s: invalid UTF-16 string.",
765 		 function );
766 
767 		return( -1 );
768 	}
769 	if( utf16_string_size > (size_t) SSIZE_MAX )
770 	{
771 		libcerror_error_set(
772 		 error,
773 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
774 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
775 		 "%s: invalid UTF-16 string size value exceeds maximum.",
776 		 function );
777 
778 		return( -1 );
779 	}
780 	if( utf16_string_index == NULL )
781 	{
782 		libcerror_error_set(
783 		 error,
784 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
785 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
786 		 "%s: invalid UTF-16 string index.",
787 		 function );
788 
789 		return( -1 );
790 	}
791 	if( ( utf16_string_size < 16 )
792 	 || ( *utf16_string_index > ( utf16_string_size - 16 ) ) )
793 	{
794 		libcerror_error_set(
795 		 error,
796 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
797 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
798 		 "%s: UTF-16 string is too small.",
799 		 function );
800 
801 		return( -1 );
802 	}
803 	string_index = *utf16_string_index;
804 
805 	utf16_string[ string_index++ ] = (uint16_t) '(';
806 	utf16_string[ string_index++ ] = (uint16_t) '0';
807 	utf16_string[ string_index++ ] = (uint16_t) 'x';
808 
809 	byte_shift = 12;
810 
811 	do
812 	{
813 		byte_value = ( internal_fat_date_time->date >> byte_shift ) & 0x0f;
814 
815 		if( byte_value <= 9 )
816 		{
817 			utf16_string[ string_index++ ] = (uint16_t) '0' + byte_value;
818 		}
819 		else
820 		{
821 			utf16_string[ string_index++ ] = (uint16_t) 'a' + byte_value - 10;
822 		}
823 		byte_shift -= 4;
824 	}
825 	while( byte_shift >= 0 );
826 
827 	utf16_string[ string_index++ ] = (uint16_t) ' ';
828 	utf16_string[ string_index++ ] = (uint16_t) '0';
829 	utf16_string[ string_index++ ] = (uint16_t) 'x';
830 
831 	byte_shift = 12;
832 
833 	do
834 	{
835 		byte_value = ( internal_fat_date_time->time >> byte_shift ) & 0x0f;
836 
837 		if( byte_value <= 9 )
838 		{
839 			utf16_string[ string_index++ ] = (uint16_t) '0' + byte_value;
840 		}
841 		else
842 		{
843 			utf16_string[ string_index++ ] = (uint16_t) 'a' + byte_value - 10;
844 		}
845 		byte_shift -= 4;
846 	}
847 	while( byte_shift >= 0 );
848 
849 	utf16_string[ string_index++ ] = (uint16_t) ')';
850 
851 	utf16_string[ string_index++ ] = 0;
852 
853 	*utf16_string_index = string_index;
854 
855 	return( 1 );
856 }
857 
858 /* Converts the FAT date and time into an UTF-16 string
859  * The string size should include the end of string character
860  * Returns 1 if successful or -1 on error
861  */
libfdatetime_fat_date_time_copy_to_utf16_string(libfdatetime_fat_date_time_t * fat_date_time,uint16_t * utf16_string,size_t utf16_string_size,uint32_t string_format_flags,libcerror_error_t ** error)862 int libfdatetime_fat_date_time_copy_to_utf16_string(
863      libfdatetime_fat_date_time_t *fat_date_time,
864      uint16_t *utf16_string,
865      size_t utf16_string_size,
866      uint32_t string_format_flags,
867      libcerror_error_t **error )
868 {
869 	static char *function     = "libfdatetime_fat_date_time_copy_to_utf16_string";
870 	size_t utf16_string_index = 0;
871 
872 	if( libfdatetime_fat_date_time_copy_to_utf16_string_with_index(
873 	     fat_date_time,
874 	     utf16_string,
875 	     utf16_string_size,
876 	     &utf16_string_index,
877 	     string_format_flags,
878 	     error ) != 1 )
879 	{
880 		libcerror_error_set(
881 		 error,
882 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
883 		 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
884 		 "%s: unable to copy FAT date time to UTF-16 string.",
885 		 function );
886 
887 		return( -1 );
888 	}
889 	return( 1 );
890 }
891 
892 /* Converts the FAT date and time into an UTF-16 string
893  * The string size should include the end of string character
894  * Returns 1 if successful or -1 on error
895  */
libfdatetime_fat_date_time_copy_to_utf16_string_with_index(libfdatetime_fat_date_time_t * fat_date_time,uint16_t * utf16_string,size_t utf16_string_size,size_t * utf16_string_index,uint32_t string_format_flags,libcerror_error_t ** error)896 int libfdatetime_fat_date_time_copy_to_utf16_string_with_index(
897      libfdatetime_fat_date_time_t *fat_date_time,
898      uint16_t *utf16_string,
899      size_t utf16_string_size,
900      size_t *utf16_string_index,
901      uint32_t string_format_flags,
902      libcerror_error_t **error )
903 {
904 	libfdatetime_date_time_values_t date_time_values;
905 
906 	libfdatetime_internal_fat_date_time_t *internal_fat_date_time = NULL;
907 	static char *function                                         = "libfdatetime_fat_date_time_copy_to_utf16_string_with_index";
908 	int result                                                    = 0;
909 
910 	if( fat_date_time == NULL )
911 	{
912 		libcerror_error_set(
913 		 error,
914 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
915 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
916 		 "%s: invalid FAT date time.",
917 		 function );
918 
919 		return( -1 );
920 	}
921 	internal_fat_date_time = (libfdatetime_internal_fat_date_time_t *) fat_date_time;
922 
923 	result = libfdatetime_internal_fat_date_time_copy_to_date_time_values(
924 	          (libfdatetime_internal_fat_date_time_t *) fat_date_time,
925 	          &date_time_values,
926 	          error );
927 
928 	if( result != 1 )
929 	{
930 #if defined( HAVE_DEBUG_OUTPUT )
931 		libcerror_error_set(
932 		 error,
933 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
934 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
935 		 "%s: unable to set date time values.",
936 		 function );
937 
938 /* TODO debug print error */
939 
940 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
941 
942 		if( ( error != NULL )
943 		 && ( *error != NULL ) )
944 		{
945 			libcerror_error_free(
946 			 error );
947 		}
948 	}
949 	else
950 	{
951 		result = libfdatetime_date_time_values_copy_to_utf16_string_with_index(
952 		          &date_time_values,
953 		          utf16_string,
954 		          utf16_string_size,
955 		          utf16_string_index,
956 		          string_format_flags,
957 		          error );
958 
959 		if( result == -1 )
960 		{
961 			libcerror_error_set(
962 			 error,
963 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
964 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
965 			 "%s: unable to copy date time values to UTF-16 string.",
966 			 function );
967 
968 			return( -1 );
969 		}
970 	}
971 	if( result != 1 )
972 	{
973 		result = libfdatetime_internal_fat_date_time_copy_to_utf16_string_in_hexadecimal(
974 		          internal_fat_date_time,
975 		          utf16_string,
976 		          utf16_string_size,
977 		          utf16_string_index,
978 		          error );
979 
980 		if( result == -1 )
981 		{
982 			libcerror_error_set(
983 			 error,
984 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
985 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
986 			 "%s: unable to FAT date time values to hexadecimal UTF-16 string.",
987 			 function );
988 
989 			return( -1 );
990 		}
991 	}
992 	return( 1 );
993 }
994 
995 /* Converts the FAT date and time into an UTF-32 string in hexadecimal representation
996  * The string size should include the end of string character
997  * Returns 1 if successful or -1 on error
998  */
libfdatetime_internal_fat_date_time_copy_to_utf32_string_in_hexadecimal(libfdatetime_internal_fat_date_time_t * internal_fat_date_time,uint32_t * utf32_string,size_t utf32_string_size,size_t * utf32_string_index,libcerror_error_t ** error)999 int libfdatetime_internal_fat_date_time_copy_to_utf32_string_in_hexadecimal(
1000      libfdatetime_internal_fat_date_time_t *internal_fat_date_time,
1001      uint32_t *utf32_string,
1002      size_t utf32_string_size,
1003      size_t *utf32_string_index,
1004      libcerror_error_t **error )
1005 {
1006 	static char *function = "libfdatetime_internal_fat_date_time_copy_to_utf32_string_in_hexadecimal";
1007 	size_t string_index   = 0;
1008 	uint8_t byte_value    = 0;
1009 	int8_t byte_shift     = 0;
1010 
1011 	if( internal_fat_date_time == NULL )
1012 	{
1013 		libcerror_error_set(
1014 		 error,
1015 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1016 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1017 		 "%s: invalid FAT date time.",
1018 		 function );
1019 
1020 		return( -1 );
1021 	}
1022 	if( utf32_string == NULL )
1023 	{
1024 		libcerror_error_set(
1025 		 error,
1026 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1027 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1028 		 "%s: invalid UTF-32 string.",
1029 		 function );
1030 
1031 		return( -1 );
1032 	}
1033 	if( utf32_string_size > (size_t) SSIZE_MAX )
1034 	{
1035 		libcerror_error_set(
1036 		 error,
1037 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1038 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1039 		 "%s: invalid UTF-32 string size value exceeds maximum.",
1040 		 function );
1041 
1042 		return( -1 );
1043 	}
1044 	if( utf32_string_index == NULL )
1045 	{
1046 		libcerror_error_set(
1047 		 error,
1048 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1049 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1050 		 "%s: invalid UTF-32 string index.",
1051 		 function );
1052 
1053 		return( -1 );
1054 	}
1055 	if( ( utf32_string_size < 16 )
1056 	 || ( *utf32_string_index > ( utf32_string_size - 16 ) ) )
1057 	{
1058 		libcerror_error_set(
1059 		 error,
1060 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1061 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1062 		 "%s: UTF-32 string is too small.",
1063 		 function );
1064 
1065 		return( -1 );
1066 	}
1067 	string_index = *utf32_string_index;
1068 
1069 	utf32_string[ string_index++ ] = (uint32_t) '(';
1070 	utf32_string[ string_index++ ] = (uint32_t) '0';
1071 	utf32_string[ string_index++ ] = (uint32_t) 'x';
1072 
1073 	byte_shift = 12;
1074 
1075 	do
1076 	{
1077 		byte_value = ( internal_fat_date_time->date >> byte_shift ) & 0x0f;
1078 
1079 		if( byte_value <= 9 )
1080 		{
1081 			utf32_string[ string_index++ ] = (uint32_t) '0' + byte_value;
1082 		}
1083 		else
1084 		{
1085 			utf32_string[ string_index++ ] = (uint32_t) 'a' + byte_value - 10;
1086 		}
1087 		byte_shift -= 4;
1088 	}
1089 	while( byte_shift >= 0 );
1090 
1091 	utf32_string[ string_index++ ] = (uint32_t) ' ';
1092 	utf32_string[ string_index++ ] = (uint32_t) '0';
1093 	utf32_string[ string_index++ ] = (uint32_t) 'x';
1094 
1095 	byte_shift = 12;
1096 
1097 	do
1098 	{
1099 		byte_value = ( internal_fat_date_time->time >> byte_shift ) & 0x0f;
1100 
1101 		if( byte_value <= 9 )
1102 		{
1103 			utf32_string[ string_index++ ] = (uint32_t) '0' + byte_value;
1104 		}
1105 		else
1106 		{
1107 			utf32_string[ string_index++ ] = (uint32_t) 'a' + byte_value - 10;
1108 		}
1109 		byte_shift -= 4;
1110 	}
1111 	while( byte_shift >= 0 );
1112 
1113 	utf32_string[ string_index++ ] = (uint32_t) ')';
1114 
1115 	utf32_string[ string_index++ ] = 0;
1116 
1117 	*utf32_string_index = string_index;
1118 
1119 	return( 1 );
1120 }
1121 
1122 /* Converts the FAT date and time into an UTF-32 string
1123  * The string size should include the end of string character
1124  * Returns 1 if successful or -1 on error
1125  */
libfdatetime_fat_date_time_copy_to_utf32_string(libfdatetime_fat_date_time_t * fat_date_time,uint32_t * utf32_string,size_t utf32_string_size,uint32_t string_format_flags,libcerror_error_t ** error)1126 int libfdatetime_fat_date_time_copy_to_utf32_string(
1127      libfdatetime_fat_date_time_t *fat_date_time,
1128      uint32_t *utf32_string,
1129      size_t utf32_string_size,
1130      uint32_t string_format_flags,
1131      libcerror_error_t **error )
1132 {
1133 	static char *function     = "libfdatetime_fat_date_time_copy_to_utf32_string";
1134 	size_t utf32_string_index = 0;
1135 
1136 	if( libfdatetime_fat_date_time_copy_to_utf32_string_with_index(
1137 	     fat_date_time,
1138 	     utf32_string,
1139 	     utf32_string_size,
1140 	     &utf32_string_index,
1141 	     string_format_flags,
1142 	     error ) != 1 )
1143 	{
1144 		libcerror_error_set(
1145 		 error,
1146 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1147 		 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1148 		 "%s: unable to copy FAT date time to UTF-32 string.",
1149 		 function );
1150 
1151 		return( -1 );
1152 	}
1153 	return( 1 );
1154 }
1155 
1156 /* Converts the FAT date and time into an UTF-32 string
1157  * The string size should include the end of string character
1158  * Returns 1 if successful or -1 on error
1159  */
libfdatetime_fat_date_time_copy_to_utf32_string_with_index(libfdatetime_fat_date_time_t * fat_date_time,uint32_t * utf32_string,size_t utf32_string_size,size_t * utf32_string_index,uint32_t string_format_flags,libcerror_error_t ** error)1160 int libfdatetime_fat_date_time_copy_to_utf32_string_with_index(
1161      libfdatetime_fat_date_time_t *fat_date_time,
1162      uint32_t *utf32_string,
1163      size_t utf32_string_size,
1164      size_t *utf32_string_index,
1165      uint32_t string_format_flags,
1166      libcerror_error_t **error )
1167 {
1168 	libfdatetime_date_time_values_t date_time_values;
1169 
1170 	libfdatetime_internal_fat_date_time_t *internal_fat_date_time = NULL;
1171 	static char *function                                         = "libfdatetime_fat_date_time_copy_to_utf32_string_with_index";
1172 	int result                                                    = 0;
1173 
1174 	if( fat_date_time == NULL )
1175 	{
1176 		libcerror_error_set(
1177 		 error,
1178 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1179 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1180 		 "%s: invalid FAT date time.",
1181 		 function );
1182 
1183 		return( -1 );
1184 	}
1185 	internal_fat_date_time = (libfdatetime_internal_fat_date_time_t *) fat_date_time;
1186 
1187 	result = libfdatetime_internal_fat_date_time_copy_to_date_time_values(
1188 	          (libfdatetime_internal_fat_date_time_t *) fat_date_time,
1189 	          &date_time_values,
1190 	          error );
1191 
1192 	if( result != 1 )
1193 	{
1194 #if defined( HAVE_DEBUG_OUTPUT )
1195 		libcerror_error_set(
1196 		 error,
1197 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1198 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1199 		 "%s: unable to set date time values.",
1200 		 function );
1201 
1202 /* TODO debug print error */
1203 
1204 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
1205 
1206 		if( ( error != NULL )
1207 		 && ( *error != NULL ) )
1208 		{
1209 			libcerror_error_free(
1210 			 error );
1211 		}
1212 	}
1213 	else
1214 	{
1215 		result = libfdatetime_date_time_values_copy_to_utf32_string_with_index(
1216 		          &date_time_values,
1217 		          utf32_string,
1218 		          utf32_string_size,
1219 		          utf32_string_index,
1220 		          string_format_flags,
1221 		          error );
1222 
1223 		if( result == -1 )
1224 		{
1225 			libcerror_error_set(
1226 			 error,
1227 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1228 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1229 			 "%s: unable to copy date time values to UTF-32 string.",
1230 			 function );
1231 
1232 			return( -1 );
1233 		}
1234 	}
1235 	if( result != 1 )
1236 	{
1237 		result = libfdatetime_internal_fat_date_time_copy_to_utf32_string_in_hexadecimal(
1238 		          internal_fat_date_time,
1239 		          utf32_string,
1240 		          utf32_string_size,
1241 		          utf32_string_index,
1242 		          error );
1243 
1244 		if( result == -1 )
1245 		{
1246 			libcerror_error_set(
1247 			 error,
1248 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1249 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1250 			 "%s: unable to FAT date time values to hexadecimal UTF-32 string.",
1251 			 function );
1252 
1253 			return( -1 );
1254 		}
1255 	}
1256 	return( 1 );
1257 }
1258 
1259