/** Copyright (C) the libgit2 contributors. All rights reserved.** This file is part of libgit2, distributed under the GNU GPL v2 with* a Linking Exception. For full terms see the included COPYING file.*/#include "git2_util.h"#include "errors.h"#include "posix.h"#include "str.h"#include "runtime.h"/** Some static error data that is used when we're out of memory, TLS* has not been setup, or TLS has failed.*/static git_error oom_error = {"Out of memory",GIT_ERROR_NOMEMORY};static git_error uninitialized_error = {"library has not been initialized",GIT_ERROR_INVALID};static git_error tlsdata_error = {"thread-local data initialization failure",GIT_ERROR_THREAD};static git_error no_error = {"no error",GIT_ERROR_NONE};#define IS_STATIC_ERROR(err) \((err) == &oom_error || (err) == &uninitialized_error || \(err) == &tlsdata_error || (err) == &no_error)/* Per-thread error state (TLS) */static git_tlsdata_key tls_key;struct error_threadstate {/* The error message buffer. */git_str message;/* Error information, set by `git_error_set` and friends. */git_error error;/** The last error to occur; points to the error member of this* struct _or_ a static error.*/git_error *last;};static void threadstate_dispose(struct error_threadstate *threadstate){if (!threadstate)return;git_str_dispose(&threadstate->message);}static struct error_threadstate *threadstate_get(void){struct error_threadstate *threadstate;if ((threadstate = git_tlsdata_get(tls_key)) != NULL)return threadstate;/** Avoid git__malloc here, since if it fails, it sets an error* message, which requires thread state, which would allocate* here, which would fail, which would set an error message...*/if ((threadstate = git__allocator.gmalloc(sizeof(struct error_threadstate),__FILE__, __LINE__)) == NULL)return NULL;memset(threadstate, 0, sizeof(struct error_threadstate));if (git_str_init(&threadstate->message, 0) < 0) {git__allocator.gfree(threadstate);return NULL;}git_tlsdata_set(tls_key, threadstate);return threadstate;}static void GIT_SYSTEM_CALL threadstate_free(void *threadstate){threadstate_dispose(threadstate);git__free(threadstate);}static void git_error_global_shutdown(void){struct error_threadstate *threadstate;threadstate = git_tlsdata_get(tls_key);git_tlsdata_set(tls_key, NULL);threadstate_dispose(threadstate);git__free(threadstate);git_tlsdata_dispose(tls_key);}int git_error_global_init(void){if (git_tlsdata_init(&tls_key, &threadstate_free) != 0)return -1;return git_runtime_shutdown_register(git_error_global_shutdown);}static void set_error_from_buffer(int error_class){struct error_threadstate *threadstate = threadstate_get();git_error *error;git_str *buf;if (!threadstate)return;error = &threadstate->error;buf = &threadstate->message;error->message = buf->ptr;error->klass = error_class;threadstate->last = error;}static void set_error(int error_class, char *string){struct error_threadstate *threadstate = threadstate_get();git_str *buf;if (!threadstate)return;buf = &threadstate->message;git_str_clear(buf);if (string)git_str_puts(buf, string);if (!git_str_oom(buf))set_error_from_buffer(error_class);}void git_error_set_oom(void){struct error_threadstate *threadstate = threadstate_get();if (!threadstate)return;threadstate->last = &oom_error;}void git_error_set(int error_class, const char *fmt, ...){va_list ap;va_start(ap, fmt);git_error_vset(error_class, fmt, ap);va_end(ap);}void git_error_vset(int error_class, const char *fmt, va_list ap){#ifdef GIT_WIN32DWORD win32_error_code = (error_class == GIT_ERROR_OS) ? GetLastError() : 0;#endifstruct error_threadstate *threadstate = threadstate_get();int error_code = (error_class == GIT_ERROR_OS) ? errno : 0;git_str *buf;if (!threadstate)return;buf = &threadstate->message;git_str_clear(buf);if (fmt) {git_str_vprintf(buf, fmt, ap);if (error_class == GIT_ERROR_OS)git_str_PUTS(buf, ": ");}if (error_class == GIT_ERROR_OS) {#ifdef GIT_WIN32char *win32_error = git_win32_get_error_message(win32_error_code);if (win32_error) {git_str_puts(buf, win32_error);git__free(win32_error);SetLastError(0);}else#endifif (error_code)git_str_puts(buf, strerror(error_code));if (error_code)errno = 0;}if (!git_str_oom(buf))set_error_from_buffer(error_class);}int git_error_set_str(int error_class, const char *string){struct error_threadstate *threadstate = threadstate_get();git_str *buf;GIT_ASSERT_ARG(string);if (!threadstate)return -1;buf = &threadstate->message;git_str_clear(buf);git_str_puts(buf, string);if (git_str_oom(buf))return -1;set_error_from_buffer(error_class);return 0;}void git_error_clear(void){struct error_threadstate *threadstate = threadstate_get();if (!threadstate)return;if (threadstate->last != NULL) {set_error(0, NULL);threadstate->last = NULL;}errno = 0;#ifdef GIT_WIN32SetLastError(0);#endif}bool git_error_exists(void){struct error_threadstate *threadstate;if ((threadstate = threadstate_get()) == NULL)return true;return threadstate->last != NULL;}const git_error *git_error_last(void){struct error_threadstate *threadstate;/* If the library is not initialized, return a static error. */if (!git_runtime_init_count())return &uninitialized_error;if ((threadstate = threadstate_get()) == NULL)return &tlsdata_error;if (!threadstate->last)return &no_error;return threadstate->last;}int git_error_save(git_error **out){struct error_threadstate *threadstate = threadstate_get();git_error *error, *dup;if (!threadstate) {*out = &tlsdata_error;return -1;}error = threadstate->last;if (!error || error == &no_error) {*out = &no_error;return 0;} else if (IS_STATIC_ERROR(error)) {*out = error;return 0;}if ((dup = git__malloc(sizeof(git_error))) == NULL) {*out = &oom_error;return -1;}dup->klass = error->klass;dup->message = git__strdup(error->message);if (!dup->message) {*out = &oom_error;return -1;}*out = dup;return 0;}int git_error_restore(git_error *error){struct error_threadstate *threadstate = threadstate_get();GIT_ASSERT_ARG(error);if (IS_STATIC_ERROR(error) && threadstate)threadstate->last = error;elseset_error(error->klass, error->message);git_error_free(error);return 0;}void git_error_free(git_error *error){if (!error)return;if (IS_STATIC_ERROR(error))return;git__free(error->message);git__free(error);}int git_error_system_last(void){#ifdef GIT_WIN32return GetLastError();#elsereturn errno;#endif}void git_error_system_set(int code){#ifdef GIT_WIN32SetLastError(code);#elseerrno = code;#endif}/* Deprecated error values and functions */#ifndef GIT_DEPRECATE_HARD#include "git2/deprecated.h"const git_error *giterr_last(void){return git_error_last();}void giterr_clear(void){git_error_clear();}void giterr_set_str(int error_class, const char *string){git_error_set_str(error_class, string);}void giterr_set_oom(void){git_error_set_oom();}#endif
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型