xref: /openbmc/qemu/util/error.c (revision 3ffef1a5)
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"
16da34e65cSMarkus Armbruster #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;
30*3ffef1a5SMarc-André Lureau Error *error_warn;
315d24ee70SPeter Crosthwaite 
32*3ffef1a5SMarc-André Lureau static void error_handle(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);
37b922c050SVladimir Sementsov-Ogievskiy         error_report("%s", error_get_pretty(err));
38b922c050SVladimir Sementsov-Ogievskiy         if (err->hint) {
39b922c050SVladimir Sementsov-Ogievskiy             error_printf("%s", err->hint->str);
40b922c050SVladimir Sementsov-Ogievskiy         }
411e9b65bbSMarkus Armbruster         abort();
421e9b65bbSMarkus Armbruster     }
43a29a37b9SMarkus Armbruster     if (errp == &error_fatal) {
44a29a37b9SMarkus Armbruster         error_report_err(err);
45a29a37b9SMarkus Armbruster         exit(1);
46a29a37b9SMarkus Armbruster     }
47*3ffef1a5SMarc-André Lureau     if (errp == &error_warn) {
48*3ffef1a5SMarc-André Lureau         warn_report_err(err);
49*3ffef1a5SMarc-André Lureau     }
50a29a37b9SMarkus Armbruster }
511e9b65bbSMarkus Armbruster 
52beede7e8SDaniel P. Berrangé G_GNUC_PRINTF(6, 0)
531e9b65bbSMarkus Armbruster static void error_setv(Error **errp,
541e9b65bbSMarkus Armbruster                        const char *src, int line, const char *func,
5520e2dec1SDaniel P. Berrange                        ErrorClass err_class, const char *fmt, va_list ap,
5620e2dec1SDaniel P. Berrange                        const char *suffix)
57baacf047SPaolo Bonzini {
58baacf047SPaolo Bonzini     Error *err;
59b276d249SMax Reitz     int saved_errno = errno;
60baacf047SPaolo Bonzini 
61baacf047SPaolo Bonzini     if (errp == NULL) {
62baacf047SPaolo Bonzini         return;
63baacf047SPaolo Bonzini     }
64baacf047SPaolo Bonzini     assert(*errp == NULL);
65baacf047SPaolo Bonzini 
66baacf047SPaolo Bonzini     err = g_malloc0(sizeof(*err));
67baacf047SPaolo Bonzini     err->msg = g_strdup_vprintf(fmt, ap);
6820e2dec1SDaniel P. Berrange     if (suffix) {
6920e2dec1SDaniel P. Berrange         char *msg = err->msg;
7020e2dec1SDaniel P. Berrange         err->msg = g_strdup_printf("%s: %s", msg, suffix);
7120e2dec1SDaniel P. Berrange         g_free(msg);
7220e2dec1SDaniel P. Berrange     }
73baacf047SPaolo Bonzini     err->err_class = err_class;
741e9b65bbSMarkus Armbruster     err->src = src;
751e9b65bbSMarkus Armbruster     err->line = line;
761e9b65bbSMarkus Armbruster     err->func = func;
77baacf047SPaolo Bonzini 
78*3ffef1a5SMarc-André Lureau     error_handle(errp, err);
79baacf047SPaolo Bonzini     *errp = err;
80b276d249SMax Reitz 
81b276d249SMax Reitz     errno = saved_errno;
82baacf047SPaolo Bonzini }
83baacf047SPaolo Bonzini 
841e9b65bbSMarkus Armbruster void error_set_internal(Error **errp,
851e9b65bbSMarkus Armbruster                         const char *src, int line, const char *func,
861e9b65bbSMarkus Armbruster                         ErrorClass err_class, const char *fmt, ...)
8755237508SMarkus Armbruster {
8855237508SMarkus Armbruster     va_list ap;
8955237508SMarkus Armbruster 
9055237508SMarkus Armbruster     va_start(ap, fmt);
9120e2dec1SDaniel P. Berrange     error_setv(errp, src, line, func, err_class, fmt, ap, NULL);
9255237508SMarkus Armbruster     va_end(ap);
9355237508SMarkus Armbruster }
9455237508SMarkus Armbruster 
951e9b65bbSMarkus Armbruster void error_setg_internal(Error **errp,
961e9b65bbSMarkus Armbruster                          const char *src, int line, const char *func,
971e9b65bbSMarkus Armbruster                          const char *fmt, ...)
98a9499dddSMarkus Armbruster {
99a9499dddSMarkus Armbruster     va_list ap;
100a9499dddSMarkus Armbruster 
101a9499dddSMarkus Armbruster     va_start(ap, fmt);
10220e2dec1SDaniel P. Berrange     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap, NULL);
103a9499dddSMarkus Armbruster     va_end(ap);
104a9499dddSMarkus Armbruster }
105a9499dddSMarkus Armbruster 
1061e9b65bbSMarkus Armbruster void error_setg_errno_internal(Error **errp,
1071e9b65bbSMarkus Armbruster                                const char *src, int line, const char *func,
1081e9b65bbSMarkus Armbruster                                int os_errno, const char *fmt, ...)
109baacf047SPaolo Bonzini {
110baacf047SPaolo Bonzini     va_list ap;
111b276d249SMax Reitz     int saved_errno = errno;
112baacf047SPaolo Bonzini 
113baacf047SPaolo Bonzini     va_start(ap, fmt);
11420e2dec1SDaniel P. Berrange     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap,
11520e2dec1SDaniel P. Berrange                os_errno != 0 ? strerror(os_errno) : NULL);
116baacf047SPaolo Bonzini     va_end(ap);
117baacf047SPaolo Bonzini 
118b276d249SMax Reitz     errno = saved_errno;
119baacf047SPaolo Bonzini }
120baacf047SPaolo Bonzini 
1211e9b65bbSMarkus Armbruster void error_setg_file_open_internal(Error **errp,
1221e9b65bbSMarkus Armbruster                                    const char *src, int line, const char *func,
1231e9b65bbSMarkus Armbruster                                    int os_errno, const char *filename)
12454028d75SLuiz Capitulino {
1251e9b65bbSMarkus Armbruster     error_setg_errno_internal(errp, src, line, func, os_errno,
1261e9b65bbSMarkus Armbruster                               "Could not open '%s'", filename);
12754028d75SLuiz Capitulino }
12854028d75SLuiz Capitulino 
12949fbc723SVladimir Sementsov-Ogievskiy void error_vprepend(Error *const *errp, const char *fmt, va_list ap)
1308277d2aaSMarkus Armbruster {
1318277d2aaSMarkus Armbruster     GString *newmsg;
1328277d2aaSMarkus Armbruster 
1338277d2aaSMarkus Armbruster     if (!errp) {
1348277d2aaSMarkus Armbruster         return;
1358277d2aaSMarkus Armbruster     }
1368277d2aaSMarkus Armbruster 
1378277d2aaSMarkus Armbruster     newmsg = g_string_new(NULL);
1388277d2aaSMarkus Armbruster     g_string_vprintf(newmsg, fmt, ap);
1398277d2aaSMarkus Armbruster     g_string_append(newmsg, (*errp)->msg);
140536eeea8SMax Reitz     g_free((*errp)->msg);
1418277d2aaSMarkus Armbruster     (*errp)->msg = g_string_free(newmsg, 0);
1428277d2aaSMarkus Armbruster }
1438277d2aaSMarkus Armbruster 
14449fbc723SVladimir Sementsov-Ogievskiy void error_prepend(Error *const *errp, const char *fmt, ...)
1458277d2aaSMarkus Armbruster {
1468277d2aaSMarkus Armbruster     va_list ap;
1478277d2aaSMarkus Armbruster 
1488277d2aaSMarkus Armbruster     va_start(ap, fmt);
1498277d2aaSMarkus Armbruster     error_vprepend(errp, fmt, ap);
1508277d2aaSMarkus Armbruster     va_end(ap);
1518277d2aaSMarkus Armbruster }
1528277d2aaSMarkus Armbruster 
15349fbc723SVladimir Sementsov-Ogievskiy void error_append_hint(Error *const *errp, const char *fmt, ...)
15450b7b000SEric Blake {
15550b7b000SEric Blake     va_list ap;
15650b7b000SEric Blake     int saved_errno = errno;
15750b7b000SEric Blake     Error *err;
15850b7b000SEric Blake 
15950b7b000SEric Blake     if (!errp) {
16050b7b000SEric Blake         return;
16150b7b000SEric Blake     }
16250b7b000SEric Blake     err = *errp;
163f4d0064aSMarkus Armbruster     assert(err && errp != &error_abort && errp != &error_fatal);
16450b7b000SEric Blake 
16550b7b000SEric Blake     if (!err->hint) {
16650b7b000SEric Blake         err->hint = g_string_new(NULL);
16750b7b000SEric Blake     }
16850b7b000SEric Blake     va_start(ap, fmt);
16950b7b000SEric Blake     g_string_append_vprintf(err->hint, fmt, ap);
17050b7b000SEric Blake     va_end(ap);
17150b7b000SEric Blake 
17250b7b000SEric Blake     errno = saved_errno;
17350b7b000SEric Blake }
17450b7b000SEric Blake 
17520840d4cSTomoki Sekiyama #ifdef _WIN32
17620840d4cSTomoki Sekiyama 
1771e9b65bbSMarkus Armbruster void error_setg_win32_internal(Error **errp,
1781e9b65bbSMarkus Armbruster                                const char *src, int line, const char *func,
1791e9b65bbSMarkus Armbruster                                int win32_err, const char *fmt, ...)
18020840d4cSTomoki Sekiyama {
18120840d4cSTomoki Sekiyama     va_list ap;
18220e2dec1SDaniel P. Berrange     char *suffix = NULL;
18320840d4cSTomoki Sekiyama 
18420840d4cSTomoki Sekiyama     if (errp == NULL) {
18520840d4cSTomoki Sekiyama         return;
18620840d4cSTomoki Sekiyama     }
18720840d4cSTomoki Sekiyama 
18820e2dec1SDaniel P. Berrange     if (win32_err != 0) {
18920e2dec1SDaniel P. Berrange         suffix = g_win32_error_message(win32_err);
19020e2dec1SDaniel P. Berrange     }
19120e2dec1SDaniel P. Berrange 
19220840d4cSTomoki Sekiyama     va_start(ap, fmt);
19320e2dec1SDaniel P. Berrange     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR,
19420e2dec1SDaniel P. Berrange                fmt, ap, suffix);
19555237508SMarkus Armbruster     va_end(ap);
19655237508SMarkus Armbruster 
19720e2dec1SDaniel P. Berrange     g_free(suffix);
19820840d4cSTomoki Sekiyama }
19920840d4cSTomoki Sekiyama 
20020840d4cSTomoki Sekiyama #endif
20120840d4cSTomoki Sekiyama 
202baacf047SPaolo Bonzini Error *error_copy(const Error *err)
203baacf047SPaolo Bonzini {
204baacf047SPaolo Bonzini     Error *err_new;
205baacf047SPaolo Bonzini 
206baacf047SPaolo Bonzini     err_new = g_malloc0(sizeof(*err));
207baacf047SPaolo Bonzini     err_new->msg = g_strdup(err->msg);
208baacf047SPaolo Bonzini     err_new->err_class = err->err_class;
20988e2ce29SEric Blake     err_new->src = err->src;
21088e2ce29SEric Blake     err_new->line = err->line;
21188e2ce29SEric Blake     err_new->func = err->func;
21250b7b000SEric Blake     if (err->hint) {
21350b7b000SEric Blake         err_new->hint = g_string_new(err->hint->str);
21450b7b000SEric Blake     }
215baacf047SPaolo Bonzini 
216baacf047SPaolo Bonzini     return err_new;
217baacf047SPaolo Bonzini }
218baacf047SPaolo Bonzini 
219baacf047SPaolo Bonzini ErrorClass error_get_class(const Error *err)
220baacf047SPaolo Bonzini {
221baacf047SPaolo Bonzini     return err->err_class;
222baacf047SPaolo Bonzini }
223baacf047SPaolo Bonzini 
224d59ce6f3SDaniel P. Berrange const char *error_get_pretty(const Error *err)
225baacf047SPaolo Bonzini {
226baacf047SPaolo Bonzini     return err->msg;
227baacf047SPaolo Bonzini }
228baacf047SPaolo Bonzini 
2292ee2f1e4SMarkus Armbruster void error_report_err(Error *err)
2302ee2f1e4SMarkus Armbruster {
2312ee2f1e4SMarkus Armbruster     error_report("%s", error_get_pretty(err));
23250b7b000SEric Blake     if (err->hint) {
2334c8b7c8bSMarkus Armbruster         error_printf("%s", err->hint->str);
23450b7b000SEric Blake     }
2352ee2f1e4SMarkus Armbruster     error_free(err);
2362ee2f1e4SMarkus Armbruster }
2372ee2f1e4SMarkus Armbruster 
238e43ead1dSAlistair Francis void warn_report_err(Error *err)
239e43ead1dSAlistair Francis {
240e43ead1dSAlistair Francis     warn_report("%s", error_get_pretty(err));
241e43ead1dSAlistair Francis     if (err->hint) {
2424c8b7c8bSMarkus Armbruster         error_printf("%s", err->hint->str);
243e43ead1dSAlistair Francis     }
244e43ead1dSAlistair Francis     error_free(err);
245e43ead1dSAlistair Francis }
246e43ead1dSAlistair Francis 
2478277d2aaSMarkus Armbruster void error_reportf_err(Error *err, const char *fmt, ...)
2488277d2aaSMarkus Armbruster {
2498277d2aaSMarkus Armbruster     va_list ap;
2508277d2aaSMarkus Armbruster 
2518277d2aaSMarkus Armbruster     va_start(ap, fmt);
2528277d2aaSMarkus Armbruster     error_vprepend(&err, fmt, ap);
2538277d2aaSMarkus Armbruster     va_end(ap);
2548277d2aaSMarkus Armbruster     error_report_err(err);
2558277d2aaSMarkus Armbruster }
2568277d2aaSMarkus Armbruster 
257e43ead1dSAlistair Francis 
258e43ead1dSAlistair Francis void warn_reportf_err(Error *err, const char *fmt, ...)
259e43ead1dSAlistair Francis {
260e43ead1dSAlistair Francis     va_list ap;
261e43ead1dSAlistair Francis 
262e43ead1dSAlistair Francis     va_start(ap, fmt);
263e43ead1dSAlistair Francis     error_vprepend(&err, fmt, ap);
264e43ead1dSAlistair Francis     va_end(ap);
265e43ead1dSAlistair Francis     warn_report_err(err);
266e43ead1dSAlistair Francis }
267e43ead1dSAlistair Francis 
268baacf047SPaolo Bonzini void error_free(Error *err)
269baacf047SPaolo Bonzini {
270baacf047SPaolo Bonzini     if (err) {
271baacf047SPaolo Bonzini         g_free(err->msg);
27250b7b000SEric Blake         if (err->hint) {
27350b7b000SEric Blake             g_string_free(err->hint, true);
27450b7b000SEric Blake         }
275baacf047SPaolo Bonzini         g_free(err);
276baacf047SPaolo Bonzini     }
277baacf047SPaolo Bonzini }
278baacf047SPaolo Bonzini 
279a12a5a1aSEric Blake void error_free_or_abort(Error **errp)
280a12a5a1aSEric Blake {
281a12a5a1aSEric Blake     assert(errp && *errp);
282a12a5a1aSEric Blake     error_free(*errp);
283a12a5a1aSEric Blake     *errp = NULL;
284a12a5a1aSEric Blake }
285a12a5a1aSEric Blake 
28664dfefedSMarkus Armbruster void error_propagate(Error **dst_errp, Error *local_err)
287baacf047SPaolo Bonzini {
288a29a37b9SMarkus Armbruster     if (!local_err) {
289a29a37b9SMarkus Armbruster         return;
290a29a37b9SMarkus Armbruster     }
291*3ffef1a5SMarc-André Lureau     error_handle(dst_errp, local_err);
292a29a37b9SMarkus Armbruster     if (dst_errp && !*dst_errp) {
29364dfefedSMarkus Armbruster         *dst_errp = local_err;
294a29a37b9SMarkus Armbruster     } else {
295baacf047SPaolo Bonzini         error_free(local_err);
296baacf047SPaolo Bonzini     }
297baacf047SPaolo Bonzini }
2984b576648SMarkus Armbruster 
2994b576648SMarkus Armbruster void error_propagate_prepend(Error **dst_errp, Error *err,
3004b576648SMarkus Armbruster                              const char *fmt, ...)
3014b576648SMarkus Armbruster {
3024b576648SMarkus Armbruster     va_list ap;
3034b576648SMarkus Armbruster 
3044b576648SMarkus Armbruster     if (dst_errp && !*dst_errp) {
3054b576648SMarkus Armbruster         va_start(ap, fmt);
3064b576648SMarkus Armbruster         error_vprepend(&err, fmt, ap);
3074b576648SMarkus Armbruster         va_end(ap);
3084b576648SMarkus Armbruster     } /* else error is being ignored, don't bother with prepending */
3094b576648SMarkus Armbruster     error_propagate(dst_errp, err);
3104b576648SMarkus Armbruster }
311