/src/libfwsi/libcerror/libcerror_error.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Error functions |
3 | | * |
4 | | * Copyright (C) 2008-2024, 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 <memory.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_STDARG_H ) || defined( WINAPI ) |
30 | | #include <stdarg.h> |
31 | | #elif defined( HAVE_VARARGS_H ) |
32 | | #include <varargs.h> |
33 | | #else |
34 | | #error Missing headers stdarg.h and varargs.h |
35 | | #endif |
36 | | |
37 | | #include <errno.h> |
38 | | |
39 | | #include "libcerror_definitions.h" |
40 | | #include "libcerror_error.h" |
41 | | #include "libcerror_types.h" |
42 | | |
43 | | /* Creates an error |
44 | | * Returns 1 if successful or -1 on error |
45 | | */ |
46 | | int libcerror_error_initialize( |
47 | | libcerror_error_t **error, |
48 | | int error_domain, |
49 | | int error_code ) |
50 | 0 | { |
51 | 0 | libcerror_internal_error_t *internal_error = NULL; |
52 | |
|
53 | 0 | if( error == NULL ) |
54 | 0 | { |
55 | 0 | return( -1 ); |
56 | 0 | } |
57 | 0 | if( *error != NULL ) |
58 | 0 | { |
59 | 0 | return( -1 ); |
60 | 0 | } |
61 | 0 | internal_error = memory_allocate_structure( |
62 | 0 | libcerror_internal_error_t ); |
63 | |
|
64 | 0 | if( internal_error == NULL ) |
65 | 0 | { |
66 | 0 | return( -1 ); |
67 | 0 | } |
68 | 0 | internal_error->domain = error_domain; |
69 | 0 | internal_error->code = error_code; |
70 | 0 | internal_error->number_of_messages = 0; |
71 | 0 | internal_error->messages = NULL; |
72 | 0 | internal_error->sizes = NULL; |
73 | |
|
74 | 0 | *error = (libcerror_error_t *) internal_error; |
75 | |
|
76 | 0 | return( 1 ); |
77 | 0 | } |
78 | | |
79 | | /* Free an error and its elements |
80 | | */ |
81 | | void libcerror_error_free( |
82 | | libcerror_error_t **error ) |
83 | 233k | { |
84 | 233k | libcerror_internal_error_t *internal_error = NULL; |
85 | 233k | int message_index = 0; |
86 | | |
87 | 233k | if( error == NULL ) |
88 | 233k | { |
89 | 233k | return; |
90 | 233k | } |
91 | 0 | if( *error != NULL ) |
92 | 0 | { |
93 | 0 | internal_error = (libcerror_internal_error_t *) *error; |
94 | |
|
95 | 0 | if( internal_error->messages != NULL ) |
96 | 0 | { |
97 | 0 | for( message_index = 0; |
98 | 0 | message_index < internal_error->number_of_messages; |
99 | 0 | message_index++ ) |
100 | 0 | { |
101 | 0 | if( internal_error->messages[ message_index ] != NULL ) |
102 | 0 | { |
103 | 0 | memory_free( |
104 | 0 | internal_error->messages[ message_index ] ); |
105 | 0 | } |
106 | 0 | } |
107 | 0 | memory_free( |
108 | 0 | internal_error->messages ); |
109 | 0 | } |
110 | 0 | if( internal_error->sizes != NULL ) |
111 | 0 | { |
112 | 0 | memory_free( |
113 | 0 | internal_error->sizes ); |
114 | 0 | } |
115 | 0 | memory_free( |
116 | 0 | *error ); |
117 | |
|
118 | 0 | *error = NULL; |
119 | 0 | } |
120 | 0 | } |
121 | | |
122 | | /* Resizes an error |
123 | | * Returns 1 if successful or -1 on error |
124 | | */ |
125 | | int libcerror_error_resize( |
126 | | libcerror_internal_error_t *internal_error ) |
127 | 0 | { |
128 | 0 | void *reallocation = NULL; |
129 | 0 | int message_index = 0; |
130 | 0 | int number_of_messages = 0; |
131 | |
|
132 | 0 | if( internal_error == NULL ) |
133 | 0 | { |
134 | 0 | return( -1 ); |
135 | 0 | } |
136 | 0 | message_index = internal_error->number_of_messages; |
137 | 0 | number_of_messages = internal_error->number_of_messages + 1; |
138 | |
|
139 | 0 | reallocation = memory_reallocate( |
140 | 0 | internal_error->messages, |
141 | 0 | sizeof( system_character_t * ) * number_of_messages ); |
142 | |
|
143 | 0 | if( reallocation == NULL ) |
144 | 0 | { |
145 | 0 | return( -1 ); |
146 | 0 | } |
147 | 0 | internal_error->messages = (system_character_t **) reallocation; |
148 | |
|
149 | 0 | internal_error->messages[ message_index ] = NULL; |
150 | |
|
151 | 0 | reallocation = memory_reallocate( |
152 | 0 | internal_error->sizes, |
153 | 0 | sizeof( size_t ) * number_of_messages ); |
154 | |
|
155 | 0 | if( reallocation == NULL ) |
156 | 0 | { |
157 | 0 | return( -1 ); |
158 | 0 | } |
159 | 0 | internal_error->sizes = (size_t *) reallocation; |
160 | |
|
161 | 0 | internal_error->sizes[ message_index ] = 0; |
162 | |
|
163 | 0 | internal_error->number_of_messages += 1; |
164 | |
|
165 | 0 | return( 1 ); |
166 | 0 | } |
167 | | |
168 | | #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) |
169 | | |
170 | | /* Retrieves the format string as a system string |
171 | | */ |
172 | | void libcerror_error_get_system_format_string( |
173 | | const char *format_string, |
174 | | size_t format_string_length, |
175 | | system_character_t **system_format_string ) |
176 | | { |
177 | | void *reallocation = NULL; |
178 | | size_t next_format_string_length = 0; |
179 | | int print_count = 0; |
180 | | |
181 | | #if defined( __BORLANDC__ ) || defined( _MSC_VER ) |
182 | | size_t string_index = 0; |
183 | | #endif |
184 | | |
185 | | if( format_string == NULL ) |
186 | | { |
187 | | return; |
188 | | } |
189 | | if( format_string_length > (size_t) SSIZE_MAX ) |
190 | | { |
191 | | return; |
192 | | } |
193 | | if( system_format_string == NULL ) |
194 | | { |
195 | | return; |
196 | | } |
197 | | next_format_string_length = format_string_length + 1; |
198 | | |
199 | | do |
200 | | { |
201 | | if( next_format_string_length >= LIBCERROR_MESSAGE_MAXIMUM_SIZE ) |
202 | | { |
203 | | next_format_string_length = LIBCERROR_MESSAGE_MAXIMUM_SIZE; |
204 | | } |
205 | | reallocation = memory_reallocate( |
206 | | *system_format_string, |
207 | | sizeof( system_character_t ) * next_format_string_length ); |
208 | | |
209 | | if( reallocation == NULL ) |
210 | | { |
211 | | memory_free( |
212 | | *system_format_string ); |
213 | | |
214 | | *system_format_string = NULL; |
215 | | |
216 | | return; |
217 | | } |
218 | | *system_format_string = (system_character_t *) reallocation; |
219 | | |
220 | | format_string_length = next_format_string_length; |
221 | | |
222 | | #if defined( __BORLANDC__ ) || defined( _MSC_VER ) |
223 | | print_count = wide_string_snwprintf( |
224 | | *system_format_string, |
225 | | format_string_length, |
226 | | L"%S", |
227 | | format_string ); |
228 | | #else |
229 | | print_count = wide_string_snwprintf( |
230 | | *system_format_string, |
231 | | format_string_length, |
232 | | L"%s", |
233 | | format_string ); |
234 | | #endif |
235 | | if( print_count <= -1 ) |
236 | | { |
237 | | next_format_string_length += LIBCERROR_MESSAGE_INCREMENT_SIZE; |
238 | | } |
239 | | else if( ( (size_t) print_count > format_string_length ) |
240 | | || ( ( *system_format_string )[ print_count ] != 0 ) ) |
241 | | { |
242 | | next_format_string_length = (size_t) print_count; |
243 | | print_count = -1; |
244 | | } |
245 | | if( next_format_string_length >= LIBCERROR_MESSAGE_MAXIMUM_SIZE ) |
246 | | { |
247 | | /* TODO handle similar to error string */ |
248 | | memory_free( |
249 | | *system_format_string ); |
250 | | |
251 | | *system_format_string = NULL; |
252 | | |
253 | | return; |
254 | | } |
255 | | } |
256 | | while( print_count <= -1 ); |
257 | | |
258 | | #if defined( __BORLANDC__ ) || defined( _MSC_VER ) |
259 | | /* Rewrite %s to %S |
260 | | */ |
261 | | string_index = 0; |
262 | | |
263 | | while( string_index < format_string_length ) |
264 | | { |
265 | | if( ( *system_format_string )[ string_index ] == 0 ) |
266 | | { |
267 | | break; |
268 | | } |
269 | | else if( ( *system_format_string )[ string_index ] == (system_character_t) '%' ) |
270 | | { |
271 | | string_index++; |
272 | | |
273 | | if( ( *system_format_string )[ string_index ] == (system_character_t) 's' ) |
274 | | { |
275 | | ( *system_format_string )[ string_index ] = (system_character_t) 'S'; |
276 | | } |
277 | | } |
278 | | string_index++; |
279 | | } |
280 | | #endif /* defined( __BORLANDC__ ) || defined( _MSC_VER ) */ |
281 | | } |
282 | | |
283 | | #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */ |
284 | | |
285 | | #if defined( HAVE_STDARG_H ) || defined( WINAPI ) |
286 | | #define VARARGS( function, error, error_domain, error_code, type, argument ) \ |
287 | | function( error, error_domain, error_code, type argument, ... ) |
288 | | #define VASTART( argument_list, type, name ) \ |
289 | 0 | va_start( argument_list, name ) |
290 | | #define VAEND( argument_list ) \ |
291 | 0 | va_end( argument_list ) |
292 | | |
293 | | #elif defined( HAVE_VARARGS_H ) |
294 | | #define VARARGS( function, error, error_domain, error_code, type, argument ) \ |
295 | | function( error, error_domain, error_code, va_alist ) va_dcl |
296 | | #define VASTART( argument_list, type, name ) \ |
297 | | { type name; va_start( argument_list ); name = va_arg( argument_list, type ) |
298 | | #define VAEND( argument_list ) \ |
299 | | va_end( argument_list ); } |
300 | | |
301 | | #endif /* defined( HAVE_STDARG_H ) || defined( WINAPI ) */ |
302 | | |
303 | | /* Sets an error |
304 | | * Creates the error if necessary |
305 | | * The error domain and code are set only the first time and the error message is appended for back tracing |
306 | | */ |
307 | | void VARARGS( |
308 | | libcerror_error_set, |
309 | | libcerror_error_t **error, |
310 | | int error_domain, |
311 | | int error_code, |
312 | | const char *, |
313 | | format_string ) |
314 | 1.61M | { |
315 | 1.61M | va_list argument_list; |
316 | | |
317 | 1.61M | libcerror_internal_error_t *internal_error = NULL; |
318 | 1.61M | system_character_t *error_string = NULL; |
319 | 1.61M | system_character_t *system_format_string = NULL; |
320 | 1.61M | void *reallocation = NULL; |
321 | 1.61M | size_t error_string_size = 0; |
322 | 1.61M | size_t format_string_length = 0; |
323 | 1.61M | size_t message_size = 0; |
324 | 1.61M | size_t next_message_size = LIBCERROR_MESSAGE_INCREMENT_SIZE; |
325 | 1.61M | int message_index = 0; |
326 | 1.61M | int print_count = 0; |
327 | | |
328 | 1.61M | if( error == NULL ) |
329 | 1.61M | { |
330 | 1.61M | return; |
331 | 1.61M | } |
332 | 0 | if( format_string == NULL ) |
333 | 0 | { |
334 | 0 | return; |
335 | 0 | } |
336 | 0 | format_string_length = narrow_string_length( |
337 | 0 | format_string ); |
338 | |
|
339 | | #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) |
340 | | libcerror_error_get_system_format_string( |
341 | | format_string, |
342 | | format_string_length, |
343 | | &system_format_string ); |
344 | | |
345 | | if( system_format_string == NULL ) |
346 | | { |
347 | | return; |
348 | | } |
349 | | #else |
350 | 0 | system_format_string = (system_character_t *) format_string; |
351 | 0 | #endif |
352 | 0 | if( *error == NULL ) |
353 | 0 | { |
354 | 0 | if( libcerror_error_initialize( |
355 | 0 | error, |
356 | 0 | error_domain, |
357 | 0 | error_code ) != 1 ) |
358 | 0 | { |
359 | 0 | goto on_error; |
360 | 0 | } |
361 | 0 | } |
362 | 0 | internal_error = (libcerror_internal_error_t *) *error; |
363 | |
|
364 | 0 | if( libcerror_error_resize( |
365 | 0 | internal_error ) != 1 ) |
366 | 0 | { |
367 | 0 | goto on_error; |
368 | 0 | } |
369 | 0 | if( format_string_length > next_message_size ) |
370 | 0 | { |
371 | 0 | next_message_size = ( ( format_string_length / LIBCERROR_MESSAGE_INCREMENT_SIZE ) + 1 ) |
372 | 0 | * LIBCERROR_MESSAGE_INCREMENT_SIZE; |
373 | 0 | } |
374 | 0 | do |
375 | 0 | { |
376 | 0 | if( next_message_size >= LIBCERROR_MESSAGE_MAXIMUM_SIZE ) |
377 | 0 | { |
378 | 0 | next_message_size = LIBCERROR_MESSAGE_MAXIMUM_SIZE; |
379 | 0 | } |
380 | 0 | reallocation = memory_reallocate( |
381 | 0 | error_string, |
382 | 0 | sizeof( system_character_t ) * next_message_size ); |
383 | |
|
384 | 0 | if( reallocation == NULL ) |
385 | 0 | { |
386 | 0 | memory_free( |
387 | 0 | error_string ); |
388 | |
|
389 | 0 | goto on_error; |
390 | 0 | } |
391 | 0 | error_string = (system_character_t *) reallocation; |
392 | |
|
393 | 0 | message_size = next_message_size; |
394 | | |
395 | | /* argument_list cannot be reused in successive calls to vsnprintf |
396 | | */ |
397 | 0 | VASTART( |
398 | 0 | argument_list, |
399 | 0 | const char *, |
400 | 0 | format_string ); |
401 | |
|
402 | 0 | print_count = system_string_vsnprintf( |
403 | 0 | error_string, |
404 | 0 | message_size, |
405 | 0 | system_format_string, |
406 | 0 | argument_list ); |
407 | |
|
408 | 0 | VAEND( |
409 | 0 | argument_list ); |
410 | |
|
411 | 0 | if( print_count <= -1 ) |
412 | 0 | { |
413 | 0 | next_message_size += LIBCERROR_MESSAGE_INCREMENT_SIZE; |
414 | 0 | } |
415 | 0 | else if( ( (size_t) print_count >= message_size ) |
416 | 0 | || ( error_string[ print_count ] != (system_character_t) 0 ) ) |
417 | 0 | { |
418 | 0 | next_message_size = (size_t) ( print_count + 1 ); |
419 | 0 | print_count = -1; |
420 | 0 | } |
421 | 0 | else |
422 | 0 | { |
423 | 0 | error_string_size = (size_t) print_count + 1; |
424 | 0 | } |
425 | 0 | if( message_size >= LIBCERROR_MESSAGE_MAXIMUM_SIZE ) |
426 | 0 | { |
427 | 0 | break; |
428 | 0 | } |
429 | 0 | } |
430 | 0 | while( print_count <= -1 ); |
431 | | |
432 | 0 | if( message_size >= LIBCERROR_MESSAGE_MAXIMUM_SIZE ) |
433 | 0 | { |
434 | 0 | error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 4 ] = (system_character_t) '.'; |
435 | 0 | error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 3 ] = (system_character_t) '.'; |
436 | 0 | error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 2 ] = (system_character_t) '.'; |
437 | 0 | error_string[ LIBCERROR_MESSAGE_MAXIMUM_SIZE - 1 ] = 0; |
438 | 0 | error_string_size = (size_t) LIBCERROR_MESSAGE_MAXIMUM_SIZE; |
439 | 0 | } |
440 | 0 | message_index = internal_error->number_of_messages - 1; |
441 | |
|
442 | 0 | internal_error->messages[ message_index ] = error_string; |
443 | 0 | internal_error->sizes[ message_index ] = error_string_size; |
444 | |
|
445 | | #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) |
446 | | memory_free( |
447 | | system_format_string ); |
448 | | |
449 | | system_format_string = NULL; |
450 | | #endif |
451 | 0 | return; |
452 | | |
453 | 0 | on_error: |
454 | | #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) |
455 | | if( system_format_string != NULL ) |
456 | | { |
457 | | memory_free( |
458 | | system_format_string ); |
459 | | } |
460 | | #endif |
461 | 0 | return; |
462 | 0 | } |
463 | | |
464 | | #undef VARARGS |
465 | | #undef VASTART |
466 | | #undef VAEND |
467 | | |
468 | | /* Determines if an error equals a certain error code of a domain |
469 | | * Returns 1 if error matches or 0 if not |
470 | | */ |
471 | | int libcerror_error_matches( |
472 | | libcerror_error_t *error, |
473 | | int error_domain, |
474 | | int error_code ) |
475 | 0 | { |
476 | 0 | if( error == NULL ) |
477 | 0 | { |
478 | 0 | return( 0 ); |
479 | 0 | } |
480 | 0 | if( ( ( (libcerror_internal_error_t *) error )->domain == error_domain ) |
481 | 0 | && ( ( (libcerror_internal_error_t *) error )->code == error_code ) ) |
482 | 0 | { |
483 | 0 | return( 1 ); |
484 | 0 | } |
485 | 0 | return( 0 ); |
486 | 0 | } |
487 | | |
488 | | /* Prints a descriptive string of the error to the stream |
489 | | * Returns the number of printed characters if successful or -1 on error |
490 | | */ |
491 | | int libcerror_error_fprint( |
492 | | libcerror_error_t *error, |
493 | | FILE *stream ) |
494 | 0 | { |
495 | 0 | libcerror_internal_error_t *internal_error = NULL; |
496 | 0 | system_character_t *error_string = NULL; |
497 | 0 | int message_index = 0; |
498 | 0 | int print_count = 0; |
499 | |
|
500 | | #if defined( WINAPI ) |
501 | | const char *format_string = "%" PRIs_SYSTEM "\r\n"; |
502 | | #else |
503 | 0 | const char *format_string = "%" PRIs_SYSTEM "\n"; |
504 | 0 | #endif |
505 | |
|
506 | 0 | if( error == NULL ) |
507 | 0 | { |
508 | 0 | return( -1 ); |
509 | 0 | } |
510 | 0 | internal_error = (libcerror_internal_error_t *) error; |
511 | |
|
512 | 0 | if( internal_error->messages == NULL ) |
513 | 0 | { |
514 | 0 | return( -1 ); |
515 | 0 | } |
516 | 0 | if( stream == NULL ) |
517 | 0 | { |
518 | 0 | return( -1 ); |
519 | 0 | } |
520 | 0 | message_index = internal_error->number_of_messages - 1; |
521 | 0 | error_string = internal_error->messages[ message_index ]; |
522 | |
|
523 | 0 | if( error_string != NULL ) |
524 | 0 | { |
525 | 0 | print_count = fprintf( |
526 | 0 | stream, |
527 | 0 | format_string, |
528 | 0 | error_string ); |
529 | |
|
530 | 0 | if( print_count <= -1 ) |
531 | 0 | { |
532 | 0 | return( -1 ); |
533 | 0 | } |
534 | 0 | } |
535 | 0 | return( print_count ); |
536 | 0 | } |
537 | | |
538 | | /* Prints a descriptive string of the error to the string |
539 | | * The end-of-string character is not included in the return value |
540 | | * Returns the number of printed characters if successful or -1 on error |
541 | | */ |
542 | | int libcerror_error_sprint( |
543 | | libcerror_error_t *error, |
544 | | char *string, |
545 | | size_t size ) |
546 | 0 | { |
547 | 0 | libcerror_internal_error_t *internal_error = NULL; |
548 | 0 | system_character_t *error_string = NULL; |
549 | 0 | size_t message_index = 0; |
550 | 0 | size_t print_count = 0; |
551 | |
|
552 | 0 | #if !defined( HAVE_WIDE_SYSTEM_CHARACTER ) |
553 | 0 | size_t error_string_size = 0; |
554 | 0 | #endif |
555 | |
|
556 | 0 | if( error == NULL ) |
557 | 0 | { |
558 | 0 | return( -1 ); |
559 | 0 | } |
560 | 0 | internal_error = (libcerror_internal_error_t *) error; |
561 | |
|
562 | 0 | if( internal_error->messages == NULL ) |
563 | 0 | { |
564 | 0 | return( -1 ); |
565 | 0 | } |
566 | 0 | if( internal_error->sizes == NULL ) |
567 | 0 | { |
568 | 0 | return( -1 ); |
569 | 0 | } |
570 | 0 | if( string == NULL ) |
571 | 0 | { |
572 | 0 | return( -1 ); |
573 | 0 | } |
574 | 0 | #if INT_MAX < SSIZE_MAX |
575 | 0 | if( size > (size_t) INT_MAX ) |
576 | | #else |
577 | | if( size > (size_t) SSIZE_MAX ) |
578 | | #endif |
579 | 0 | { |
580 | 0 | return( -1 ); |
581 | 0 | } |
582 | 0 | message_index = internal_error->number_of_messages - 1; |
583 | 0 | error_string = internal_error->messages[ message_index ]; |
584 | |
|
585 | 0 | if( error_string != NULL ) |
586 | 0 | { |
587 | | #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) |
588 | | #if defined( _MSC_VER ) |
589 | | if( wcstombs_s( |
590 | | &print_count, |
591 | | string, |
592 | | size, |
593 | | error_string, |
594 | | _TRUNCATE ) != 0 ) |
595 | | { |
596 | | return( -1 ); |
597 | | } |
598 | | #else |
599 | | print_count = wcstombs( |
600 | | string, |
601 | | error_string, |
602 | | size ); |
603 | | |
604 | | if( print_count == (size_t) -1 ) |
605 | | { |
606 | | return( -1 ); |
607 | | } |
608 | | #endif /* defined( _MSC_VER ) */ |
609 | | |
610 | | if( print_count >= size ) |
611 | | { |
612 | | return( -1 ); |
613 | | } |
614 | | #else |
615 | 0 | error_string_size = internal_error->sizes[ message_index ]; |
616 | |
|
617 | 0 | if( size < ( error_string_size + 1 ) ) |
618 | 0 | { |
619 | 0 | return( -1 ); |
620 | 0 | } |
621 | 0 | if( narrow_string_copy( |
622 | 0 | string, |
623 | 0 | error_string, |
624 | 0 | error_string_size ) == NULL ) |
625 | 0 | { |
626 | 0 | return( -1 ); |
627 | 0 | } |
628 | 0 | print_count = error_string_size; |
629 | |
|
630 | 0 | #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */ |
631 | 0 | } |
632 | 0 | if( print_count > (size_t) INT_MAX ) |
633 | 0 | { |
634 | 0 | return( -1 ); |
635 | 0 | } |
636 | 0 | return( (int) print_count ); |
637 | 0 | } |
638 | | |
639 | | /* Prints a backtrace of the error to the stream |
640 | | * Returns the number of printed characters if successful or -1 on error |
641 | | */ |
642 | | int libcerror_error_backtrace_fprint( |
643 | | libcerror_error_t *error, |
644 | | FILE *stream ) |
645 | 0 | { |
646 | 0 | libcerror_internal_error_t *internal_error = NULL; |
647 | 0 | system_character_t *error_string = NULL; |
648 | 0 | int message_index = 0; |
649 | 0 | int print_count = 0; |
650 | 0 | int total_print_count = 0; |
651 | |
|
652 | | #if defined( WINAPI ) |
653 | | const char *format_string = "%" PRIs_SYSTEM "\r\n"; |
654 | | #else |
655 | 0 | const char *format_string = "%" PRIs_SYSTEM "\n"; |
656 | 0 | #endif |
657 | |
|
658 | 0 | if( error == NULL ) |
659 | 0 | { |
660 | 0 | return( -1 ); |
661 | 0 | } |
662 | 0 | internal_error = (libcerror_internal_error_t *) error; |
663 | |
|
664 | 0 | if( internal_error->messages == NULL ) |
665 | 0 | { |
666 | 0 | return( -1 ); |
667 | 0 | } |
668 | 0 | if( stream == NULL ) |
669 | 0 | { |
670 | 0 | return( -1 ); |
671 | 0 | } |
672 | 0 | for( message_index = 0; |
673 | 0 | message_index < internal_error->number_of_messages; |
674 | 0 | message_index++ ) |
675 | 0 | { |
676 | 0 | error_string = internal_error->messages[ message_index ]; |
677 | |
|
678 | 0 | if( error_string != NULL ) |
679 | 0 | { |
680 | 0 | print_count = fprintf( |
681 | 0 | stream, |
682 | 0 | format_string, |
683 | 0 | error_string ); |
684 | |
|
685 | 0 | if( print_count <= -1 ) |
686 | 0 | { |
687 | 0 | return( -1 ); |
688 | 0 | } |
689 | 0 | total_print_count += print_count; |
690 | 0 | } |
691 | 0 | } |
692 | 0 | return( total_print_count ); |
693 | 0 | } |
694 | | |
695 | | /* Prints a backtrace of the error to the string |
696 | | * The end-of-string character is not included in the return value |
697 | | * Returns the number of printed characters if successful or -1 on error |
698 | | */ |
699 | | int libcerror_error_backtrace_sprint( |
700 | | libcerror_error_t *error, |
701 | | char *string, |
702 | | size_t size ) |
703 | 0 | { |
704 | 0 | libcerror_internal_error_t *internal_error = NULL; |
705 | 0 | system_character_t *error_string = NULL; |
706 | 0 | size_t string_index = 0; |
707 | 0 | int message_index = 0; |
708 | |
|
709 | | #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) |
710 | | size_t print_count = 0; |
711 | | #else |
712 | 0 | size_t error_string_size = 0; |
713 | 0 | #endif |
714 | |
|
715 | 0 | if( error == NULL ) |
716 | 0 | { |
717 | 0 | return( -1 ); |
718 | 0 | } |
719 | 0 | internal_error = (libcerror_internal_error_t *) error; |
720 | |
|
721 | 0 | if( internal_error->messages == NULL ) |
722 | 0 | { |
723 | 0 | return( -1 ); |
724 | 0 | } |
725 | 0 | if( internal_error->sizes == NULL ) |
726 | 0 | { |
727 | 0 | return( -1 ); |
728 | 0 | } |
729 | 0 | if( string == NULL ) |
730 | 0 | { |
731 | 0 | return( -1 ); |
732 | 0 | } |
733 | 0 | #if INT_MAX < SSIZE_MAX |
734 | 0 | if( size > (size_t) INT_MAX ) |
735 | | #else |
736 | | if( size > (size_t) SSIZE_MAX ) |
737 | | #endif |
738 | 0 | { |
739 | 0 | return( -1 ); |
740 | 0 | } |
741 | 0 | for( message_index = 0; |
742 | 0 | message_index < internal_error->number_of_messages; |
743 | 0 | message_index++ ) |
744 | 0 | { |
745 | 0 | error_string = internal_error->messages[ message_index ]; |
746 | |
|
747 | 0 | if( error_string != NULL ) |
748 | 0 | { |
749 | 0 | if( string_index > 0 ) |
750 | 0 | { |
751 | | #if defined( WINAPI ) |
752 | | if( ( string_index + 2 ) >= size ) |
753 | | { |
754 | | return( -1 ); |
755 | | } |
756 | | string[ string_index++ ] = (system_character_t) '\r'; |
757 | | #else |
758 | 0 | if( ( string_index + 1 ) >= size ) |
759 | 0 | { |
760 | 0 | return( -1 ); |
761 | 0 | } |
762 | 0 | #endif /* defined( WINAPI ) */ |
763 | | |
764 | 0 | string[ string_index++ ] = (system_character_t) '\n'; |
765 | 0 | string[ string_index ] = (system_character_t) 0; |
766 | 0 | } |
767 | | #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) |
768 | | #if defined( _MSC_VER ) |
769 | | if( wcstombs_s( |
770 | | &print_count, |
771 | | &( string[ string_index ] ), |
772 | | size - string_index, |
773 | | error_string, |
774 | | _TRUNCATE ) != 0 ) |
775 | | { |
776 | | return( -1 ); |
777 | | } |
778 | | #else |
779 | | print_count = wcstombs( |
780 | | &( string[ string_index ] ), |
781 | | error_string, |
782 | | size - string_index ); |
783 | | |
784 | | if( print_count == (size_t) -1 ) |
785 | | { |
786 | | return( -1 ); |
787 | | } |
788 | | #endif /*defined( _MSC_VER ) */ |
789 | | |
790 | | string_index += print_count; |
791 | | |
792 | | if( string_index >= size ) |
793 | | { |
794 | | return( -1 ); |
795 | | } |
796 | | if( string[ string_index - 1 ] == 0 ) |
797 | | { |
798 | | string_index--; |
799 | | } |
800 | | #else |
801 | 0 | error_string_size = internal_error->sizes[ message_index ]; |
802 | |
|
803 | 0 | if( size < ( string_index + error_string_size + 1 ) ) |
804 | 0 | { |
805 | 0 | return( -1 ); |
806 | 0 | } |
807 | 0 | if( narrow_string_copy( |
808 | 0 | &( string[ string_index ] ), |
809 | 0 | error_string, |
810 | 0 | error_string_size ) == NULL ) |
811 | 0 | { |
812 | 0 | return( -1 ); |
813 | 0 | } |
814 | 0 | string_index += error_string_size - 1; |
815 | |
|
816 | 0 | #endif /* defined( HAVE_WIDE_SYSTEM_CHARACTER ) */ |
817 | 0 | } |
818 | 0 | } |
819 | 0 | string_index++; |
820 | |
|
821 | 0 | if( string_index > (size_t) INT_MAX ) |
822 | 0 | { |
823 | 0 | return( -1 ); |
824 | 0 | } |
825 | 0 | return( (int) string_index ); |
826 | 0 | } |
827 | | |