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