aboutsummaryrefslogblamecommitdiffstats
path: root/set_error.c
blob: e7a16ac3b4988cd27429ec9bed1ab1fa2ead655b (plain) (tree)
1
2
3
4
5
6
7
8
9






                                                                                                                     
                                                  
                                     
                                        
                           
 








                                                           










                                                                                              

















                                                                                                



                                              





                                                            


                                                               
/* See LICENSE file for copyright and license details. */
#include "internal.h"


void
liberror_set_error(const char description[256], const char source[64], const char code_group[64], long long int code)
{
	struct liberror_error *cause = NULL, *old;
	struct liberror_error *error;
	int have_cause = 0, saved_errno;
	const char *errstr;

	old = liberror_get_error();
	if (old) {
		have_cause = 1;
		saved_errno = errno;
		cause = malloc(sizeof(*cause));
		errno = saved_errno;
		if (cause)
			memcpy(cause, old, sizeof(*cause));
	}

	error = &liberror_error_;
	liberror_have_error_ = 1;

	memset(error, 0, sizeof(*error));

	if (*description) {
		stpcpy(error->description, description);
	} else if (!strcmp(code_group, "errno")) {
		if (code >= (long long int)INT_MIN && code <= (long long int)INT_MAX)
			strerror_r((int)code, error->description, sizeof(error->description));
	} else if (!strcmp(code_group, "h_errno")) {
		if (code >= (long long int)INT_MIN && code <= (long long int)INT_MAX) {
			saved_errno = errno;
			errstr = hstrerror(code);
			if (errstr)
				strncpy(error->description, errstr, sizeof(error->description));
			errno = saved_errno;
		}
	} else if (!strcmp(code_group, "addrinfo")) {
		if (code == (long long int)EAI_SYSTEM) {
			strerror_r(errno, error->description, sizeof(error->description));
		} else if (code >= (long long int)INT_MIN && code <= (long long int)INT_MAX) {
			saved_errno = errno;
			errstr = gai_strerror(code);
			if (errstr)
				strncpy(error->description, errstr, sizeof(error->description));
			errno = saved_errno;
		}
	}
	stpcpy(error->source, source);
	stpcpy(error->code_group, code_group);
	error->code = code;
	if (liberror_saved_backtrace) {
		error->backtrace = liberror_saved_backtrace;
		liberror_saved_backtrace = NULL;
	} else {
		liberror_save_backtrace(error);
	}
	error->cause = cause;
	error->failed_to_allocate_cause = have_cause && !cause;
}