]> git.proxmox.com Git - mirror_qemu.git/blame - util/error.c
raven: Mark use of hw_error() in realize() FIXME
[mirror_qemu.git] / util / error.c
CommitLineData
d5ec4f27
LC
1/*
2 * QEMU Error Objects
3 *
4 * Copyright IBM, Corp. 2011
a29a37b9 5 * Copyright (C) 2011-2015 Red Hat, Inc.
d5ec4f27
LC
6 *
7 * Authors:
8 * Anthony Liguori <aliguori@us.ibm.com>
a29a37b9 9 * Markus Armbruster <armbru@redhat.com>,
d5ec4f27
LC
10 *
11 * This work is licensed under the terms of the GNU LGPL, version 2. See
12 * the COPYING.LIB file in the top-level directory.
13 */
e4ea5e2d
SW
14
15#include "qemu-common.h"
7b1b5d19 16#include "qapi/error.h"
073a3411 17#include "qemu/error-report.h"
d5ec4f27
LC
18
19struct Error
20{
d5ec4f27 21 char *msg;
13f59ae8 22 ErrorClass err_class;
1e9b65bb
MA
23 const char *src, *func;
24 int line;
50b7b000 25 GString *hint;
d5ec4f27
LC
26};
27
5d24ee70 28Error *error_abort;
a29a37b9 29Error *error_fatal;
5d24ee70 30
a29a37b9 31static void error_handle_fatal(Error **errp, Error *err)
1e9b65bb 32{
a29a37b9
MA
33 if (errp == &error_abort) {
34 fprintf(stderr, "Unexpected error in %s() at %s:%d:\n",
35 err->func, err->src, err->line);
36 error_report_err(err);
37 abort();
38 }
39 if (errp == &error_fatal) {
40 error_report_err(err);
41 exit(1);
42 }
1e9b65bb
MA
43}
44
45static void error_setv(Error **errp,
46 const char *src, int line, const char *func,
47 ErrorClass err_class, const char *fmt, va_list ap)
d5ec4f27
LC
48{
49 Error *err;
b276d249 50 int saved_errno = errno;
d5ec4f27
LC
51
52 if (errp == NULL) {
53 return;
54 }
d195325b 55 assert(*errp == NULL);
d5ec4f27 56
7267c094 57 err = g_malloc0(sizeof(*err));
df1e608a 58 err->msg = g_strdup_vprintf(fmt, ap);
13f59ae8 59 err->err_class = err_class;
1e9b65bb
MA
60 err->src = src;
61 err->line = line;
62 err->func = func;
d5ec4f27 63
a29a37b9 64 error_handle_fatal(errp, err);
d5ec4f27 65 *errp = err;
b276d249
HR
66
67 errno = saved_errno;
d5ec4f27
LC
68}
69
1e9b65bb
MA
70void error_set_internal(Error **errp,
71 const char *src, int line, const char *func,
72 ErrorClass err_class, const char *fmt, ...)
55237508
MA
73{
74 va_list ap;
75
76 va_start(ap, fmt);
1e9b65bb 77 error_setv(errp, src, line, func, err_class, fmt, ap);
55237508
MA
78 va_end(ap);
79}
80
1e9b65bb
MA
81void error_setg_internal(Error **errp,
82 const char *src, int line, const char *func,
83 const char *fmt, ...)
a9499ddd
MA
84{
85 va_list ap;
86
87 va_start(ap, fmt);
1e9b65bb 88 error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
a9499ddd
MA
89 va_end(ap);
90}
91
1e9b65bb
MA
92void error_setg_errno_internal(Error **errp,
93 const char *src, int line, const char *func,
94 int os_errno, const char *fmt, ...)
680d16dc 95{
680d16dc 96 va_list ap;
55237508 97 char *msg;
b276d249 98 int saved_errno = errno;
680d16dc
PB
99
100 if (errp == NULL) {
101 return;
102 }
680d16dc
PB
103
104 va_start(ap, fmt);
1e9b65bb 105 error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
680d16dc 106 va_end(ap);
680d16dc 107
55237508
MA
108 if (os_errno != 0) {
109 msg = (*errp)->msg;
110 (*errp)->msg = g_strdup_printf("%s: %s", msg, strerror(os_errno));
111 g_free(msg);
5d24ee70
PC
112 }
113
b276d249 114 errno = saved_errno;
680d16dc
PB
115}
116
1e9b65bb
MA
117void error_setg_file_open_internal(Error **errp,
118 const char *src, int line, const char *func,
119 int os_errno, const char *filename)
54028d75 120{
1e9b65bb
MA
121 error_setg_errno_internal(errp, src, line, func, os_errno,
122 "Could not open '%s'", filename);
54028d75
LC
123}
124
50b7b000
EB
125void error_append_hint(Error **errp, const char *fmt, ...)
126{
127 va_list ap;
128 int saved_errno = errno;
129 Error *err;
130
131 if (!errp) {
132 return;
133 }
134 err = *errp;
135 assert(err && errp != &error_abort);
136
137 if (!err->hint) {
138 err->hint = g_string_new(NULL);
139 }
140 va_start(ap, fmt);
141 g_string_append_vprintf(err->hint, fmt, ap);
142 va_end(ap);
143
144 errno = saved_errno;
145}
146
20840d4c
TS
147#ifdef _WIN32
148
1e9b65bb
MA
149void error_setg_win32_internal(Error **errp,
150 const char *src, int line, const char *func,
151 int win32_err, const char *fmt, ...)
20840d4c 152{
20840d4c 153 va_list ap;
55237508 154 char *msg1, *msg2;
20840d4c
TS
155
156 if (errp == NULL) {
157 return;
158 }
20840d4c
TS
159
160 va_start(ap, fmt);
1e9b65bb 161 error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
55237508
MA
162 va_end(ap);
163
20840d4c 164 if (win32_err != 0) {
55237508
MA
165 msg1 = (*errp)->msg;
166 msg2 = g_win32_error_message(win32_err);
167 (*errp)->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2,
168 (unsigned)win32_err);
20840d4c
TS
169 g_free(msg2);
170 g_free(msg1);
5d24ee70 171 }
20840d4c
TS
172}
173
174#endif
175
79020cfc
LC
176Error *error_copy(const Error *err)
177{
178 Error *err_new;
179
180 err_new = g_malloc0(sizeof(*err));
181 err_new->msg = g_strdup(err->msg);
13f59ae8 182 err_new->err_class = err->err_class;
88e2ce29
EB
183 err_new->src = err->src;
184 err_new->line = err->line;
185 err_new->func = err->func;
50b7b000
EB
186 if (err->hint) {
187 err_new->hint = g_string_new(err->hint->str);
188 }
79020cfc
LC
189
190 return err_new;
191}
192
ea25fbca
LC
193ErrorClass error_get_class(const Error *err)
194{
195 return err->err_class;
196}
197
d5ec4f27
LC
198const char *error_get_pretty(Error *err)
199{
d5ec4f27
LC
200 return err->msg;
201}
202
2ee2f1e4
MA
203void error_report_err(Error *err)
204{
205 error_report("%s", error_get_pretty(err));
50b7b000
EB
206 if (err->hint) {
207 error_printf_unless_qmp("%s\n", err->hint->str);
208 }
2ee2f1e4
MA
209 error_free(err);
210}
211
d5ec4f27
LC
212void error_free(Error *err)
213{
214 if (err) {
7267c094 215 g_free(err->msg);
50b7b000
EB
216 if (err->hint) {
217 g_string_free(err->hint, true);
218 }
7267c094 219 g_free(err);
d5ec4f27
LC
220 }
221}
222
a12a5a1a
EB
223void error_free_or_abort(Error **errp)
224{
225 assert(errp && *errp);
226 error_free(*errp);
227 *errp = NULL;
228}
229
64dfefed 230void error_propagate(Error **dst_errp, Error *local_err)
d5ec4f27 231{
a29a37b9
MA
232 if (!local_err) {
233 return;
234 }
235 error_handle_fatal(dst_errp, local_err);
236 if (dst_errp && !*dst_errp) {
64dfefed 237 *dst_errp = local_err;
a29a37b9 238 } else {
d5ec4f27
LC
239 error_free(local_err);
240 }
241}