xref: /openbmc/qemu/util/error.c (revision c964b660)
1 /*
2  * QEMU Error Objects
3  *
4  * Copyright IBM, Corp. 2011
5  * Copyright (C) 2011-2015 Red Hat, Inc.
6  *
7  * Authors:
8  *  Anthony Liguori   <aliguori@us.ibm.com>
9  *  Markus Armbruster <armbru@redhat.com>,
10  *
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  */
14 
15 #include "qemu/osdep.h"
16 #include "qemu-common.h"
17 #include "qemu/error-report.h"
18 
19 struct Error
20 {
21     char *msg;
22     ErrorClass err_class;
23     const char *src, *func;
24     int line;
25     GString *hint;
26 };
27 
28 Error *error_abort;
29 Error *error_fatal;
30 
31 static void error_handle_fatal(Error **errp, Error *err)
32 {
33     if (errp == &error_abort) {
34         fprintf(stderr, "Unexpected error in %s() at %s:%d:\n",
35                 err->func, err->src, err->line);
36         error_report_err(err);
37         abort();
38     }
39     if (errp == &error_fatal) {
40         error_report_err(err);
41         exit(1);
42     }
43 }
44 
45 static void error_setv(Error **errp,
46                        const char *src, int line, const char *func,
47                        ErrorClass err_class, const char *fmt, va_list ap)
48 {
49     Error *err;
50     int saved_errno = errno;
51 
52     if (errp == NULL) {
53         return;
54     }
55     assert(*errp == NULL);
56 
57     err = g_malloc0(sizeof(*err));
58     err->msg = g_strdup_vprintf(fmt, ap);
59     err->err_class = err_class;
60     err->src = src;
61     err->line = line;
62     err->func = func;
63 
64     error_handle_fatal(errp, err);
65     *errp = err;
66 
67     errno = saved_errno;
68 }
69 
70 void error_set_internal(Error **errp,
71                         const char *src, int line, const char *func,
72                         ErrorClass err_class, const char *fmt, ...)
73 {
74     va_list ap;
75 
76     va_start(ap, fmt);
77     error_setv(errp, src, line, func, err_class, fmt, ap);
78     va_end(ap);
79 }
80 
81 void error_setg_internal(Error **errp,
82                          const char *src, int line, const char *func,
83                          const char *fmt, ...)
84 {
85     va_list ap;
86 
87     va_start(ap, fmt);
88     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
89     va_end(ap);
90 }
91 
92 void error_setg_errno_internal(Error **errp,
93                                const char *src, int line, const char *func,
94                                int os_errno, const char *fmt, ...)
95 {
96     va_list ap;
97     char *msg;
98     int saved_errno = errno;
99 
100     if (errp == NULL) {
101         return;
102     }
103 
104     va_start(ap, fmt);
105     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
106     va_end(ap);
107 
108     if (os_errno != 0) {
109         msg = (*errp)->msg;
110         (*errp)->msg = g_strdup_printf("%s: %s", msg, strerror(os_errno));
111         g_free(msg);
112     }
113 
114     errno = saved_errno;
115 }
116 
117 void error_setg_file_open_internal(Error **errp,
118                                    const char *src, int line, const char *func,
119                                    int os_errno, const char *filename)
120 {
121     error_setg_errno_internal(errp, src, line, func, os_errno,
122                               "Could not open '%s'", filename);
123 }
124 
125 void error_vprepend(Error **errp, const char *fmt, va_list ap)
126 {
127     GString *newmsg;
128 
129     if (!errp) {
130         return;
131     }
132 
133     newmsg = g_string_new(NULL);
134     g_string_vprintf(newmsg, fmt, ap);
135     g_string_append(newmsg, (*errp)->msg);
136     (*errp)->msg = g_string_free(newmsg, 0);
137 }
138 
139 void error_prepend(Error **errp, const char *fmt, ...)
140 {
141     va_list ap;
142 
143     va_start(ap, fmt);
144     error_vprepend(errp, fmt, ap);
145     va_end(ap);
146 }
147 
148 void error_append_hint(Error **errp, const char *fmt, ...)
149 {
150     va_list ap;
151     int saved_errno = errno;
152     Error *err;
153 
154     if (!errp) {
155         return;
156     }
157     err = *errp;
158     assert(err && errp != &error_abort && errp != &error_fatal);
159 
160     if (!err->hint) {
161         err->hint = g_string_new(NULL);
162     }
163     va_start(ap, fmt);
164     g_string_append_vprintf(err->hint, fmt, ap);
165     va_end(ap);
166 
167     errno = saved_errno;
168 }
169 
170 #ifdef _WIN32
171 
172 void error_setg_win32_internal(Error **errp,
173                                const char *src, int line, const char *func,
174                                int win32_err, const char *fmt, ...)
175 {
176     va_list ap;
177     char *msg1, *msg2;
178 
179     if (errp == NULL) {
180         return;
181     }
182 
183     va_start(ap, fmt);
184     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
185     va_end(ap);
186 
187     if (win32_err != 0) {
188         msg1 = (*errp)->msg;
189         msg2 = g_win32_error_message(win32_err);
190         (*errp)->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2,
191                                        (unsigned)win32_err);
192         g_free(msg2);
193         g_free(msg1);
194     }
195 }
196 
197 #endif
198 
199 Error *error_copy(const Error *err)
200 {
201     Error *err_new;
202 
203     err_new = g_malloc0(sizeof(*err));
204     err_new->msg = g_strdup(err->msg);
205     err_new->err_class = err->err_class;
206     err_new->src = err->src;
207     err_new->line = err->line;
208     err_new->func = err->func;
209     if (err->hint) {
210         err_new->hint = g_string_new(err->hint->str);
211     }
212 
213     return err_new;
214 }
215 
216 ErrorClass error_get_class(const Error *err)
217 {
218     return err->err_class;
219 }
220 
221 const char *error_get_pretty(Error *err)
222 {
223     return err->msg;
224 }
225 
226 void error_report_err(Error *err)
227 {
228     error_report("%s", error_get_pretty(err));
229     if (err->hint) {
230         error_printf_unless_qmp("%s", err->hint->str);
231     }
232     error_free(err);
233 }
234 
235 void error_reportf_err(Error *err, const char *fmt, ...)
236 {
237     va_list ap;
238 
239     va_start(ap, fmt);
240     error_vprepend(&err, fmt, ap);
241     va_end(ap);
242     error_report_err(err);
243 }
244 
245 void error_free(Error *err)
246 {
247     if (err) {
248         g_free(err->msg);
249         if (err->hint) {
250             g_string_free(err->hint, true);
251         }
252         g_free(err);
253     }
254 }
255 
256 void error_free_or_abort(Error **errp)
257 {
258     assert(errp && *errp);
259     error_free(*errp);
260     *errp = NULL;
261 }
262 
263 void error_propagate(Error **dst_errp, Error *local_err)
264 {
265     if (!local_err) {
266         return;
267     }
268     error_handle_fatal(dst_errp, local_err);
269     if (dst_errp && !*dst_errp) {
270         *dst_errp = local_err;
271     } else {
272         error_free(local_err);
273     }
274 }
275