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