]> git.proxmox.com Git - libgit2.git/blob - src/errors.c
Merge pull request #2528 from libgit2/vmg/tostr_s
[libgit2.git] / src / errors.c
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7 #include "common.h"
8 #include "global.h"
9 #include "posix.h"
10 #include "buffer.h"
11
12 /********************************************
13 * New error handling
14 ********************************************/
15
16 static git_error g_git_oom_error = {
17 "Out of memory",
18 GITERR_NOMEMORY
19 };
20
21 static void set_error(int error_class, char *string)
22 {
23 git_error *error = &GIT_GLOBAL->error_t;
24
25 if (error->message != string)
26 git__free(error->message);
27
28 error->message = string;
29 error->klass = error_class;
30
31 GIT_GLOBAL->last_error = error;
32 }
33
34 void giterr_set_oom(void)
35 {
36 GIT_GLOBAL->last_error = &g_git_oom_error;
37 }
38
39 void giterr_set(int error_class, const char *string, ...)
40 {
41 git_buf buf = GIT_BUF_INIT;
42 va_list arglist;
43 #ifdef GIT_WIN32
44 DWORD win32_error_code = (error_class == GITERR_OS) ? GetLastError() : 0;
45 #endif
46 int error_code = (error_class == GITERR_OS) ? errno : 0;
47
48 if (string) {
49 va_start(arglist, string);
50 git_buf_vprintf(&buf, string, arglist);
51 va_end(arglist);
52
53 if (error_class == GITERR_OS)
54 git_buf_PUTS(&buf, ": ");
55 }
56
57 if (error_class == GITERR_OS) {
58 #ifdef GIT_WIN32
59 char * win32_error = git_win32_get_error_message(win32_error_code);
60 if (win32_error) {
61 git_buf_puts(&buf, win32_error);
62 git__free(win32_error);
63
64 SetLastError(0);
65 }
66 else
67 #endif
68 if (error_code)
69 git_buf_puts(&buf, strerror(error_code));
70
71 if (error_code)
72 errno = 0;
73 }
74
75 if (!git_buf_oom(&buf))
76 set_error(error_class, git_buf_detach(&buf));
77 }
78
79 void giterr_set_str(int error_class, const char *string)
80 {
81 char *message;
82
83 assert(string);
84
85 message = git__strdup(string);
86
87 if (message)
88 set_error(error_class, message);
89 }
90
91 int giterr_set_regex(const regex_t *regex, int error_code)
92 {
93 char error_buf[1024];
94
95 assert(error_code);
96
97 regerror(error_code, regex, error_buf, sizeof(error_buf));
98 giterr_set_str(GITERR_REGEX, error_buf);
99
100 if (error_code == REG_NOMATCH)
101 return GIT_ENOTFOUND;
102
103 return GIT_EINVALIDSPEC;
104 }
105
106 void giterr_clear(void)
107 {
108 if (GIT_GLOBAL->last_error != NULL) {
109 set_error(0, NULL);
110 GIT_GLOBAL->last_error = NULL;
111 }
112
113 errno = 0;
114 #ifdef GIT_WIN32
115 SetLastError(0);
116 #endif
117 }
118
119 int giterr_detach(git_error *cpy)
120 {
121 git_error *error = GIT_GLOBAL->last_error;
122
123 assert(cpy);
124
125 if (!error)
126 return -1;
127
128 cpy->message = error->message;
129 cpy->klass = error->klass;
130
131 error->message = NULL;
132 giterr_clear();
133
134 return 0;
135 }
136
137 const git_error *giterr_last(void)
138 {
139 return GIT_GLOBAL->last_error;
140 }
141
142 int giterr_capture(git_error_state *state, int error_code)
143 {
144 state->error_code = error_code;
145 if (error_code)
146 giterr_detach(&state->error_msg);
147 return error_code;
148 }
149
150 int giterr_restore(git_error_state *state)
151 {
152 if (state && state->error_code && state->error_msg.message)
153 set_error(state->error_msg.klass, state->error_msg.message);
154 else
155 giterr_clear();
156
157 return state ? state->error_code : 0;
158 }
159
160 int giterr_system_last(void)
161 {
162 #ifdef GIT_WIN32
163 return GetLastError();
164 #else
165 return errno;
166 #endif
167 }
168
169 void giterr_system_set(int code)
170 {
171 #ifdef GIT_WIN32
172 SetLastError(code);
173 #else
174 errno = code;
175 #endif
176 }