1 /*
2 * Functions for testing
3 *
4 * Copyright (C) 2020-2021, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include <common.h>
23 #include <file_stream.h>
24 #include <narrow_string.h>
25 #include <system_string.h>
26 #include <types.h>
27 #include <wide_string.h>
28
29 #if defined( HAVE_STDLIB_H ) || defined( WINAPI )
30 #include <stdlib.h>
31 #endif
32
33 #include "fsxfs_test_libbfio.h"
34 #include "fsxfs_test_libcerror.h"
35 #include "fsxfs_test_libclocale.h"
36 #include "fsxfs_test_libuna.h"
37
38 /* Retrieves source as a narrow string
39 * Returns 1 if successful or -1 on error
40 */
fsxfs_test_get_narrow_source(const system_character_t * source,char * narrow_string,size_t narrow_string_size,libcerror_error_t ** error)41 int fsxfs_test_get_narrow_source(
42 const system_character_t *source,
43 char *narrow_string,
44 size_t narrow_string_size,
45 libcerror_error_t **error )
46 {
47 static char *function = "fsxfs_test_get_narrow_source";
48 size_t narrow_source_size = 0;
49 size_t source_length = 0;
50
51 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
52 int result = 0;
53 #endif
54
55 if( source == NULL )
56 {
57 libcerror_error_set(
58 error,
59 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
60 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
61 "%s: invalid source.",
62 function );
63
64 return( -1 );
65 }
66 if( narrow_string == NULL )
67 {
68 libcerror_error_set(
69 error,
70 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
71 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
72 "%s: invalid narrow string.",
73 function );
74
75 return( -1 );
76 }
77 if( narrow_string_size > (size_t) SSIZE_MAX )
78 {
79 libcerror_error_set(
80 error,
81 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
82 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
83 "%s: invalid narrow string size value exceeds maximum.",
84 function );
85
86 return( -1 );
87 }
88 source_length = system_string_length(
89 source );
90
91 if( source_length > (size_t) ( SSIZE_MAX - 1 ) )
92 {
93 libcerror_error_set(
94 error,
95 LIBCERROR_ERROR_DOMAIN_RUNTIME,
96 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
97 "%s: invalid source length value out of bounds.",
98 function );
99
100 return( -1 );
101 }
102 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
103 if( libclocale_codepage == 0 )
104 {
105 #if SIZEOF_WCHAR_T == 4
106 result = libuna_utf8_string_size_from_utf32(
107 (libuna_utf32_character_t *) source,
108 source_length + 1,
109 &narrow_source_size,
110 error );
111 #elif SIZEOF_WCHAR_T == 2
112 result = libuna_utf8_string_size_from_utf16(
113 (libuna_utf16_character_t *) source,
114 source_length + 1,
115 &narrow_source_size,
116 error );
117 #endif
118 }
119 else
120 {
121 #if SIZEOF_WCHAR_T == 4
122 result = libuna_byte_stream_size_from_utf32(
123 (libuna_utf32_character_t *) source,
124 source_length + 1,
125 libclocale_codepage,
126 &narrow_source_size,
127 error );
128 #elif SIZEOF_WCHAR_T == 2
129 result = libuna_byte_stream_size_from_utf16(
130 (libuna_utf16_character_t *) source,
131 source_length + 1,
132 libclocale_codepage,
133 &narrow_source_size,
134 error );
135 #endif
136 }
137 if( result != 1 )
138 {
139 libcerror_error_set(
140 error,
141 LIBCERROR_ERROR_DOMAIN_CONVERSION,
142 LIBCERROR_CONVERSION_ERROR_GENERIC,
143 "%s: unable to determine narrow string size.",
144 function );
145
146 return( -1 );
147 }
148 #else
149 narrow_source_size = source_length + 1;
150
151 #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
152
153 if( narrow_string_size < narrow_source_size )
154 {
155 libcerror_error_set(
156 error,
157 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
158 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
159 "%s: narrow string too small.",
160 function );
161
162 return( -1 );
163 }
164 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
165 if( libclocale_codepage == 0 )
166 {
167 #if SIZEOF_WCHAR_T == 4
168 result = libuna_utf8_string_copy_from_utf32(
169 (libuna_utf8_character_t *) narrow_string,
170 narrow_string_size,
171 (libuna_utf32_character_t *) source,
172 source_length + 1,
173 error );
174 #elif SIZEOF_WCHAR_T == 2
175 result = libuna_utf8_string_copy_from_utf16(
176 (libuna_utf8_character_t *) narrow_string,
177 narrow_string_size,
178 (libuna_utf16_character_t *) source,
179 source_length + 1,
180 error );
181 #endif
182 }
183 else
184 {
185 #if SIZEOF_WCHAR_T == 4
186 result = libuna_byte_stream_copy_from_utf32(
187 (uint8_t *) narrow_string,
188 narrow_string_size,
189 libclocale_codepage,
190 (libuna_utf32_character_t *) source,
191 source_length + 1,
192 error );
193 #elif SIZEOF_WCHAR_T == 2
194 result = libuna_byte_stream_copy_from_utf16(
195 (uint8_t *) narrow_string,
196 narrow_string_size,
197 libclocale_codepage,
198 (libuna_utf16_character_t *) source,
199 source_length + 1,
200 error );
201 #endif
202 }
203 if( result != 1 )
204 {
205 libcerror_error_set(
206 error,
207 LIBCERROR_ERROR_DOMAIN_CONVERSION,
208 LIBCERROR_CONVERSION_ERROR_GENERIC,
209 "%s: unable to set narrow string.",
210 function );
211
212 return( -1 );
213 }
214 #else
215 if( system_string_copy(
216 narrow_string,
217 source,
218 source_length ) == NULL )
219 {
220 libcerror_error_set(
221 error,
222 LIBCERROR_ERROR_DOMAIN_MEMORY,
223 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
224 "%s: unable to set narrow string.",
225 function );
226
227 return( -1 );
228 }
229 narrow_string[ source_length ] = 0;
230
231 #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
232
233 return( 1 );
234 }
235
236 #if defined( HAVE_WIDE_CHARACTER_TYPE )
237
238 /* Retrieves source as a wide string
239 * Returns 1 if successful or -1 on error
240 */
fsxfs_test_get_wide_source(const system_character_t * source,wchar_t * wide_string,size_t wide_string_size,libcerror_error_t ** error)241 int fsxfs_test_get_wide_source(
242 const system_character_t *source,
243 wchar_t *wide_string,
244 size_t wide_string_size,
245 libcerror_error_t **error )
246 {
247 static char *function = "fsxfs_test_get_wide_source";
248 size_t wide_source_size = 0;
249 size_t source_length = 0;
250
251 #if !defined( HAVE_WIDE_SYSTEM_CHARACTER )
252 int result = 0;
253 #endif
254
255 if( source == NULL )
256 {
257 libcerror_error_set(
258 error,
259 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
260 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
261 "%s: invalid source.",
262 function );
263
264 return( -1 );
265 }
266 if( wide_string == NULL )
267 {
268 libcerror_error_set(
269 error,
270 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
271 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
272 "%s: invalid wide string.",
273 function );
274
275 return( -1 );
276 }
277 if( wide_string_size > (size_t) SSIZE_MAX )
278 {
279 libcerror_error_set(
280 error,
281 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
282 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
283 "%s: invalid wide string size value exceeds maximum.",
284 function );
285
286 return( -1 );
287 }
288 source_length = system_string_length(
289 source );
290
291 if( source_length > (size_t) ( SSIZE_MAX - 1 ) )
292 {
293 libcerror_error_set(
294 error,
295 LIBCERROR_ERROR_DOMAIN_RUNTIME,
296 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
297 "%s: invalid source length value out of bounds.",
298 function );
299
300 return( -1 );
301 }
302 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
303 wide_source_size = source_length + 1;
304 #else
305 if( libclocale_codepage == 0 )
306 {
307 #if SIZEOF_WCHAR_T == 4
308 result = libuna_utf32_string_size_from_utf8(
309 (libuna_utf8_character_t *) source,
310 source_length + 1,
311 &wide_source_size,
312 error );
313 #elif SIZEOF_WCHAR_T == 2
314 result = libuna_utf16_string_size_from_utf8(
315 (libuna_utf8_character_t *) source,
316 source_length + 1,
317 &wide_source_size,
318 error );
319 #endif
320 }
321 else
322 {
323 #if SIZEOF_WCHAR_T == 4
324 result = libuna_utf32_string_size_from_byte_stream(
325 (uint8_t *) source,
326 source_length + 1,
327 libclocale_codepage,
328 &wide_source_size,
329 error );
330 #elif SIZEOF_WCHAR_T == 2
331 result = libuna_utf16_string_size_from_byte_stream(
332 (uint8_t *) source,
333 source_length + 1,
334 libclocale_codepage,
335 &wide_source_size,
336 error );
337 #endif
338 }
339 if( result != 1 )
340 {
341 libcerror_error_set(
342 error,
343 LIBCERROR_ERROR_DOMAIN_CONVERSION,
344 LIBCERROR_CONVERSION_ERROR_GENERIC,
345 "%s: unable to determine wide string size.",
346 function );
347
348 return( -1 );
349 }
350 #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
351
352 if( wide_string_size < wide_source_size )
353 {
354 libcerror_error_set(
355 error,
356 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
357 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
358 "%s: wide string too small.",
359 function );
360
361 return( -1 );
362 }
363 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
364 if( system_string_copy(
365 wide_string,
366 source,
367 source_length ) == NULL )
368 {
369 libcerror_error_set(
370 error,
371 LIBCERROR_ERROR_DOMAIN_MEMORY,
372 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
373 "%s: unable to set wide string.",
374 function );
375
376 return( -1 );
377 }
378 wide_string[ source_length ] = 0;
379 #else
380 if( libclocale_codepage == 0 )
381 {
382 #if SIZEOF_WCHAR_T == 4
383 result = libuna_utf32_string_copy_from_utf8(
384 (libuna_utf32_character_t *) wide_string,
385 wide_string_size,
386 (uint8_t *) source,
387 source_length + 1,
388 error );
389 #elif SIZEOF_WCHAR_T == 2
390 result = libuna_utf16_string_copy_from_utf8(
391 (libuna_utf16_character_t *) wide_string,
392 wide_string_size,
393 (uint8_t *) source,
394 source_length + 1,
395 error );
396 #endif
397 }
398 else
399 {
400 #if SIZEOF_WCHAR_T == 4
401 result = libuna_utf32_string_copy_from_byte_stream(
402 (libuna_utf32_character_t *) wide_string,
403 wide_string_size,
404 (uint8_t *) source,
405 source_length + 1,
406 libclocale_codepage,
407 error );
408 #elif SIZEOF_WCHAR_T == 2
409 result = libuna_utf16_string_copy_from_byte_stream(
410 (libuna_utf16_character_t *) wide_string,
411 wide_string_size,
412 (uint8_t *) source,
413 source_length + 1,
414 libclocale_codepage,
415 error );
416 #endif
417 }
418 if( result != 1 )
419 {
420 libcerror_error_set(
421 error,
422 LIBCERROR_ERROR_DOMAIN_CONVERSION,
423 LIBCERROR_CONVERSION_ERROR_GENERIC,
424 "%s: unable to set wide string.",
425 function );
426
427 return( -1 );
428 }
429
430 #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */
431
432 return( 1 );
433 }
434
435 #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
436
437 /* Copies a string of a decimal value to a 64-bit value
438 * Returns 1 if successful or -1 on error
439 */
fsxfs_test_system_string_copy_from_64_bit_in_decimal(const system_character_t * string,size_t string_size,uint64_t * value_64bit,libcerror_error_t ** error)440 int fsxfs_test_system_string_copy_from_64_bit_in_decimal(
441 const system_character_t *string,
442 size_t string_size,
443 uint64_t *value_64bit,
444 libcerror_error_t **error )
445 {
446 static char *function = "fsxfs_test_system_string_copy_from_64_bit_in_decimal";
447 size_t string_index = 0;
448 system_character_t character_value = 0;
449 uint8_t maximum_string_index = 20;
450 int8_t sign = 1;
451
452 if( string == NULL )
453 {
454 libcerror_error_set(
455 error,
456 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
457 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
458 "%s: invalid string.",
459 function );
460
461 return( -1 );
462 }
463 if( string_size > (size_t) SSIZE_MAX )
464 {
465 libcerror_error_set(
466 error,
467 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
468 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
469 "%s: invalid string size value exceeds maximum.",
470 function );
471
472 return( -1 );
473 }
474 if( value_64bit == NULL )
475 {
476 libcerror_error_set(
477 error,
478 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
479 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
480 "%s: invalid value 64-bit.",
481 function );
482
483 return( -1 );
484 }
485 *value_64bit = 0;
486
487 if( string[ string_index ] == (system_character_t) '-' )
488 {
489 string_index++;
490 maximum_string_index++;
491
492 sign = -1;
493 }
494 else if( string[ string_index ] == (system_character_t) '+' )
495 {
496 string_index++;
497 maximum_string_index++;
498 }
499 while( string_index < string_size )
500 {
501 if( string[ string_index ] == 0 )
502 {
503 break;
504 }
505 if( string_index > (size_t) maximum_string_index )
506 {
507 libcerror_error_set(
508 error,
509 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
510 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_LARGE,
511 "%s: string too large.",
512 function );
513
514 return( -1 );
515 }
516 *value_64bit *= 10;
517
518 if( ( string[ string_index ] >= (system_character_t) '0' )
519 && ( string[ string_index ] <= (system_character_t) '9' ) )
520 {
521 character_value = (system_character_t) ( string[ string_index ] - (system_character_t) '0' );
522 }
523 else
524 {
525 libcerror_error_set(
526 error,
527 LIBCERROR_ERROR_DOMAIN_RUNTIME,
528 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
529 "%s: unsupported character value: %" PRIc_SYSTEM " at index: %d.",
530 function,
531 string[ string_index ],
532 string_index );
533
534 return( -1 );
535 }
536 *value_64bit += character_value;
537
538 string_index++;
539 }
540 if( sign == -1 )
541 {
542 *value_64bit *= (uint64_t) -1;
543 }
544 return( 1 );
545 }
546
547 /* Creates a file IO handle for test data
548 * Returns 1 if successful or -1 on error
549 */
fsxfs_test_open_file_io_handle(libbfio_handle_t ** file_io_handle,uint8_t * data,size_t data_size,libcerror_error_t ** error)550 int fsxfs_test_open_file_io_handle(
551 libbfio_handle_t **file_io_handle,
552 uint8_t *data,
553 size_t data_size,
554 libcerror_error_t **error )
555 {
556 static char *function = "fsxfs_test_open_file_io_handle";
557
558 if( file_io_handle == NULL )
559 {
560 libcerror_error_set(
561 error,
562 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
563 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
564 "%s: invalid file IO handle.",
565 function );
566
567 return( -1 );
568 }
569 if( libbfio_memory_range_initialize(
570 file_io_handle,
571 error ) != 1 )
572 {
573 libcerror_error_set(
574 error,
575 LIBCERROR_ERROR_DOMAIN_RUNTIME,
576 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
577 "%s: unable to create file IO handle.",
578 function );
579
580 goto on_error;
581 }
582 if( libbfio_memory_range_set(
583 *file_io_handle,
584 data,
585 data_size,
586 error ) != 1 )
587 {
588 libcerror_error_set(
589 error,
590 LIBCERROR_ERROR_DOMAIN_RUNTIME,
591 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
592 "%s: unable to set memory range of file IO handle.",
593 function );
594
595 goto on_error;
596 }
597 if( libbfio_handle_open(
598 *file_io_handle,
599 LIBBFIO_OPEN_READ,
600 error ) != 1 )
601 {
602 libcerror_error_set(
603 error,
604 LIBCERROR_ERROR_DOMAIN_IO,
605 LIBCERROR_IO_ERROR_OPEN_FAILED,
606 "%s: unable to open file IO handle.",
607 function );
608
609 goto on_error;
610 }
611 return( 1 );
612
613 on_error:
614 if( *file_io_handle != NULL )
615 {
616 libbfio_handle_free(
617 file_io_handle,
618 NULL );
619 }
620 return( -1 );
621 }
622
623 /* Closes a file IO handle for test data
624 * Returns 0 if successful or -1 on error
625 */
fsxfs_test_close_file_io_handle(libbfio_handle_t ** file_io_handle,libcerror_error_t ** error)626 int fsxfs_test_close_file_io_handle(
627 libbfio_handle_t **file_io_handle,
628 libcerror_error_t **error )
629 {
630 static char *function = "fsxfs_test_close_file_io_handle";
631 int result = 0;
632
633 if( file_io_handle == NULL )
634 {
635 libcerror_error_set(
636 error,
637 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
638 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
639 "%s: invalid file IO handle.",
640 function );
641
642 return( -1 );
643 }
644 if( libbfio_handle_close(
645 *file_io_handle,
646 error ) != 0 )
647 {
648 libcerror_error_set(
649 error,
650 LIBCERROR_ERROR_DOMAIN_IO,
651 LIBCERROR_IO_ERROR_CLOSE_FAILED,
652 "%s: unable to close file IO handle.",
653 function );
654
655 result = -1;
656 }
657 if( libbfio_handle_free(
658 file_io_handle,
659 error ) != 1 )
660 {
661 libcerror_error_set(
662 error,
663 LIBCERROR_ERROR_DOMAIN_RUNTIME,
664 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
665 "%s: unable to free file IO handle.",
666 function );
667
668 result = -1;
669 }
670 return( result );
671 }
672
673