blob: e5e247209a9e0796074a9794f5598325f22f8d35 [file] [log] [blame]
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -05001/*
2 * QEMU Error Objects
3 *
4 * Copyright IBM, Corp. 2011
Markus Armbrustera29a37b2015-09-11 16:51:42 +02005 * Copyright (C) 2011-2015 Red Hat, Inc.
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -05006 *
7 * Authors:
8 * Anthony Liguori <aliguori@us.ibm.com>
Markus Armbrustera29a37b2015-09-11 16:51:42 +02009 * Markus Armbruster <armbru@redhat.com>,
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -050010 *
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 */
Stefan Weile4ea5e22011-06-13 23:01:53 +020014
Peter Maydellaafd7582016-01-29 17:49:55 +000015#include "qemu/osdep.h"
Markus Armbrusterda34e652016-03-14 09:01:28 +010016#include "qapi/error.h"
Cole Robinson073a3412014-03-21 19:42:28 -040017#include "qemu/error-report.h"
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -050018
19struct Error
20{
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -050021 char *msg;
Luiz Capitulino13f59ae2012-07-27 14:09:29 -030022 ErrorClass err_class;
Markus Armbruster1e9b65b2015-06-19 19:21:59 +020023 const char *src, *func;
24 int line;
Eric Blake50b7b002015-09-10 10:19:16 -060025 GString *hint;
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -050026};
27
Peter Crosthwaite5d24ee72014-01-01 18:46:59 -080028Error *error_abort;
Markus Armbrustera29a37b2015-09-11 16:51:42 +020029Error *error_fatal;
Marc-André Lureau3ffef1a2023-02-21 16:47:50 +040030Error *error_warn;
Peter Crosthwaite5d24ee72014-01-01 18:46:59 -080031
Marc-André Lureau3ffef1a2023-02-21 16:47:50 +040032static void error_handle(Error **errp, Error *err)
Markus Armbruster1e9b65b2015-06-19 19:21:59 +020033{
Markus Armbrustera29a37b2015-09-11 16:51:42 +020034 if (errp == &error_abort) {
35 fprintf(stderr, "Unexpected error in %s() at %s:%d:\n",
36 err->func, err->src, err->line);
Vladimir Sementsov-Ogievskiyb922c052019-04-15 17:25:19 +030037 error_report("%s", error_get_pretty(err));
38 if (err->hint) {
39 error_printf("%s", err->hint->str);
40 }
Markus Armbrustera29a37b2015-09-11 16:51:42 +020041 abort();
42 }
43 if (errp == &error_fatal) {
44 error_report_err(err);
45 exit(1);
46 }
Marc-André Lureau3ffef1a2023-02-21 16:47:50 +040047 if (errp == &error_warn) {
48 warn_report_err(err);
Stefan Bergercc40b8b2023-04-06 11:43:47 -040049 } else if (errp && !*errp) {
50 *errp = err;
51 } else {
52 error_free(err);
Marc-André Lureau3ffef1a2023-02-21 16:47:50 +040053 }
Markus Armbruster1e9b65b2015-06-19 19:21:59 +020054}
55
Daniel P. Berrangébeede7e2022-12-19 08:02:03 -050056G_GNUC_PRINTF(6, 0)
Markus Armbruster1e9b65b2015-06-19 19:21:59 +020057static void error_setv(Error **errp,
58 const char *src, int line, const char *func,
Daniel P. Berrange20e2dec2016-03-09 17:28:24 +000059 ErrorClass err_class, const char *fmt, va_list ap,
60 const char *suffix)
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -050061{
62 Error *err;
Max Reitzb276d242013-11-07 20:10:29 +010063 int saved_errno = errno;
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -050064
65 if (errp == NULL) {
66 return;
67 }
Paolo Bonzinid1953252012-07-17 16:17:04 +020068 assert(*errp == NULL);
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -050069
Anthony Liguori7267c092011-08-20 22:09:37 -050070 err = g_malloc0(sizeof(*err));
Luiz Capitulinodf1e6082012-07-27 17:51:03 -030071 err->msg = g_strdup_vprintf(fmt, ap);
Daniel P. Berrange20e2dec2016-03-09 17:28:24 +000072 if (suffix) {
73 char *msg = err->msg;
74 err->msg = g_strdup_printf("%s: %s", msg, suffix);
75 g_free(msg);
76 }
Luiz Capitulino13f59ae2012-07-27 14:09:29 -030077 err->err_class = err_class;
Markus Armbruster1e9b65b2015-06-19 19:21:59 +020078 err->src = src;
79 err->line = line;
80 err->func = func;
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -050081
Marc-André Lureau3ffef1a2023-02-21 16:47:50 +040082 error_handle(errp, err);
Max Reitzb276d242013-11-07 20:10:29 +010083
84 errno = saved_errno;
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -050085}
86
Markus Armbruster1e9b65b2015-06-19 19:21:59 +020087void error_set_internal(Error **errp,
88 const char *src, int line, const char *func,
89 ErrorClass err_class, const char *fmt, ...)
Markus Armbruster55237502015-06-19 13:59:47 +020090{
91 va_list ap;
92
93 va_start(ap, fmt);
Daniel P. Berrange20e2dec2016-03-09 17:28:24 +000094 error_setv(errp, src, line, func, err_class, fmt, ap, NULL);
Markus Armbruster55237502015-06-19 13:59:47 +020095 va_end(ap);
96}
97
Markus Armbruster1e9b65b2015-06-19 19:21:59 +020098void error_setg_internal(Error **errp,
99 const char *src, int line, const char *func,
100 const char *fmt, ...)
Markus Armbrustera9499dd2015-06-19 15:36:16 +0200101{
102 va_list ap;
103
104 va_start(ap, fmt);
Daniel P. Berrange20e2dec2016-03-09 17:28:24 +0000105 error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap, NULL);
Markus Armbrustera9499dd2015-06-19 15:36:16 +0200106 va_end(ap);
107}
108
Markus Armbruster1e9b65b2015-06-19 19:21:59 +0200109void error_setg_errno_internal(Error **errp,
110 const char *src, int line, const char *func,
111 int os_errno, const char *fmt, ...)
Paolo Bonzini680d16d2012-10-02 09:00:45 +0200112{
Paolo Bonzini680d16d2012-10-02 09:00:45 +0200113 va_list ap;
Max Reitzb276d242013-11-07 20:10:29 +0100114 int saved_errno = errno;
Paolo Bonzini680d16d2012-10-02 09:00:45 +0200115
Paolo Bonzini680d16d2012-10-02 09:00:45 +0200116 va_start(ap, fmt);
Daniel P. Berrange20e2dec2016-03-09 17:28:24 +0000117 error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap,
118 os_errno != 0 ? strerror(os_errno) : NULL);
Paolo Bonzini680d16d2012-10-02 09:00:45 +0200119 va_end(ap);
Paolo Bonzini680d16d2012-10-02 09:00:45 +0200120
Max Reitzb276d242013-11-07 20:10:29 +0100121 errno = saved_errno;
Paolo Bonzini680d16d2012-10-02 09:00:45 +0200122}
123
Markus Armbruster1e9b65b2015-06-19 19:21:59 +0200124void error_setg_file_open_internal(Error **errp,
125 const char *src, int line, const char *func,
126 int os_errno, const char *filename)
Luiz Capitulino54028d72013-06-07 14:24:49 -0400127{
Markus Armbruster1e9b65b2015-06-19 19:21:59 +0200128 error_setg_errno_internal(errp, src, line, func, os_errno,
129 "Could not open '%s'", filename);
Luiz Capitulino54028d72013-06-07 14:24:49 -0400130}
131
Vladimir Sementsov-Ogievskiy49fbc722019-12-05 20:46:17 +0300132void error_vprepend(Error *const *errp, const char *fmt, va_list ap)
Markus Armbruster8277d2a2015-12-18 16:35:12 +0100133{
134 GString *newmsg;
135
136 if (!errp) {
137 return;
138 }
139
140 newmsg = g_string_new(NULL);
141 g_string_vprintf(newmsg, fmt, ap);
142 g_string_append(newmsg, (*errp)->msg);
Max Reitz536eeea2017-04-13 18:09:52 +0200143 g_free((*errp)->msg);
Markus Armbruster8277d2a2015-12-18 16:35:12 +0100144 (*errp)->msg = g_string_free(newmsg, 0);
145}
146
Vladimir Sementsov-Ogievskiy49fbc722019-12-05 20:46:17 +0300147void error_prepend(Error *const *errp, const char *fmt, ...)
Markus Armbruster8277d2a2015-12-18 16:35:12 +0100148{
149 va_list ap;
150
151 va_start(ap, fmt);
152 error_vprepend(errp, fmt, ap);
153 va_end(ap);
154}
155
Vladimir Sementsov-Ogievskiy49fbc722019-12-05 20:46:17 +0300156void error_append_hint(Error *const *errp, const char *fmt, ...)
Eric Blake50b7b002015-09-10 10:19:16 -0600157{
158 va_list ap;
159 int saved_errno = errno;
160 Error *err;
161
162 if (!errp) {
163 return;
164 }
165 err = *errp;
Markus Armbrusterf4d00642015-12-18 16:35:08 +0100166 assert(err && errp != &error_abort && errp != &error_fatal);
Eric Blake50b7b002015-09-10 10:19:16 -0600167
168 if (!err->hint) {
169 err->hint = g_string_new(NULL);
170 }
171 va_start(ap, fmt);
172 g_string_append_vprintf(err->hint, fmt, ap);
173 va_end(ap);
174
175 errno = saved_errno;
176}
177
Tomoki Sekiyama20840d42013-08-07 11:40:11 -0400178#ifdef _WIN32
179
Markus Armbruster1e9b65b2015-06-19 19:21:59 +0200180void error_setg_win32_internal(Error **errp,
181 const char *src, int line, const char *func,
182 int win32_err, const char *fmt, ...)
Tomoki Sekiyama20840d42013-08-07 11:40:11 -0400183{
Tomoki Sekiyama20840d42013-08-07 11:40:11 -0400184 va_list ap;
Daniel P. Berrange20e2dec2016-03-09 17:28:24 +0000185 char *suffix = NULL;
Tomoki Sekiyama20840d42013-08-07 11:40:11 -0400186
187 if (errp == NULL) {
188 return;
189 }
Tomoki Sekiyama20840d42013-08-07 11:40:11 -0400190
Daniel P. Berrange20e2dec2016-03-09 17:28:24 +0000191 if (win32_err != 0) {
192 suffix = g_win32_error_message(win32_err);
193 }
194
Tomoki Sekiyama20840d42013-08-07 11:40:11 -0400195 va_start(ap, fmt);
Daniel P. Berrange20e2dec2016-03-09 17:28:24 +0000196 error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR,
197 fmt, ap, suffix);
Markus Armbruster55237502015-06-19 13:59:47 +0200198 va_end(ap);
199
Daniel P. Berrange20e2dec2016-03-09 17:28:24 +0000200 g_free(suffix);
Tomoki Sekiyama20840d42013-08-07 11:40:11 -0400201}
202
203#endif
204
Luiz Capitulino79020cf2011-12-05 16:04:05 -0200205Error *error_copy(const Error *err)
206{
207 Error *err_new;
208
209 err_new = g_malloc0(sizeof(*err));
210 err_new->msg = g_strdup(err->msg);
Luiz Capitulino13f59ae2012-07-27 14:09:29 -0300211 err_new->err_class = err->err_class;
Eric Blake88e2ce22015-09-10 10:34:50 -0600212 err_new->src = err->src;
213 err_new->line = err->line;
214 err_new->func = err->func;
Eric Blake50b7b002015-09-10 10:19:16 -0600215 if (err->hint) {
216 err_new->hint = g_string_new(err->hint->str);
217 }
Luiz Capitulino79020cf2011-12-05 16:04:05 -0200218
219 return err_new;
220}
221
Luiz Capitulinoea25fbc2012-08-01 16:29:38 -0300222ErrorClass error_get_class(const Error *err)
223{
224 return err->err_class;
225}
226
Daniel P. Berranged59ce6f2016-04-27 11:05:00 +0100227const char *error_get_pretty(const Error *err)
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -0500228{
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -0500229 return err->msg;
230}
231
Markus Armbruster2ee2f1e2015-02-06 15:27:19 +0100232void error_report_err(Error *err)
233{
234 error_report("%s", error_get_pretty(err));
Eric Blake50b7b002015-09-10 10:19:16 -0600235 if (err->hint) {
Markus Armbruster4c8b7c82019-04-16 17:38:50 +0200236 error_printf("%s", err->hint->str);
Eric Blake50b7b002015-09-10 10:19:16 -0600237 }
Markus Armbruster2ee2f1e2015-02-06 15:27:19 +0100238 error_free(err);
239}
240
Alistair Francise43ead12017-07-12 06:57:52 -0700241void warn_report_err(Error *err)
242{
243 warn_report("%s", error_get_pretty(err));
244 if (err->hint) {
Markus Armbruster4c8b7c82019-04-16 17:38:50 +0200245 error_printf("%s", err->hint->str);
Alistair Francise43ead12017-07-12 06:57:52 -0700246 }
247 error_free(err);
248}
249
Markus Armbruster8277d2a2015-12-18 16:35:12 +0100250void error_reportf_err(Error *err, const char *fmt, ...)
251{
252 va_list ap;
253
254 va_start(ap, fmt);
255 error_vprepend(&err, fmt, ap);
256 va_end(ap);
257 error_report_err(err);
258}
259
Alistair Francise43ead12017-07-12 06:57:52 -0700260
261void warn_reportf_err(Error *err, const char *fmt, ...)
262{
263 va_list ap;
264
265 va_start(ap, fmt);
266 error_vprepend(&err, fmt, ap);
267 va_end(ap);
268 warn_report_err(err);
269}
270
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -0500271void error_free(Error *err)
272{
273 if (err) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500274 g_free(err->msg);
Eric Blake50b7b002015-09-10 10:19:16 -0600275 if (err->hint) {
276 g_string_free(err->hint, true);
277 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500278 g_free(err);
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -0500279 }
280}
281
Eric Blakea12a5a12015-11-05 23:35:31 -0700282void error_free_or_abort(Error **errp)
283{
284 assert(errp && *errp);
285 error_free(*errp);
286 *errp = NULL;
287}
288
Markus Armbruster64dfefe2014-05-02 13:26:32 +0200289void error_propagate(Error **dst_errp, Error *local_err)
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -0500290{
Markus Armbrustera29a37b2015-09-11 16:51:42 +0200291 if (!local_err) {
292 return;
293 }
Marc-André Lureau3ffef1a2023-02-21 16:47:50 +0400294 error_handle(dst_errp, local_err);
Luiz Capitulinod5ec4f22011-06-01 12:14:49 -0500295}
Markus Armbruster4b576642018-10-17 10:26:25 +0200296
297void error_propagate_prepend(Error **dst_errp, Error *err,
298 const char *fmt, ...)
299{
300 va_list ap;
301
302 if (dst_errp && !*dst_errp) {
303 va_start(ap, fmt);
304 error_vprepend(&err, fmt, ap);
305 va_end(ap);
306 } /* else error is being ignored, don't bother with prepending */
307 error_propagate(dst_errp, err);
308}