xref: /openbmc/qemu/util/error.c (revision 543202c0)
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 
15baacf047SPaolo Bonzini #include "qemu-common.h"
16baacf047SPaolo Bonzini #include "qapi/error.h"
17073a3411SCole Robinson #include "qemu/error-report.h"
18baacf047SPaolo Bonzini 
19baacf047SPaolo Bonzini struct Error
20baacf047SPaolo Bonzini {
21baacf047SPaolo Bonzini     char *msg;
22baacf047SPaolo Bonzini     ErrorClass err_class;
231e9b65bbSMarkus Armbruster     const char *src, *func;
241e9b65bbSMarkus Armbruster     int line;
2550b7b000SEric Blake     GString *hint;
26baacf047SPaolo Bonzini };
27baacf047SPaolo Bonzini 
285d24ee70SPeter Crosthwaite Error *error_abort;
29a29a37b9SMarkus Armbruster Error *error_fatal;
305d24ee70SPeter Crosthwaite 
31a29a37b9SMarkus Armbruster static void error_handle_fatal(Error **errp, Error *err)
321e9b65bbSMarkus Armbruster {
33a29a37b9SMarkus Armbruster     if (errp == &error_abort) {
341e9b65bbSMarkus Armbruster         fprintf(stderr, "Unexpected error in %s() at %s:%d:\n",
351e9b65bbSMarkus Armbruster                 err->func, err->src, err->line);
361e9b65bbSMarkus Armbruster         error_report_err(err);
371e9b65bbSMarkus Armbruster         abort();
381e9b65bbSMarkus Armbruster     }
39a29a37b9SMarkus Armbruster     if (errp == &error_fatal) {
40a29a37b9SMarkus Armbruster         error_report_err(err);
41a29a37b9SMarkus Armbruster         exit(1);
42a29a37b9SMarkus Armbruster     }
43a29a37b9SMarkus Armbruster }
441e9b65bbSMarkus Armbruster 
451e9b65bbSMarkus Armbruster static void error_setv(Error **errp,
461e9b65bbSMarkus Armbruster                        const char *src, int line, const char *func,
471e9b65bbSMarkus Armbruster                        ErrorClass err_class, const char *fmt, va_list ap)
48baacf047SPaolo Bonzini {
49baacf047SPaolo Bonzini     Error *err;
50b276d249SMax Reitz     int saved_errno = errno;
51baacf047SPaolo Bonzini 
52baacf047SPaolo Bonzini     if (errp == NULL) {
53baacf047SPaolo Bonzini         return;
54baacf047SPaolo Bonzini     }
55baacf047SPaolo Bonzini     assert(*errp == NULL);
56baacf047SPaolo Bonzini 
57baacf047SPaolo Bonzini     err = g_malloc0(sizeof(*err));
58baacf047SPaolo Bonzini     err->msg = g_strdup_vprintf(fmt, ap);
59baacf047SPaolo Bonzini     err->err_class = err_class;
601e9b65bbSMarkus Armbruster     err->src = src;
611e9b65bbSMarkus Armbruster     err->line = line;
621e9b65bbSMarkus Armbruster     err->func = func;
63baacf047SPaolo Bonzini 
64a29a37b9SMarkus Armbruster     error_handle_fatal(errp, err);
65baacf047SPaolo Bonzini     *errp = err;
66b276d249SMax Reitz 
67b276d249SMax Reitz     errno = saved_errno;
68baacf047SPaolo Bonzini }
69baacf047SPaolo Bonzini 
701e9b65bbSMarkus Armbruster void error_set_internal(Error **errp,
711e9b65bbSMarkus Armbruster                         const char *src, int line, const char *func,
721e9b65bbSMarkus Armbruster                         ErrorClass err_class, const char *fmt, ...)
7355237508SMarkus Armbruster {
7455237508SMarkus Armbruster     va_list ap;
7555237508SMarkus Armbruster 
7655237508SMarkus Armbruster     va_start(ap, fmt);
771e9b65bbSMarkus Armbruster     error_setv(errp, src, line, func, err_class, fmt, ap);
7855237508SMarkus Armbruster     va_end(ap);
7955237508SMarkus Armbruster }
8055237508SMarkus Armbruster 
811e9b65bbSMarkus Armbruster void error_setg_internal(Error **errp,
821e9b65bbSMarkus Armbruster                          const char *src, int line, const char *func,
831e9b65bbSMarkus Armbruster                          const char *fmt, ...)
84a9499dddSMarkus Armbruster {
85a9499dddSMarkus Armbruster     va_list ap;
86a9499dddSMarkus Armbruster 
87a9499dddSMarkus Armbruster     va_start(ap, fmt);
881e9b65bbSMarkus Armbruster     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
89a9499dddSMarkus Armbruster     va_end(ap);
90a9499dddSMarkus Armbruster }
91a9499dddSMarkus Armbruster 
921e9b65bbSMarkus Armbruster void error_setg_errno_internal(Error **errp,
931e9b65bbSMarkus Armbruster                                const char *src, int line, const char *func,
941e9b65bbSMarkus Armbruster                                int os_errno, const char *fmt, ...)
95baacf047SPaolo Bonzini {
96baacf047SPaolo Bonzini     va_list ap;
9755237508SMarkus Armbruster     char *msg;
98b276d249SMax Reitz     int saved_errno = errno;
99baacf047SPaolo Bonzini 
100baacf047SPaolo Bonzini     if (errp == NULL) {
101baacf047SPaolo Bonzini         return;
102baacf047SPaolo Bonzini     }
103baacf047SPaolo Bonzini 
104baacf047SPaolo Bonzini     va_start(ap, fmt);
1051e9b65bbSMarkus Armbruster     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
106baacf047SPaolo Bonzini     va_end(ap);
107baacf047SPaolo Bonzini 
10855237508SMarkus Armbruster     if (os_errno != 0) {
10955237508SMarkus Armbruster         msg = (*errp)->msg;
11055237508SMarkus Armbruster         (*errp)->msg = g_strdup_printf("%s: %s", msg, strerror(os_errno));
11155237508SMarkus Armbruster         g_free(msg);
1125d24ee70SPeter Crosthwaite     }
1135d24ee70SPeter Crosthwaite 
114b276d249SMax Reitz     errno = saved_errno;
115baacf047SPaolo Bonzini }
116baacf047SPaolo Bonzini 
1171e9b65bbSMarkus Armbruster void error_setg_file_open_internal(Error **errp,
1181e9b65bbSMarkus Armbruster                                    const char *src, int line, const char *func,
1191e9b65bbSMarkus Armbruster                                    int os_errno, const char *filename)
12054028d75SLuiz Capitulino {
1211e9b65bbSMarkus Armbruster     error_setg_errno_internal(errp, src, line, func, os_errno,
1221e9b65bbSMarkus Armbruster                               "Could not open '%s'", filename);
12354028d75SLuiz Capitulino }
12454028d75SLuiz Capitulino 
12550b7b000SEric Blake void error_append_hint(Error **errp, const char *fmt, ...)
12650b7b000SEric Blake {
12750b7b000SEric Blake     va_list ap;
12850b7b000SEric Blake     int saved_errno = errno;
12950b7b000SEric Blake     Error *err;
13050b7b000SEric Blake 
13150b7b000SEric Blake     if (!errp) {
13250b7b000SEric Blake         return;
13350b7b000SEric Blake     }
13450b7b000SEric Blake     err = *errp;
13550b7b000SEric Blake     assert(err && errp != &error_abort);
13650b7b000SEric Blake 
13750b7b000SEric Blake     if (!err->hint) {
13850b7b000SEric Blake         err->hint = g_string_new(NULL);
13950b7b000SEric Blake     }
14050b7b000SEric Blake     va_start(ap, fmt);
14150b7b000SEric Blake     g_string_append_vprintf(err->hint, fmt, ap);
14250b7b000SEric Blake     va_end(ap);
14350b7b000SEric Blake 
14450b7b000SEric Blake     errno = saved_errno;
14550b7b000SEric Blake }
14650b7b000SEric Blake 
14720840d4cSTomoki Sekiyama #ifdef _WIN32
14820840d4cSTomoki Sekiyama 
1491e9b65bbSMarkus Armbruster void error_setg_win32_internal(Error **errp,
1501e9b65bbSMarkus Armbruster                                const char *src, int line, const char *func,
1511e9b65bbSMarkus Armbruster                                int win32_err, const char *fmt, ...)
15220840d4cSTomoki Sekiyama {
15320840d4cSTomoki Sekiyama     va_list ap;
15455237508SMarkus Armbruster     char *msg1, *msg2;
15520840d4cSTomoki Sekiyama 
15620840d4cSTomoki Sekiyama     if (errp == NULL) {
15720840d4cSTomoki Sekiyama         return;
15820840d4cSTomoki Sekiyama     }
15920840d4cSTomoki Sekiyama 
16020840d4cSTomoki Sekiyama     va_start(ap, fmt);
1611e9b65bbSMarkus Armbruster     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
16255237508SMarkus Armbruster     va_end(ap);
16355237508SMarkus Armbruster 
16420840d4cSTomoki Sekiyama     if (win32_err != 0) {
16555237508SMarkus Armbruster         msg1 = (*errp)->msg;
16655237508SMarkus Armbruster         msg2 = g_win32_error_message(win32_err);
16755237508SMarkus Armbruster         (*errp)->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2,
16820840d4cSTomoki Sekiyama                                        (unsigned)win32_err);
16920840d4cSTomoki Sekiyama         g_free(msg2);
17020840d4cSTomoki Sekiyama         g_free(msg1);
17120840d4cSTomoki Sekiyama     }
17220840d4cSTomoki Sekiyama }
17320840d4cSTomoki Sekiyama 
17420840d4cSTomoki Sekiyama #endif
17520840d4cSTomoki Sekiyama 
176baacf047SPaolo Bonzini Error *error_copy(const Error *err)
177baacf047SPaolo Bonzini {
178baacf047SPaolo Bonzini     Error *err_new;
179baacf047SPaolo Bonzini 
180baacf047SPaolo Bonzini     err_new = g_malloc0(sizeof(*err));
181baacf047SPaolo Bonzini     err_new->msg = g_strdup(err->msg);
182baacf047SPaolo Bonzini     err_new->err_class = err->err_class;
18388e2ce29SEric Blake     err_new->src = err->src;
18488e2ce29SEric Blake     err_new->line = err->line;
18588e2ce29SEric Blake     err_new->func = err->func;
18650b7b000SEric Blake     if (err->hint) {
18750b7b000SEric Blake         err_new->hint = g_string_new(err->hint->str);
18850b7b000SEric Blake     }
189baacf047SPaolo Bonzini 
190baacf047SPaolo Bonzini     return err_new;
191baacf047SPaolo Bonzini }
192baacf047SPaolo Bonzini 
193baacf047SPaolo Bonzini ErrorClass error_get_class(const Error *err)
194baacf047SPaolo Bonzini {
195baacf047SPaolo Bonzini     return err->err_class;
196baacf047SPaolo Bonzini }
197baacf047SPaolo Bonzini 
198baacf047SPaolo Bonzini const char *error_get_pretty(Error *err)
199baacf047SPaolo Bonzini {
200baacf047SPaolo Bonzini     return err->msg;
201baacf047SPaolo Bonzini }
202baacf047SPaolo Bonzini 
2032ee2f1e4SMarkus Armbruster void error_report_err(Error *err)
2042ee2f1e4SMarkus Armbruster {
2052ee2f1e4SMarkus Armbruster     error_report("%s", error_get_pretty(err));
20650b7b000SEric Blake     if (err->hint) {
207*543202c0SMarkus Armbruster         error_printf_unless_qmp("%s", err->hint->str);
20850b7b000SEric Blake     }
2092ee2f1e4SMarkus Armbruster     error_free(err);
2102ee2f1e4SMarkus Armbruster }
2112ee2f1e4SMarkus Armbruster 
212baacf047SPaolo Bonzini void error_free(Error *err)
213baacf047SPaolo Bonzini {
214baacf047SPaolo Bonzini     if (err) {
215baacf047SPaolo Bonzini         g_free(err->msg);
21650b7b000SEric Blake         if (err->hint) {
21750b7b000SEric Blake             g_string_free(err->hint, true);
21850b7b000SEric Blake         }
219baacf047SPaolo Bonzini         g_free(err);
220baacf047SPaolo Bonzini     }
221baacf047SPaolo Bonzini }
222baacf047SPaolo Bonzini 
223a12a5a1aSEric Blake void error_free_or_abort(Error **errp)
224a12a5a1aSEric Blake {
225a12a5a1aSEric Blake     assert(errp && *errp);
226a12a5a1aSEric Blake     error_free(*errp);
227a12a5a1aSEric Blake     *errp = NULL;
228a12a5a1aSEric Blake }
229a12a5a1aSEric Blake 
23064dfefedSMarkus Armbruster void error_propagate(Error **dst_errp, Error *local_err)
231baacf047SPaolo Bonzini {
232a29a37b9SMarkus Armbruster     if (!local_err) {
233a29a37b9SMarkus Armbruster         return;
234a29a37b9SMarkus Armbruster     }
235a29a37b9SMarkus Armbruster     error_handle_fatal(dst_errp, local_err);
236a29a37b9SMarkus Armbruster     if (dst_errp && !*dst_errp) {
23764dfefedSMarkus Armbruster         *dst_errp = local_err;
238a29a37b9SMarkus Armbruster     } else {
239baacf047SPaolo Bonzini         error_free(local_err);
240baacf047SPaolo Bonzini     }
241baacf047SPaolo Bonzini }
242