1 // Copyright 2012 Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors
14 // may be used to endorse or promote products derived from this software
15 // without specific prior written permission.
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 /// Generic hook to format an error that does not have a format callback.
41 /// \param error Error for which to generate a message.
42 /// \param output_buffer Buffer to hold the generated message.
43 /// \param output_size Length of output_buffer.
45 generic_format_callback(const kyua_error_t error
, char* const output_buffer
,
48 assert(error
!= NULL
);
49 return snprintf(output_buffer
, output_size
, "Error '%s'", error
->type_name
);
53 /// Initializes an error object.
55 /// \param error Error for which to generate a message.
56 /// \param type_name Name of the error type.
57 /// \param data Opaque data that belongs to the error, for usage by
58 /// error-specific methods like format_callback.
59 /// \param data_size Size of the opaque data object.
60 /// \param format_callback Type-specific method to generate a user
61 /// representation of the error.
63 /// \return True if the initialization succeeds; false otherwise. If
64 /// false, the error object passed in has not been modified.
66 error_init(kyua_error_t
const error
, const char* const type_name
,
67 void* const data
, const size_t data_size
,
68 const kyua_error_format_callback format_callback
)
70 assert(data
!= NULL
|| data_size
== 0);
71 assert(data_size
!= 0 || data
== NULL
);
77 error
->needs_free
= false;
80 void* new_data
= malloc(data_size
);
81 if (new_data
== NULL
) {
84 memcpy(new_data
, data
, data_size
);
85 error
->data
= new_data
;
91 error
->type_name
= type_name
;
92 error
->format_callback
= (format_callback
== NULL
) ?
93 generic_format_callback
: format_callback
;
100 /// Allocates and initializes a new error.
102 /// \param type_name Name of the error type.
103 /// \param data Opaque data that belongs to the error, for usage by
104 /// error-specific methods like format_callback.
105 /// \param data_size Size of the opaque data object.
106 /// \param format_callback Type-specific method to generate a user
107 /// representation of the error.
109 /// \return The newly initialized error, or an out of memory error.
111 kyua_error_new(const char* const type_name
, void* const data
,
112 const size_t data_size
,
113 const kyua_error_format_callback format_callback
)
115 assert(data
!= NULL
|| data_size
== 0);
116 assert(data_size
!= 0 || data
== NULL
);
118 kyua_error_t error
= malloc(sizeof(struct kyua_error
));
120 error
= kyua_oom_error_new();
122 if (!error_init(error
, type_name
, data
, data_size
, format_callback
)) {
124 error
= kyua_oom_error_new();
126 error
->needs_free
= true;
130 assert(error
!= NULL
);
135 /// Releases an error.
137 /// \param error The error object to release.
139 kyua_error_free(kyua_error_t error
)
141 assert(error
!= NULL
);
143 const bool needs_free
= error
->needs_free
;
145 if (error
->data
!= NULL
)
152 /// Returns the "most important" of two errors.
154 /// "Most important" is defined as: the primary error is returned if set,
155 /// otherwise the secondary error is returned.
157 /// It is the responsibility of the caller to free the *resulting* error of this
158 /// call. The original errors passed in should not be consulted any longer,
159 /// because it is impossible to know which one was chosen.
161 /// \param primary The primary error to compare.
162 /// \param [in,out] secondary The secondary error to compare. This is freed if
163 /// the primary error is set.
165 /// \return Either primary or secondary.
167 kyua_error_subsume(kyua_error_t primary
, kyua_error_t secondary
)
169 if (kyua_error_is_set(primary
)) {
170 if (kyua_error_is_set(secondary
))
171 kyua_error_free(secondary
);
179 /// Constructor for a no-error condition.
181 /// \return Opaque representation of a no-error condition.
189 /// Checks if the given error object represents an error or not.
191 /// \param error The error to check.
193 /// \return True if the error is set.
195 kyua_error_is_set(const kyua_error_t error
)
197 return error
!= NULL
;
201 /// Checks if the given error object is of a specific type.
203 /// \pre The error must be set.
205 /// \param error The error to check.
206 /// \param type_name The type of the expected error.
208 /// \return True if the error is of type type_name.
210 kyua_error_is_type(const kyua_error_t error
, const char* type_name
)
212 assert(error
!= NULL
);
214 return strcmp(error
->type_name
, type_name
) == 0;
218 /// Returns a pointer to the error-specific data.
220 /// \pre The error must be set.
222 /// \param error The error to query.
224 /// \return An opaque pointer to the error data. This should only be
225 /// dereferenced by the methods of the error class that created it.
227 kyua_error_data(const kyua_error_t error
)
229 assert(error
!= NULL
);
235 /// Generates a user-friendly representation of the error.
237 /// This cannot fail, but it is possible that the generated error does not
238 /// fit in the provided buffer.
240 /// \pre The error must be set.
242 /// \param error Error for which to generate a message.
243 /// \param output_buffer Buffer to hold the generated message.
244 /// \param output_size Length of output_buffer.
246 /// \return The number of bytes written to output_buffer, or a negative value if
247 /// there was an error.
249 kyua_error_format(const kyua_error_t error
, char* const output_buffer
,
250 const size_t output_size
)
252 assert(kyua_error_is_set(error
));
253 return error
->format_callback(error
, output_buffer
, output_size
);
257 /// Formats a string and appends an error code to it.
259 /// \param error Error to append to the formatted message.
260 /// \param format User-specified message, as a formatting string.
261 /// \param ap List of arguments to the format string.
262 /// \param [out] output_buffer Buffer into which to write the message.
263 /// \param output_size Length of the output_buffer.
265 /// \return The number of bytes written to output_buffer, or a negative value if
266 /// there was an error.
268 format_user_message(const kyua_error_t error
, const char* format
, va_list ap
,
269 char* const output_buffer
, const size_t output_size
)
271 assert(kyua_error_is_set(error
));
275 size_t written
= vsnprintf(output_buffer
, output_size
, format
, ap2
);
277 if (written
>= output_size
)
280 written
+= snprintf(output_buffer
+ written
, output_size
- written
, ": ");
281 if (written
>= output_size
)
284 return kyua_error_format(error
, output_buffer
+ written
,
285 output_size
- written
);
289 /// Version of err(3) that works with kyua_error_t objects.
291 /// \param exit_code Error code with which to terminate the execution.
292 /// \param error Error to append to the output.
293 /// \param format User-specified message, as a formatting string.
294 /// \param ... Positional arguments to the format string.
296 /// \post Execution terminates with exit_code.
298 kyua_error_err(const int exit_code
, const kyua_error_t error
,
299 const char* format
, ...)
304 va_start(ap
, format
);
305 (void)format_user_message(error
, format
, ap
, buffer
, sizeof(buffer
));
307 kyua_error_free(error
);
309 errx(exit_code
, "%s", buffer
);
313 /// Writes an error to a file stream.
315 /// \param stream Stream to which to write the message.
316 /// \param error Error to append to the output. This is not released.
317 /// \param format User-specified message, as a formatting string.
318 /// \param ... Positional arguments to the format string.
320 kyua_error_fprintf(FILE* stream
, const kyua_error_t error
,
321 const char* format
, ...)
326 va_start(ap
, format
);
327 (void)format_user_message(error
, format
, ap
, buffer
, sizeof(buffer
));
330 fprintf(stream
, "%s", buffer
);
334 /// Version of warn(3) that works with kyua_error_t objects.
336 /// \param error Error to append to the output. This is not released.
337 /// \param format User-specified message, as a formatting string.
338 /// \param ... Positional arguments to the format string.
340 kyua_error_warn(const kyua_error_t error
, const char* format
, ...)
345 va_start(ap
, format
);
346 (void)format_user_message(error
, format
, ap
, buffer
, sizeof(buffer
));
353 /// Name of an generic error type.
354 const char* const kyua_generic_error_type
= "generic";
357 /// Generates a user-friendly representation of the error.
359 /// \pre The error must be set.
361 /// \param error Error for which to generate a message.
362 /// \param output_buffer Buffer to hold the generated message.
363 /// \param output_size Length of output_buffer.
365 /// \return The number of bytes written to output_buffer, or a negative value if
366 /// there was an error.
368 generic_format(const kyua_error_t error
, char* const output_buffer
,
369 const size_t output_size
)
371 assert(kyua_error_is_type(error
, kyua_generic_error_type
));
373 const char* message
= kyua_error_data(error
);
374 return snprintf(output_buffer
, output_size
, "%s", message
);
378 /// Constructs a new generic error.
380 /// \param message Textual description of the problem.
381 /// \param ... Positional arguments for the description.
383 /// \return The generated error.
385 kyua_generic_error_new(const char* message
, ...)
387 char formatted
[1024];
390 va_start(ap
, message
);
391 (void)vsnprintf(formatted
, sizeof(formatted
), message
, ap
);
394 return kyua_error_new(kyua_generic_error_type
, formatted
, sizeof(formatted
),
399 /// Name of a libc type.
400 const char* const kyua_libc_error_type
= "libc";
403 /// Representation of a libc error.
404 struct libc_error_data
{
405 /// Value of the errno captured during the error creation.
408 /// Explanation of the problem that lead to the error.
409 char description
[4096];
411 /// Shorthand for a libc_error_data structure.
412 typedef struct libc_error_data libc_error_data_t
;
415 /// Generates a user-friendly representation of the error.
417 /// \pre The error must be set.
419 /// \param error Error for which to generate a message.
420 /// \param output_buffer Buffer to hold the generated message.
421 /// \param output_size Length of output_buffer.
423 /// \return The number of bytes written to output_buffer, or a negative value if
424 /// there was an error.
426 libc_format(const kyua_error_t error
, char* const output_buffer
,
427 const size_t output_size
)
429 assert(kyua_error_is_type(error
, kyua_libc_error_type
));
431 const libc_error_data_t
* data
= kyua_error_data(error
);
432 return snprintf(output_buffer
, output_size
, "%s: %s", data
->description
,
433 strerror(data
->original_errno
));
437 /// Constructs a new libc error.
439 /// \param original_errno libc error code for this error.
440 /// \param description Textual description of the problem.
441 /// \param ... Positional arguments for the description.
443 /// \return The generated error.
445 kyua_libc_error_new(const int original_errno
, const char* description
, ...)
449 const size_t data_size
= sizeof(libc_error_data_t
);
450 libc_error_data_t
* data
= (libc_error_data_t
*)malloc(data_size
);
452 return kyua_oom_error_new();
454 data
->original_errno
= original_errno
;
455 va_start(ap
, description
);
456 (void)vsnprintf(data
->description
, sizeof(data
->description
),
460 return kyua_error_new(kyua_libc_error_type
, data
, data_size
, libc_format
);
464 /// Extracts the original errno of a libc error.
466 /// \pre error must have been constructed by kyua_libc_error_new.
468 /// \param error The error object to access.
470 /// \return The libc error code.
472 kyua_libc_error_errno(const kyua_error_t error
)
474 assert(kyua_error_is_type(error
, kyua_libc_error_type
));
476 const struct libc_error_data
* data
= kyua_error_data(error
);
477 return data
->original_errno
;
481 /// Name of an OOM type.
482 const char* const kyua_oom_error_type
= "oom";
485 /// Data of an out of memory error.
487 /// All error types are allocated in dynamic memory. However, doing so for
488 /// an out of memory error is not possible because, when we are out of
489 /// memory, we probably cannot allocate more memory to generate an error.
490 /// Therefore, we just keep a single static instance of the out of memory
491 /// error around all the time.
492 static struct kyua_error oom_error
;
495 /// Generates a user-friendly representation of the error.
497 /// \pre The error must be set.
499 /// \param error Error for which to generate a message.
500 /// \param output_buffer Buffer to hold the generated message.
501 /// \param output_size Length of output_buffer.
503 /// \return The number of bytes written to output_buffer, or a negative value if
504 /// there was an error.
506 oom_format(const kyua_error_t error
, char* const output_buffer
,
507 const size_t output_size
)
509 assert(kyua_error_is_type(error
, kyua_oom_error_type
));
511 return snprintf(output_buffer
, output_size
, "Not enough memory");
515 /// Constructs a new out-of-memory error.
517 /// This will always succeed because we just return a reference to the
518 /// statically-allocated oom_error.
520 /// \return An error representing an out of memory condition.
522 kyua_oom_error_new(void)
524 // This is idempotent; no need to ensure that we call it only once.
525 #if defined(__minix) && !defined(NDEBUG)
527 #endif /* defined(__minix) && !defined(NDEBUG) */
528 error_init(&oom_error
, kyua_oom_error_type
, NULL
, 0, oom_format
);
535 /// Name of an usage error type.
536 const char* const kyua_usage_error_type
= "usage";
539 /// Generates a user-friendly representation of the error.
541 /// \pre The error must be set.
543 /// \param error Error for which to generate a message.
544 /// \param output_buffer Buffer to hold the generated message.
545 /// \param output_size Length of output_buffer.
547 /// \return The number of bytes written to output_buffer, or a negative value if
548 /// there was an error.
550 usage_format(const kyua_error_t error
, char* const output_buffer
,
551 const size_t output_size
)
553 assert(kyua_error_is_type(error
, kyua_usage_error_type
));
555 const char* message
= kyua_error_data(error
);
556 return snprintf(output_buffer
, output_size
, "%s", message
);
560 /// Constructs a new usage error.
562 /// \param message Textual description of the problem.
563 /// \param ... Positional arguments for the description.
565 /// \return The generated error.
567 kyua_usage_error_new(const char* message
, ...)
569 char formatted
[1024];
572 va_start(ap
, message
);
573 (void)vsnprintf(formatted
, sizeof(formatted
), message
, ap
);
576 return kyua_error_new(kyua_usage_error_type
, formatted
, sizeof(formatted
),