xref: /openbmc/qemu/util/error.c (revision 1e9b65bb)
1baacf047SPaolo Bonzini /*
2baacf047SPaolo Bonzini  * QEMU Error Objects
3baacf047SPaolo Bonzini  *
4baacf047SPaolo Bonzini  * Copyright IBM, Corp. 2011
5baacf047SPaolo Bonzini  *
6baacf047SPaolo Bonzini  * Authors:
7baacf047SPaolo Bonzini  *  Anthony Liguori   <aliguori@us.ibm.com>
8baacf047SPaolo Bonzini  *
9baacf047SPaolo Bonzini  * This work is licensed under the terms of the GNU LGPL, version 2.  See
10baacf047SPaolo Bonzini  * the COPYING.LIB file in the top-level directory.
11baacf047SPaolo Bonzini  */
12baacf047SPaolo Bonzini 
13baacf047SPaolo Bonzini #include "qemu-common.h"
14baacf047SPaolo Bonzini #include "qapi/error.h"
15073a3411SCole Robinson #include "qemu/error-report.h"
16baacf047SPaolo Bonzini 
17baacf047SPaolo Bonzini struct Error
18baacf047SPaolo Bonzini {
19baacf047SPaolo Bonzini     char *msg;
20baacf047SPaolo Bonzini     ErrorClass err_class;
21*1e9b65bbSMarkus Armbruster     const char *src, *func;
22*1e9b65bbSMarkus Armbruster     int line;
23baacf047SPaolo Bonzini };
24baacf047SPaolo Bonzini 
255d24ee70SPeter Crosthwaite Error *error_abort;
265d24ee70SPeter Crosthwaite 
27*1e9b65bbSMarkus Armbruster static void error_do_abort(Error *err)
28*1e9b65bbSMarkus Armbruster {
29*1e9b65bbSMarkus Armbruster     fprintf(stderr, "Unexpected error in %s() at %s:%d:\n",
30*1e9b65bbSMarkus Armbruster             err->func, err->src, err->line);
31*1e9b65bbSMarkus Armbruster     error_report_err(err);
32*1e9b65bbSMarkus Armbruster     abort();
33*1e9b65bbSMarkus Armbruster }
34*1e9b65bbSMarkus Armbruster 
35*1e9b65bbSMarkus Armbruster static void error_setv(Error **errp,
36*1e9b65bbSMarkus Armbruster                        const char *src, int line, const char *func,
37*1e9b65bbSMarkus Armbruster                        ErrorClass err_class, const char *fmt, va_list ap)
38baacf047SPaolo Bonzini {
39baacf047SPaolo Bonzini     Error *err;
40b276d249SMax Reitz     int saved_errno = errno;
41baacf047SPaolo Bonzini 
42baacf047SPaolo Bonzini     if (errp == NULL) {
43baacf047SPaolo Bonzini         return;
44baacf047SPaolo Bonzini     }
45baacf047SPaolo Bonzini     assert(*errp == NULL);
46baacf047SPaolo Bonzini 
47baacf047SPaolo Bonzini     err = g_malloc0(sizeof(*err));
48baacf047SPaolo Bonzini     err->msg = g_strdup_vprintf(fmt, ap);
49baacf047SPaolo Bonzini     err->err_class = err_class;
50*1e9b65bbSMarkus Armbruster     err->src = src;
51*1e9b65bbSMarkus Armbruster     err->line = line;
52*1e9b65bbSMarkus Armbruster     err->func = func;
53baacf047SPaolo Bonzini 
545d24ee70SPeter Crosthwaite     if (errp == &error_abort) {
55*1e9b65bbSMarkus Armbruster         error_do_abort(err);
565d24ee70SPeter Crosthwaite     }
575d24ee70SPeter Crosthwaite 
58baacf047SPaolo Bonzini     *errp = err;
59b276d249SMax Reitz 
60b276d249SMax Reitz     errno = saved_errno;
61baacf047SPaolo Bonzini }
62baacf047SPaolo Bonzini 
63*1e9b65bbSMarkus Armbruster void error_set_internal(Error **errp,
64*1e9b65bbSMarkus Armbruster                         const char *src, int line, const char *func,
65*1e9b65bbSMarkus Armbruster                         ErrorClass err_class, const char *fmt, ...)
6655237508SMarkus Armbruster {
6755237508SMarkus Armbruster     va_list ap;
6855237508SMarkus Armbruster 
6955237508SMarkus Armbruster     va_start(ap, fmt);
70*1e9b65bbSMarkus Armbruster     error_setv(errp, src, line, func, err_class, fmt, ap);
7155237508SMarkus Armbruster     va_end(ap);
7255237508SMarkus Armbruster }
7355237508SMarkus Armbruster 
74*1e9b65bbSMarkus Armbruster void error_setg_internal(Error **errp,
75*1e9b65bbSMarkus Armbruster                          const char *src, int line, const char *func,
76*1e9b65bbSMarkus Armbruster                          const char *fmt, ...)
77a9499dddSMarkus Armbruster {
78a9499dddSMarkus Armbruster     va_list ap;
79a9499dddSMarkus Armbruster 
80a9499dddSMarkus Armbruster     va_start(ap, fmt);
81*1e9b65bbSMarkus Armbruster     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
82a9499dddSMarkus Armbruster     va_end(ap);
83a9499dddSMarkus Armbruster }
84a9499dddSMarkus Armbruster 
85*1e9b65bbSMarkus Armbruster void error_setg_errno_internal(Error **errp,
86*1e9b65bbSMarkus Armbruster                                const char *src, int line, const char *func,
87*1e9b65bbSMarkus Armbruster                                int os_errno, const char *fmt, ...)
88baacf047SPaolo Bonzini {
89baacf047SPaolo Bonzini     va_list ap;
9055237508SMarkus Armbruster     char *msg;
91b276d249SMax Reitz     int saved_errno = errno;
92baacf047SPaolo Bonzini 
93baacf047SPaolo Bonzini     if (errp == NULL) {
94baacf047SPaolo Bonzini         return;
95baacf047SPaolo Bonzini     }
96baacf047SPaolo Bonzini 
97baacf047SPaolo Bonzini     va_start(ap, fmt);
98*1e9b65bbSMarkus Armbruster     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
99baacf047SPaolo Bonzini     va_end(ap);
100baacf047SPaolo Bonzini 
10155237508SMarkus Armbruster     if (os_errno != 0) {
10255237508SMarkus Armbruster         msg = (*errp)->msg;
10355237508SMarkus Armbruster         (*errp)->msg = g_strdup_printf("%s: %s", msg, strerror(os_errno));
10455237508SMarkus Armbruster         g_free(msg);
1055d24ee70SPeter Crosthwaite     }
1065d24ee70SPeter Crosthwaite 
107b276d249SMax Reitz     errno = saved_errno;
108baacf047SPaolo Bonzini }
109baacf047SPaolo Bonzini 
110*1e9b65bbSMarkus Armbruster void error_setg_file_open_internal(Error **errp,
111*1e9b65bbSMarkus Armbruster                                    const char *src, int line, const char *func,
112*1e9b65bbSMarkus Armbruster                                    int os_errno, const char *filename)
11354028d75SLuiz Capitulino {
114*1e9b65bbSMarkus Armbruster     error_setg_errno_internal(errp, src, line, func, os_errno,
115*1e9b65bbSMarkus Armbruster                               "Could not open '%s'", filename);
11654028d75SLuiz Capitulino }
11754028d75SLuiz Capitulino 
11820840d4cSTomoki Sekiyama #ifdef _WIN32
11920840d4cSTomoki Sekiyama 
120*1e9b65bbSMarkus Armbruster void error_setg_win32_internal(Error **errp,
121*1e9b65bbSMarkus Armbruster                                const char *src, int line, const char *func,
122*1e9b65bbSMarkus Armbruster                                int win32_err, const char *fmt, ...)
12320840d4cSTomoki Sekiyama {
12420840d4cSTomoki Sekiyama     va_list ap;
12555237508SMarkus Armbruster     char *msg1, *msg2;
12620840d4cSTomoki Sekiyama 
12720840d4cSTomoki Sekiyama     if (errp == NULL) {
12820840d4cSTomoki Sekiyama         return;
12920840d4cSTomoki Sekiyama     }
13020840d4cSTomoki Sekiyama 
13120840d4cSTomoki Sekiyama     va_start(ap, fmt);
132*1e9b65bbSMarkus Armbruster     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
13355237508SMarkus Armbruster     va_end(ap);
13455237508SMarkus Armbruster 
13520840d4cSTomoki Sekiyama     if (win32_err != 0) {
13655237508SMarkus Armbruster         msg1 = (*errp)->msg;
13755237508SMarkus Armbruster         msg2 = g_win32_error_message(win32_err);
13855237508SMarkus Armbruster         (*errp)->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2,
13920840d4cSTomoki Sekiyama                                        (unsigned)win32_err);
14020840d4cSTomoki Sekiyama         g_free(msg2);
14120840d4cSTomoki Sekiyama         g_free(msg1);
14220840d4cSTomoki Sekiyama     }
14320840d4cSTomoki Sekiyama }
14420840d4cSTomoki Sekiyama 
14520840d4cSTomoki Sekiyama #endif
14620840d4cSTomoki Sekiyama 
147baacf047SPaolo Bonzini Error *error_copy(const Error *err)
148baacf047SPaolo Bonzini {
149baacf047SPaolo Bonzini     Error *err_new;
150baacf047SPaolo Bonzini 
151baacf047SPaolo Bonzini     err_new = g_malloc0(sizeof(*err));
152baacf047SPaolo Bonzini     err_new->msg = g_strdup(err->msg);
153baacf047SPaolo Bonzini     err_new->err_class = err->err_class;
154baacf047SPaolo Bonzini 
155baacf047SPaolo Bonzini     return err_new;
156baacf047SPaolo Bonzini }
157baacf047SPaolo Bonzini 
158baacf047SPaolo Bonzini ErrorClass error_get_class(const Error *err)
159baacf047SPaolo Bonzini {
160baacf047SPaolo Bonzini     return err->err_class;
161baacf047SPaolo Bonzini }
162baacf047SPaolo Bonzini 
163baacf047SPaolo Bonzini const char *error_get_pretty(Error *err)
164baacf047SPaolo Bonzini {
165baacf047SPaolo Bonzini     return err->msg;
166baacf047SPaolo Bonzini }
167baacf047SPaolo Bonzini 
1682ee2f1e4SMarkus Armbruster void error_report_err(Error *err)
1692ee2f1e4SMarkus Armbruster {
1702ee2f1e4SMarkus Armbruster     error_report("%s", error_get_pretty(err));
1712ee2f1e4SMarkus Armbruster     error_free(err);
1722ee2f1e4SMarkus Armbruster }
1732ee2f1e4SMarkus Armbruster 
174baacf047SPaolo Bonzini void error_free(Error *err)
175baacf047SPaolo Bonzini {
176baacf047SPaolo Bonzini     if (err) {
177baacf047SPaolo Bonzini         g_free(err->msg);
178baacf047SPaolo Bonzini         g_free(err);
179baacf047SPaolo Bonzini     }
180baacf047SPaolo Bonzini }
181baacf047SPaolo Bonzini 
18264dfefedSMarkus Armbruster void error_propagate(Error **dst_errp, Error *local_err)
183baacf047SPaolo Bonzini {
18464dfefedSMarkus Armbruster     if (local_err && dst_errp == &error_abort) {
185*1e9b65bbSMarkus Armbruster         error_do_abort(local_err);
18664dfefedSMarkus Armbruster     } else if (dst_errp && !*dst_errp) {
18764dfefedSMarkus Armbruster         *dst_errp = local_err;
188baacf047SPaolo Bonzini     } else if (local_err) {
189baacf047SPaolo Bonzini         error_free(local_err);
190baacf047SPaolo Bonzini     }
191baacf047SPaolo Bonzini }
192