diff options
Diffstat (limited to '')
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | internal.h | 13 | ||||
-rw-r--r-- | liberror-libc.h | 2 | ||||
-rw-r--r-- | liberror.h | 236 | ||||
-rw-r--r-- | set_error_one_file.c | 17 | ||||
-rw-r--r-- | shutdown.c | 4 |
6 files changed, 269 insertions, 5 deletions
@@ -15,6 +15,7 @@ LIB_VERSION = $(LIB_MAJOR).$(LIB_MINOR) HDR =\ liberror-libc.h\ + liberror.h\ internal.h OBJ =\ @@ -24,6 +25,7 @@ OBJ =\ llabs.o\ pipe.o\ putenv.o\ + set_error_one_file.o\ setenv.o\ shutdown.o\ unsetenv.o @@ -1,5 +1,6 @@ /* See LICENSE file for copyright and license details. */ #include "liberror-libc.h" +#include "liberror.h" #include <sys/socket.h> #include <errno.h> @@ -9,5 +10,13 @@ #include <unistd.h> -void liberror_set_error(const char[256], const char[64], const char[64], long long int); -void liberror_set_error_errno(const char[256], const char[64], int); +#if defined(__GNUC__) +# define GCC_ATTRIBUTES(...) __attribute__((__VA_ARGS__)) +#else +# define GCC_ATTRIBUTES(...) +#endif + +#define HIDDEN GCC_ATTRIBUTES(__visibility__("hidden")) + + +HIDDEN void liberror_libc_set_error_one_file(const char[256], const char[64], const char *, int, const char *); diff --git a/liberror-libc.h b/liberror-libc.h index 0a8634c..fd67f3b 100644 --- a/liberror-libc.h +++ b/liberror-libc.h @@ -12,7 +12,7 @@ long long int liberror_llabs(long long int); int liberror_pipe(int[2]); int liberror_putenv(char *); int liberror_setenv(const char *, const char *, int); -int liberror_shutdown(int, int); +int liberror_shutdown(int, int, const char *); int liberror_unsetenv(const char *); diff --git a/liberror.h b/liberror.h new file mode 100644 index 0000000..508dbac --- /dev/null +++ b/liberror.h @@ -0,0 +1,236 @@ +/* See LICENSE file for copyright and license details. */ +#ifndef LIBERROR_H +#define LIBERROR_H + +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> + + +/** + * Opaque backtrace structure + */ +struct liberror_backtrace; + +/** + * Value that specifies which feild in a + * `union liberror_details` that is used + */ +enum liberror_details_type { + LIBERROR_DETAILS_NONE, + LIBERROR_DETAILS_USER, + LIBERROR_DETAILS_ONE_FILE, + LIBERROR_DETAILS_TWO_FILES +}; + +/** + * Error details + */ +union liberror_details { + /** + * For `LIBERROR_DETAILS_USER` + */ + struct { + const char *library; + void *data; + void (*free_data)(void *); + void *(*copy_data)(void *); + } user; + + /** + * For `LIBERROR_DETAILS_ONE_FILE` + */ + struct { + int fd; + char *name; + const char *role; + } one_file; + + /** + * For `LIBERROR_DETAILS_TWO_FILES` + */ + struct { + int fd1; + int fd2; + char *name1; + char *name2; + const char *role1; + const char *role2; + } two_files; +}; + +/** + * Error structure + */ +struct liberror_error { + /** + * Backtrace for the error, `NULL` if the it could + * not be allocated or if the program is not linked + * with `-lerror-backtrace` + */ + struct liberror_backtrace *backtrace; + + /** + * Description of the error + */ + char description[256]; + + /** + * The function that failed + */ + char source[64]; + + /** + * Name of error code group, for normal `errno` + * errors this is "error", for getaddrinfo(3) errors + * this is "addrinfo", for custom errors it is the + * name of the library or application + */ + char code_group[64]; + + /** + * The error code + */ + long long int code; + + /** + * The error that caused this error, `NULL` if + * none or it could not be allocated (if and only + * if so, `.failed_to_allocate_cause` will be set + * to a non-zero value, specifically 1) + */ + struct liberror_error *cause; + + /** + * Whether allocation of `.cause` failed + */ + int failed_to_allocate_cause; + + /** + * Whether the error is physically allocated + */ + int dynamically_allocated; + + /** + * Which value in `.details` that is used + */ + enum liberror_details_type details_type; + + /** + * Error detail + */ + union liberror_details details; +}; + + +/** + * Get the current error for the thread + * + * @return The current error, `NULL` if none + */ +struct liberror_error *liberror_get_error(void); + +/** + * Create a copy of an error + * + * This function will only fail of enough memory + * cannot be allocated, however `errno` will not + * be changed + * + * @param error The error to copy + * @return Copy of the error, `NULL` on failure + */ +struct liberror_error *liberror_copy_error(struct liberror_error *); + +/** + * Deallocate and error and the error stored as + * its cause (recursively) + * + * @param error The error to deallocate + */ +void liberror_free_error(struct liberror_error *); + +/** + * Deallocate the current error for the thread + * and reset the error for the thread + * + * This function shall be called after handling + * the error + */ +void liberror_reset_error(void); + +/** + * Print the backtrace of an error + * + * If the backtrace could not be allocated, + * nothing will be printed + * + * This function will never change `errno` + * + * Note: this library does not actually save + * a backtrace, `-lerror-backtrace` is needed + * for that functionallity (it will replace + * some things in this library, so no other + * action is required) + * + * @param error The error + * @param fp The file to print the backtrace to + * @param indent Text to print at the beginning of each line + */ +void liberror_print_backtrace(struct liberror_error *, FILE *, const char *); + +/** + * Set the current error for the thread + * + * If the thread already has an error saved, + * it will be stored as the cause of the new + * error + * + * @param description Description of the error, empty for default description + * @param source The function that failed + * @param code_group Name of error code group, for normal `errno` errors + * this shall be "error", for getaddrinfo(3) errors + * this shall be "addrinfo", for custom errors it shall + * be the name of the library or application + * @param code The error code + */ +void liberror_set_error(const char[256], const char[64], const char[64], long long int); + +/** + * Set the current error for the thread + * + * This function can be used as an alternative + * to `liberror_set_error` for `errno` errors + * + * If the thread already has an error saved, + * it will be stored as the cause of the new + * error + * + * @param description Description of the error, empty for default description + * @param source The function that failed + * @param code The `errno` value + */ +void liberror_set_error_errno(const char[256], const char[64], int); + +/** + * The an error, its backtrace, and its + * cause (recursively) + * + * If `error` is `NULL` and the thread does + * not have any error set, this function + * will not do anything + * + * @param error The error, the thread's current error if `NULL` + * @param fp Output stream, standard error if `NULL` + * @param reset Whether `error` shall be deallocated, `error` + * is null and `reset` is non-zero, the thread's + * error will be reset + * @param prefix Prefix for each printed line, ": " will be + * appended to this prefix; if `NULL` or empty, + * no prefix is used; this should normally be + * `argv[0]` from the main() function + */ +void liberror_print_error(struct liberror_error *, FILE *, int, const char *); + + +#endif diff --git a/set_error_one_file.c b/set_error_one_file.c new file mode 100644 index 0000000..f8061f8 --- /dev/null +++ b/set_error_one_file.c @@ -0,0 +1,17 @@ +/* See LICENSE file for copyright and license details. */ +#include "internal.h" + + +void +liberror_libc_set_error_one_file(const char desc[256], const char source[64], const char *frole, int fd, const char *fname) +{ + struct liberror_error *error; + int saved_errno = errno; + liberror_set_error_errno(desc, source, saved_errno); + error = liberror_get_error(); + error->details_type = LIBERROR_DETAILS_ONE_FILE; + error->details.one_file.fd = fd; + error->details.one_file.name = fname ? strdup(fname) : NULL; + error->details.one_file.role = frole; + errno = saved_errno; +} @@ -3,7 +3,7 @@ int -liberror_shutdown(int fd, int how) +liberror_shutdown(int fd, int how, const char *fname) { const char *desc; if (!shutdown(fd, how)) @@ -28,6 +28,6 @@ liberror_shutdown(int fd, int how) desc = ""; break; } - liberror_set_error_errno(desc, "shutdown", errno); + liberror_libc_set_error_one_file(desc, "shutdown", "Socket file", fd, fname); return -1; } |