xref: /openbmc/qemu/util/error.c (revision da34e65c)
1baacf047SPaolo Bonzini /*
2baacf047SPaolo Bonzini  * QEMU Error Objects
3baacf047SPaolo Bonzini  *
4baacf047SPaolo Bonzini  * Copyright IBM, Corp. 2011
5a29a37b9SMarkus Armbruster  * Copyright (C) 2011-2015 Red Hat, Inc.
6baacf047SPaolo Bonzini  *
7baacf047SPaolo Bonzini  * Authors:
8baacf047SPaolo Bonzini  *  Anthony Liguori   <aliguori@us.ibm.com>
9a29a37b9SMarkus Armbruster  *  Markus Armbruster <armbru@redhat.com>,
10baacf047SPaolo Bonzini  *
11baacf047SPaolo Bonzini  * This work is licensed under the terms of the GNU LGPL, version 2.  See
12baacf047SPaolo Bonzini  * the COPYING.LIB file in the top-level directory.
13baacf047SPaolo Bonzini  */
14baacf047SPaolo Bonzini 
15aafd7584SPeter Maydell #include "qemu/osdep.h"
16*da34e65cSMarkus Armbruster #include "qapi/error.h"
17baacf047SPaolo Bonzini #include "qemu-common.h"
18073a3411SCole Robinson #include "qemu/error-report.h"
19baacf047SPaolo Bonzini 
20baacf047SPaolo Bonzini struct Error
21baacf047SPaolo Bonzini {
22baacf047SPaolo Bonzini     char *msg;
23baacf047SPaolo Bonzini     ErrorClass err_class;
241e9b65bbSMarkus Armbruster     const char *src, *func;
251e9b65bbSMarkus Armbruster     int line;
2650b7b000SEric Blake     GString *hint;
27baacf047SPaolo Bonzini };
28baacf047SPaolo Bonzini 
295d24ee70SPeter Crosthwaite Error *error_abort;
30a29a37b9SMarkus Armbruster Error *error_fatal;
315d24ee70SPeter Crosthwaite 
32a29a37b9SMarkus Armbruster static void error_handle_fatal(Error **errp, Error *err)
331e9b65bbSMarkus Armbruster {
34a29a37b9SMarkus Armbruster     if (errp == &error_abort) {
351e9b65bbSMarkus Armbruster         fprintf(stderr, "Unexpected error in %s() at %s:%d:\n",
361e9b65bbSMarkus Armbruster                 err->func, err->src, err->line);
371e9b65bbSMarkus Armbruster         error_report_err(err);
381e9b65bbSMarkus Armbruster         abort();
391e9b65bbSMarkus Armbruster     }
40a29a37b9SMarkus Armbruster     if (errp == &error_fatal) {
41a29a37b9SMarkus Armbruster         error_report_err(err);
42a29a37b9SMarkus Armbruster         exit(1);
43a29a37b9SMarkus Armbruster     }
44a29a37b9SMarkus Armbruster }
451e9b65bbSMarkus Armbruster 
461e9b65bbSMarkus Armbruster static void error_setv(Error **errp,
471e9b65bbSMarkus Armbruster                        const char *src, int line, const char *func,
4820e2dec1SDaniel P. Berrange                        ErrorClass err_class, const char *fmt, va_list ap,
4920e2dec1SDaniel P. Berrange                        const char *suffix)
50baacf047SPaolo Bonzini {
51baacf047SPaolo Bonzini     Error *err;
52b276d249SMax Reitz     int saved_errno = errno;
53baacf047SPaolo Bonzini 
54baacf047SPaolo Bonzini     if (errp == NULL) {
55baacf047SPaolo Bonzini         return;
56baacf047SPaolo Bonzini     }
57baacf047SPaolo Bonzini     assert(*errp == NULL);
58baacf047SPaolo Bonzini 
59baacf047SPaolo Bonzini     err = g_malloc0(sizeof(*err));
60baacf047SPaolo Bonzini     err->msg = g_strdup_vprintf(fmt, ap);
6120e2dec1SDaniel P. Berrange     if (suffix) {
6220e2dec1SDaniel P. Berrange         char *msg = err->msg;
6320e2dec1SDaniel P. Berrange         err->msg = g_strdup_printf("%s: %s", msg, suffix);
6420e2dec1SDaniel P. Berrange         g_free(msg);
6520e2dec1SDaniel P. Berrange     }
66baacf047SPaolo Bonzini     err->err_class = err_class;
671e9b65bbSMarkus Armbruster     err->src = src;
681e9b65bbSMarkus Armbruster     err->line = line;
691e9b65bbSMarkus Armbruster     err->func = func;
70baacf047SPaolo Bonzini 
71a29a37b9SMarkus Armbruster     error_handle_fatal(errp, err);
72baacf047SPaolo Bonzini     *errp = err;
73b276d249SMax Reitz 
74b276d249SMax Reitz     errno = saved_errno;
75baacf047SPaolo Bonzini }
76baacf047SPaolo Bonzini 
771e9b65bbSMarkus Armbruster void error_set_internal(Error **errp,
781e9b65bbSMarkus Armbruster                         const char *src, int line, const char *func,
791e9b65bbSMarkus Armbruster                         ErrorClass err_class, const char *fmt, ...)
8055237508SMarkus Armbruster {
8155237508SMarkus Armbruster     va_list ap;
8255237508SMarkus Armbruster 
8355237508SMarkus Armbruster     va_start(ap, fmt);
8420e2dec1SDaniel P. Berrange     error_setv(errp, src, line, func, err_class, fmt, ap, NULL);
8555237508SMarkus Armbruster     va_end(ap);
8655237508SMarkus Armbruster }
8755237508SMarkus Armbruster 
881e9b65bbSMarkus Armbruster void error_setg_internal(Error **errp,
891e9b65bbSMarkus Armbruster                          const char *src, int line, const char *func,
901e9b65bbSMarkus Armbruster                          const char *fmt, ...)
91a9499dddSMarkus Armbruster {
92a9499dddSMarkus Armbruster     va_list ap;
93a9499dddSMarkus Armbruster 
94a9499dddSMarkus Armbruster     va_start(ap, fmt);
9520e2dec1SDaniel P. Berrange     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap, NULL);
96a9499dddSMarkus Armbruster     va_end(ap);
97a9499dddSMarkus Armbruster }
98a9499dddSMarkus Armbruster 
991e9b65bbSMarkus Armbruster void error_setg_errno_internal(Error **errp,
1001e9b65bbSMarkus Armbruster                                const char *src, int line, const char *func,
1011e9b65bbSMarkus Armbruster                                int os_errno, const char *fmt, ...)
102baacf047SPaolo Bonzini {
103baacf047SPaolo Bonzini     va_list ap;
104b276d249SMax Reitz     int saved_errno = errno;
105baacf047SPaolo Bonzini 
106baacf047SPaolo Bonzini     if (errp == NULL) {
107baacf047SPaolo Bonzini         return;
108baacf047SPaolo Bonzini     }
109baacf047SPaolo Bonzini 
110baacf047SPaolo Bonzini     va_start(ap, fmt);
11120e2dec1SDaniel P. Berrange     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap,
11220e2dec1SDaniel P. Berrange                os_errno != 0 ? strerror(os_errno) : NULL);
113baacf047SPaolo Bonzini     va_end(ap);
114baacf047SPaolo Bonzini 
115b276d249SMax Reitz     errno = saved_errno;
116baacf047SPaolo Bonzini }
117baacf047SPaolo Bonzini 
1181e9b65bbSMarkus Armbruster void error_setg_file_open_internal(Error **errp,
1191e9b65bbSMarkus Armbruster                                    const char *src, int line, const char *func,
1201e9b65bbSMarkus Armbruster                                    int os_errno, const char *filename)
12154028d75SLuiz Capitulino {
1221e9b65bbSMarkus Armbruster     error_setg_errno_internal(errp, src, line, func, os_errno,
1231e9b65bbSMarkus Armbruster                               "Could not open '%s'", filename);
12454028d75SLuiz Capitulino }
12554028d75SLuiz Capitulino 
1268277d2aaSMarkus Armbruster void error_vprepend(Error **errp, const char *fmt, va_list ap)
1278277d2aaSMarkus Armbruster {
1288277d2aaSMarkus Armbruster     GString *newmsg;
1298277d2aaSMarkus Armbruster 
1308277d2aaSMarkus Armbruster     if (!errp) {
1318277d2aaSMarkus Armbruster         return;
1328277d2aaSMarkus Armbruster     }
1338277d2aaSMarkus Armbruster 
1348277d2aaSMarkus Armbruster     newmsg = g_string_new(NULL);
1358277d2aaSMarkus Armbruster     g_string_vprintf(newmsg, fmt, ap);
1368277d2aaSMarkus Armbruster     g_string_append(newmsg, (*errp)->msg);
1378277d2aaSMarkus Armbruster     (*errp)->msg = g_string_free(newmsg, 0);
1388277d2aaSMarkus Armbruster }
1398277d2aaSMarkus Armbruster 
1408277d2aaSMarkus Armbruster void error_prepend(Error **errp, const char *fmt, ...)
1418277d2aaSMarkus Armbruster {
1428277d2aaSMarkus Armbruster     va_list ap;
1438277d2aaSMarkus Armbruster 
1448277d2aaSMarkus Armbruster     va_start(ap, fmt);
1458277d2aaSMarkus Armbruster     error_vprepend(errp, fmt, ap);
1468277d2aaSMarkus Armbruster     va_end(ap);
1478277d2aaSMarkus Armbruster }
1488277d2aaSMarkus Armbruster 
14950b7b000SEric Blake void error_append_hint(Error **errp, const char *fmt, ...)
15050b7b000SEric Blake {
15150b7b000SEric Blake     va_list ap;
15250b7b000SEric Blake     int saved_errno = errno;
15350b7b000SEric Blake     Error *err;
15450b7b000SEric Blake 
15550b7b000SEric Blake     if (!errp) {
15650b7b000SEric Blake         return;
15750b7b000SEric Blake     }
15850b7b000SEric Blake     err = *errp;
159f4d0064aSMarkus Armbruster     assert(err && errp != &error_abort && errp != &error_fatal);
16050b7b000SEric Blake 
16150b7b000SEric Blake     if (!err->hint) {
16250b7b000SEric Blake         err->hint = g_string_new(NULL);
16350b7b000SEric Blake     }
16450b7b000SEric Blake     va_start(ap, fmt);
16550b7b000SEric Blake     g_string_append_vprintf(err->hint, fmt, ap);
16650b7b000SEric Blake     va_end(ap);
16750b7b000SEric Blake 
16850b7b000SEric Blake     errno = saved_errno;
16950b7b000SEric Blake }
17050b7b000SEric Blake 
17120840d4cSTomoki Sekiyama #ifdef _WIN32
17220840d4cSTomoki Sekiyama 
1731e9b65bbSMarkus Armbruster void error_setg_win32_internal(Error **errp,
1741e9b65bbSMarkus Armbruster                                const char *src, int line, const char *func,
1751e9b65bbSMarkus Armbruster                                int win32_err, const char *fmt, ...)
17620840d4cSTomoki Sekiyama {
17720840d4cSTomoki Sekiyama     va_list ap;
17820e2dec1SDaniel P. Berrange     char *suffix = NULL;
17920840d4cSTomoki Sekiyama 
18020840d4cSTomoki Sekiyama     if (errp == NULL) {
18120840d4cSTomoki Sekiyama         return;
18220840d4cSTomoki Sekiyama     }
18320840d4cSTomoki Sekiyama 
18420e2dec1SDaniel P. Berrange     if (win32_err != 0) {
18520e2dec1SDaniel P. Berrange         suffix = g_win32_error_message(win32_err);
18620e2dec1SDaniel P. Berrange     }
18720e2dec1SDaniel P. Berrange 
18820840d4cSTomoki Sekiyama     va_start(ap, fmt);
18920e2dec1SDaniel P. Berrange     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR,
19020e2dec1SDaniel P. Berrange                fmt, ap, suffix);
19155237508SMarkus Armbruster     va_end(ap);
19255237508SMarkus Armbruster 
19320e2dec1SDaniel P. Berrange     g_free(suffix);
19420840d4cSTomoki Sekiyama }
19520840d4cSTomoki Sekiyama 
19620840d4cSTomoki Sekiyama #endif
19720840d4cSTomoki Sekiyama 
198baacf047SPaolo Bonzini Error *error_copy(const Error *err)
199baacf047SPaolo Bonzini {
200baacf047SPaolo Bonzini     Error *err_new;
201baacf047SPaolo Bonzini 
202baacf047SPaolo Bonzini     err_new = g_malloc0(sizeof(*err));
203baacf047SPaolo Bonzini     err_new->msg = g_strdup(err->msg);
204baacf047SPaolo Bonzini     err_new->err_class = err->err_class;
20588e2ce29SEric Blake     err_new->src = err->src;
20688e2ce29SEric Blake     err_new->line = err->line;
20788e2ce29SEric Blake     err_new->func = err->func;
20850b7b000SEric Blake     if (err->hint) {
20950b7b000SEric Blake         err_new->hint = g_string_new(err->hint->str);
21050b7b000SEric Blake     }
211baacf047SPaolo Bonzini 
212baacf047SPaolo Bonzini     return err_new;
213baacf047SPaolo Bonzini }
214baacf047SPaolo Bonzini 
215baacf047SPaolo Bonzini ErrorClass error_get_class(const Error *err)
216baacf047SPaolo Bonzini {
217baacf047SPaolo Bonzini     return err->err_class;
218baacf047SPaolo Bonzini }
219baacf047SPaolo Bonzini 
220baacf047SPaolo Bonzini const char *error_get_pretty(Error *err)
221baacf047SPaolo Bonzini {
222baacf047SPaolo Bonzini     return err->msg;
223baacf047SPaolo Bonzini }
224baacf047SPaolo Bonzini 
2252ee2f1e4SMarkus Armbruster void error_report_err(Error *err)
2262ee2f1e4SMarkus Armbruster {
2272ee2f1e4SMarkus Armbruster     error_report("%s", error_get_pretty(err));
22850b7b000SEric Blake     if (err->hint) {
229543202c0SMarkus Armbruster         error_printf_unless_qmp("%s", err->hint->str);
23050b7b000SEric Blake     }
2312ee2f1e4SMarkus Armbruster     error_free(err);
2322ee2f1e4SMarkus Armbruster }
2332ee2f1e4SMarkus Armbruster 
2348277d2aaSMarkus Armbruster void error_reportf_err(Error *err, const char *fmt, ...)
2358277d2aaSMarkus Armbruster {
2368277d2aaSMarkus Armbruster     va_list ap;
2378277d2aaSMarkus Armbruster 
2388277d2aaSMarkus Armbruster     va_start(ap, fmt);
2398277d2aaSMarkus Armbruster     error_vprepend(&err, fmt, ap);
2408277d2aaSMarkus Armbruster     va_end(ap);
2418277d2aaSMarkus Armbruster     error_report_err(err);
2428277d2aaSMarkus Armbruster }
2438277d2aaSMarkus Armbruster 
244baacf047SPaolo Bonzini void error_free(Error *err)
245baacf047SPaolo Bonzini {
246baacf047SPaolo Bonzini     if (err) {
247baacf047SPaolo Bonzini         g_free(err->msg);
24850b7b000SEric Blake         if (err->hint) {
24950b7b000SEric Blake             g_string_free(err->hint, true);
25050b7b000SEric Blake         }
251baacf047SPaolo Bonzini         g_free(err);
252baacf047SPaolo Bonzini     }
253baacf047SPaolo Bonzini }
254baacf047SPaolo Bonzini 
255a12a5a1aSEric Blake void error_free_or_abort(Error **errp)
256a12a5a1aSEric Blake {
257a12a5a1aSEric Blake     assert(errp && *errp);
258a12a5a1aSEric Blake     error_free(*errp);
259a12a5a1aSEric Blake     *errp = NULL;
260a12a5a1aSEric Blake }
261a12a5a1aSEric Blake 
26264dfefedSMarkus Armbruster void error_propagate(Error **dst_errp, Error *local_err)
263baacf047SPaolo Bonzini {
264a29a37b9SMarkus Armbruster     if (!local_err) {
265a29a37b9SMarkus Armbruster         return;
266a29a37b9SMarkus Armbruster     }
267a29a37b9SMarkus Armbruster     error_handle_fatal(dst_errp, local_err);
268a29a37b9SMarkus Armbruster     if (dst_errp && !*dst_errp) {
26964dfefedSMarkus Armbruster         *dst_errp = local_err;
270a29a37b9SMarkus Armbruster     } else {
271baacf047SPaolo Bonzini         error_free(local_err);
272baacf047SPaolo Bonzini     }
273baacf047SPaolo Bonzini }
274