Blame src/errors.c

Packit ae9e2a
/*
Packit ae9e2a
 * Copyright (C) the libgit2 contributors. All rights reserved.
Packit ae9e2a
 *
Packit ae9e2a
 * This file is part of libgit2, distributed under the GNU GPL v2 with
Packit ae9e2a
 * a Linking Exception. For full terms see the included COPYING file.
Packit ae9e2a
 */
Packit ae9e2a
#include "common.h"
Packit ae9e2a
#include "global.h"
Packit ae9e2a
#include "posix.h"
Packit ae9e2a
#include "buffer.h"
Packit ae9e2a
Packit ae9e2a
/********************************************
Packit ae9e2a
 * New error handling
Packit ae9e2a
 ********************************************/
Packit ae9e2a
Packit ae9e2a
static git_error g_git_oom_error = {
Packit ae9e2a
	"Out of memory",
Packit ae9e2a
	GITERR_NOMEMORY
Packit ae9e2a
};
Packit ae9e2a
Packit ae9e2a
static void set_error_from_buffer(int error_class)
Packit ae9e2a
{
Packit ae9e2a
	git_error *error = &GIT_GLOBAL->error_t;
Packit ae9e2a
	git_buf *buf = &GIT_GLOBAL->error_buf;
Packit ae9e2a
Packit ae9e2a
	error->message = buf->ptr;
Packit ae9e2a
	error->klass = error_class;
Packit ae9e2a
Packit ae9e2a
	GIT_GLOBAL->last_error = error;
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
static void set_error(int error_class, char *string)
Packit ae9e2a
{
Packit ae9e2a
	git_buf *buf = &GIT_GLOBAL->error_buf;
Packit ae9e2a
Packit ae9e2a
	git_buf_clear(buf);
Packit ae9e2a
	if (string) {
Packit ae9e2a
		git_buf_puts(buf, string);
Packit ae9e2a
		git__free(string);
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	set_error_from_buffer(error_class);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
void giterr_set_oom(void)
Packit ae9e2a
{
Packit ae9e2a
	GIT_GLOBAL->last_error = &g_git_oom_error;
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
void giterr_set(int error_class, const char *string, ...)
Packit ae9e2a
{
Packit ae9e2a
	va_list arglist;
Packit ae9e2a
#ifdef GIT_WIN32
Packit ae9e2a
	DWORD win32_error_code = (error_class == GITERR_OS) ? GetLastError() : 0;
Packit ae9e2a
#endif
Packit ae9e2a
	int error_code = (error_class == GITERR_OS) ? errno : 0;
Packit ae9e2a
	git_buf *buf = &GIT_GLOBAL->error_buf;
Packit ae9e2a
Packit ae9e2a
	git_buf_clear(buf);
Packit ae9e2a
	if (string) {
Packit ae9e2a
		va_start(arglist, string);
Packit ae9e2a
		git_buf_vprintf(buf, string, arglist);
Packit ae9e2a
		va_end(arglist);
Packit ae9e2a
Packit ae9e2a
		if (error_class == GITERR_OS)
Packit ae9e2a
			git_buf_PUTS(buf, ": ");
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	if (error_class == GITERR_OS) {
Packit ae9e2a
#ifdef GIT_WIN32
Packit ae9e2a
		char * win32_error = git_win32_get_error_message(win32_error_code);
Packit ae9e2a
		if (win32_error) {
Packit ae9e2a
			git_buf_puts(buf, win32_error);
Packit ae9e2a
			git__free(win32_error);
Packit ae9e2a
Packit ae9e2a
			SetLastError(0);
Packit ae9e2a
		}
Packit ae9e2a
		else
Packit ae9e2a
#endif
Packit ae9e2a
		if (error_code)
Packit ae9e2a
			git_buf_puts(buf, strerror(error_code));
Packit ae9e2a
Packit ae9e2a
		if (error_code)
Packit ae9e2a
			errno = 0;
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	if (!git_buf_oom(buf))
Packit ae9e2a
		set_error_from_buffer(error_class);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
void giterr_set_str(int error_class, const char *string)
Packit ae9e2a
{
Packit ae9e2a
	git_buf *buf = &GIT_GLOBAL->error_buf;
Packit ae9e2a
Packit ae9e2a
	assert(string);
Packit ae9e2a
Packit ae9e2a
	if (!string)
Packit ae9e2a
		return;
Packit ae9e2a
Packit ae9e2a
	git_buf_clear(buf);
Packit ae9e2a
	git_buf_puts(buf, string);
Packit ae9e2a
	if (!git_buf_oom(buf))
Packit ae9e2a
		set_error_from_buffer(error_class);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
int giterr_set_regex(const regex_t *regex, int error_code)
Packit ae9e2a
{
Packit ae9e2a
	char error_buf[1024];
Packit ae9e2a
Packit ae9e2a
	assert(error_code);
Packit ae9e2a
Packit ae9e2a
	regerror(error_code, regex, error_buf, sizeof(error_buf));
Packit ae9e2a
	giterr_set_str(GITERR_REGEX, error_buf);
Packit ae9e2a
Packit ae9e2a
	if (error_code == REG_NOMATCH)
Packit ae9e2a
		return GIT_ENOTFOUND;
Packit ae9e2a
Packit ae9e2a
	return GIT_EINVALIDSPEC;
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
void giterr_clear(void)
Packit ae9e2a
{
Packit ae9e2a
	if (GIT_GLOBAL->last_error != NULL) {
Packit ae9e2a
		set_error(0, NULL);
Packit ae9e2a
		GIT_GLOBAL->last_error = NULL;
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	errno = 0;
Packit ae9e2a
#ifdef GIT_WIN32
Packit ae9e2a
	SetLastError(0);
Packit ae9e2a
#endif
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
const git_error *giterr_last(void)
Packit ae9e2a
{
Packit ae9e2a
	return GIT_GLOBAL->last_error;
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
int giterr_state_capture(git_error_state *state, int error_code)
Packit ae9e2a
{
Packit ae9e2a
	git_error *error = GIT_GLOBAL->last_error;
Packit ae9e2a
	git_buf *error_buf = &GIT_GLOBAL->error_buf;
Packit ae9e2a
Packit ae9e2a
	memset(state, 0, sizeof(git_error_state));
Packit ae9e2a
Packit ae9e2a
	if (!error_code)
Packit ae9e2a
		return 0;
Packit ae9e2a
Packit ae9e2a
	state->error_code = error_code;
Packit ae9e2a
	state->oom = (error == &g_git_oom_error);
Packit ae9e2a
Packit ae9e2a
	if (error) {
Packit ae9e2a
		state->error_msg.klass = error->klass;
Packit ae9e2a
Packit ae9e2a
		if (state->oom)
Packit ae9e2a
			state->error_msg.message = g_git_oom_error.message;
Packit ae9e2a
		else
Packit ae9e2a
			state->error_msg.message = git_buf_detach(error_buf);
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	giterr_clear();
Packit ae9e2a
	return error_code;
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
int giterr_state_restore(git_error_state *state)
Packit ae9e2a
{
Packit ae9e2a
	int ret = 0;
Packit ae9e2a
Packit ae9e2a
	giterr_clear();
Packit ae9e2a
Packit ae9e2a
	if (state && state->error_msg.message) {
Packit ae9e2a
		if (state->oom)
Packit ae9e2a
			giterr_set_oom();
Packit ae9e2a
		else
Packit ae9e2a
			set_error(state->error_msg.klass, state->error_msg.message);
Packit ae9e2a
Packit ae9e2a
		ret = state->error_code;
Packit ae9e2a
		memset(state, 0, sizeof(git_error_state));
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	return ret;
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
void giterr_state_free(git_error_state *state)
Packit ae9e2a
{
Packit ae9e2a
	if (!state)
Packit ae9e2a
		return;
Packit ae9e2a
Packit ae9e2a
	if (!state->oom)
Packit ae9e2a
		git__free(state->error_msg.message);
Packit ae9e2a
Packit ae9e2a
	memset(state, 0, sizeof(git_error_state));
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
int giterr_system_last(void)
Packit ae9e2a
{
Packit ae9e2a
#ifdef GIT_WIN32
Packit ae9e2a
	return GetLastError();
Packit ae9e2a
#else
Packit ae9e2a
	return errno;
Packit ae9e2a
#endif
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
void giterr_system_set(int code)
Packit ae9e2a
{
Packit ae9e2a
#ifdef GIT_WIN32
Packit ae9e2a
	SetLastError(code);
Packit ae9e2a
#else
Packit ae9e2a
	errno = code;
Packit ae9e2a
#endif
Packit ae9e2a
}