xref: /qemu/util/error.c (revision 96215036f47403438c7c7869b7cd419bd7a11f82)
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 "qapi/error.h"
17 #include "qemu/error-report.h"
18 #include "qapi/error-internal.h"
19 
20 Error *error_abort;
21 Error *error_fatal;
22 Error *error_warn;
23 
error_handle(Error ** errp,Error * err)24 static void error_handle(Error **errp, Error *err)
25 {
26     if (errp == &error_abort) {
27         if (err->func) {
28             fprintf(stderr, "Unexpected error in %s() at %.*s:%d:\n",
29                     err->func, err->src_len, err->src, err->line);
30         } else {
31             fprintf(stderr, "Unexpected error at %.*s:%d:\n",
32 		    err->src_len, err->src, err->line);
33         }
34         error_report("%s", error_get_pretty(err));
35         if (err->hint) {
36             error_printf("%s", err->hint->str);
37         }
38         abort();
39     }
40     if (errp == &error_fatal) {
41         error_report_err(err);
42         exit(1);
43     }
44     if (errp == &error_warn) {
45         warn_report_err(err);
46     } else if (errp && !*errp) {
47         *errp = err;
48     } else {
49         error_free(err);
50     }
51 }
52 
53 G_GNUC_PRINTF(6, 0)
error_setv(Error ** errp,const char * src,int line,const char * func,ErrorClass err_class,const char * fmt,va_list ap,const char * suffix)54 static void error_setv(Error **errp,
55                        const char *src, int line, const char *func,
56                        ErrorClass err_class, const char *fmt, va_list ap,
57                        const char *suffix)
58 {
59     Error *err;
60     int saved_errno = errno;
61 
62     if (errp == NULL) {
63         return;
64     }
65     assert(*errp == NULL);
66 
67     err = g_malloc0(sizeof(*err));
68     err->msg = g_strdup_vprintf(fmt, ap);
69     if (suffix) {
70         char *msg = err->msg;
71         err->msg = g_strdup_printf("%s: %s", msg, suffix);
72         g_free(msg);
73     }
74     err->err_class = err_class;
75     err->src_len = -1;
76     err->src = src;
77     err->line = line;
78     err->func = func;
79 
80     error_handle(errp, err);
81 
82     errno = saved_errno;
83 }
84 
error_set_internal(Error ** errp,const char * src,int line,const char * func,ErrorClass err_class,const char * fmt,...)85 void error_set_internal(Error **errp,
86                         const char *src, int line, const char *func,
87                         ErrorClass err_class, const char *fmt, ...)
88 {
89     va_list ap;
90 
91     va_start(ap, fmt);
92     error_setv(errp, src, line, func, err_class, fmt, ap, NULL);
93     va_end(ap);
94 }
95 
error_setg_internal(Error ** errp,const char * src,int line,const char * func,const char * fmt,...)96 void error_setg_internal(Error **errp,
97                          const char *src, int line, const char *func,
98                          const char *fmt, ...)
99 {
100     va_list ap;
101 
102     va_start(ap, fmt);
103     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap, NULL);
104     va_end(ap);
105 }
106 
error_setg_errno_internal(Error ** errp,const char * src,int line,const char * func,int os_errno,const char * fmt,...)107 void error_setg_errno_internal(Error **errp,
108                                const char *src, int line, const char *func,
109                                int os_errno, const char *fmt, ...)
110 {
111     va_list ap;
112     int saved_errno = errno;
113 
114     va_start(ap, fmt);
115     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap,
116                os_errno != 0 ? strerror(os_errno) : NULL);
117     va_end(ap);
118 
119     errno = saved_errno;
120 }
121 
error_setg_file_open_internal(Error ** errp,const char * src,int line,const char * func,int os_errno,const char * filename)122 void error_setg_file_open_internal(Error **errp,
123                                    const char *src, int line, const char *func,
124                                    int os_errno, const char *filename)
125 {
126     error_setg_errno_internal(errp, src, line, func, os_errno,
127                               "Could not open '%s'", filename);
128 }
129 
error_vprepend(Error * const * errp,const char * fmt,va_list ap)130 void error_vprepend(Error *const *errp, const char *fmt, va_list ap)
131 {
132     GString *newmsg;
133 
134     if (!errp) {
135         return;
136     }
137 
138     newmsg = g_string_new(NULL);
139     g_string_vprintf(newmsg, fmt, ap);
140     g_string_append(newmsg, (*errp)->msg);
141     g_free((*errp)->msg);
142     (*errp)->msg = g_string_free(newmsg, 0);
143 }
144 
error_prepend(Error * const * errp,const char * fmt,...)145 void error_prepend(Error *const *errp, const char *fmt, ...)
146 {
147     va_list ap;
148 
149     va_start(ap, fmt);
150     error_vprepend(errp, fmt, ap);
151     va_end(ap);
152 }
153 
error_append_hint(Error * const * errp,const char * fmt,...)154 void error_append_hint(Error *const *errp, const char *fmt, ...)
155 {
156     va_list ap;
157     int saved_errno = errno;
158     Error *err;
159 
160     if (!errp) {
161         return;
162     }
163     err = *errp;
164     assert(err && errp != &error_abort && errp != &error_fatal);
165 
166     if (!err->hint) {
167         err->hint = g_string_new(NULL);
168     }
169     va_start(ap, fmt);
170     g_string_append_vprintf(err->hint, fmt, ap);
171     va_end(ap);
172 
173     errno = saved_errno;
174 }
175 
176 #ifdef _WIN32
177 
error_setg_win32_internal(Error ** errp,const char * src,int line,const char * func,int win32_err,const char * fmt,...)178 void error_setg_win32_internal(Error **errp,
179                                const char *src, int line, const char *func,
180                                int win32_err, const char *fmt, ...)
181 {
182     va_list ap;
183     char *suffix = NULL;
184 
185     if (errp == NULL) {
186         return;
187     }
188 
189     if (win32_err != 0) {
190         suffix = g_win32_error_message(win32_err);
191     }
192 
193     va_start(ap, fmt);
194     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR,
195                fmt, ap, suffix);
196     va_end(ap);
197 
198     g_free(suffix);
199 }
200 
201 #endif
202 
error_copy(const Error * err)203 Error *error_copy(const Error *err)
204 {
205     Error *err_new;
206 
207     err_new = g_malloc0(sizeof(*err));
208     err_new->msg = g_strdup(err->msg);
209     err_new->err_class = err->err_class;
210     err_new->src = err->src;
211     err_new->line = err->line;
212     err_new->func = err->func;
213     if (err->hint) {
214         err_new->hint = g_string_new(err->hint->str);
215     }
216 
217     return err_new;
218 }
219 
error_get_class(const Error * err)220 ErrorClass error_get_class(const Error *err)
221 {
222     return err->err_class;
223 }
224 
error_get_pretty(const Error * err)225 const char *error_get_pretty(const Error *err)
226 {
227     return err->msg;
228 }
229 
error_report_err(Error * err)230 void error_report_err(Error *err)
231 {
232     error_report("%s", error_get_pretty(err));
233     if (err->hint) {
234         error_printf("%s", err->hint->str);
235     }
236     error_free(err);
237 }
238 
warn_report_err(Error * err)239 void warn_report_err(Error *err)
240 {
241     warn_report("%s", error_get_pretty(err));
242     if (err->hint) {
243         error_printf("%s", err->hint->str);
244     }
245     error_free(err);
246 }
247 
warn_report_err_once_cond(bool * printed,Error * err)248 bool warn_report_err_once_cond(bool *printed, Error *err)
249 {
250     if (*printed) {
251         error_free(err);
252         return false;
253     }
254     *printed = true;
255     warn_report_err(err);
256     return true;
257 }
258 
error_reportf_err(Error * err,const char * fmt,...)259 void error_reportf_err(Error *err, const char *fmt, ...)
260 {
261     va_list ap;
262 
263     va_start(ap, fmt);
264     error_vprepend(&err, fmt, ap);
265     va_end(ap);
266     error_report_err(err);
267 }
268 
269 
warn_reportf_err(Error * err,const char * fmt,...)270 void warn_reportf_err(Error *err, const char *fmt, ...)
271 {
272     va_list ap;
273 
274     va_start(ap, fmt);
275     error_vprepend(&err, fmt, ap);
276     va_end(ap);
277     warn_report_err(err);
278 }
279 
error_free(Error * err)280 void error_free(Error *err)
281 {
282     if (err) {
283         g_free(err->msg);
284         if (err->hint) {
285             g_string_free(err->hint, true);
286         }
287         g_free(err);
288     }
289 }
290 
error_free_or_abort(Error ** errp)291 void error_free_or_abort(Error **errp)
292 {
293     assert(errp && *errp);
294     error_free(*errp);
295     *errp = NULL;
296 }
297 
error_propagate(Error ** dst_errp,Error * local_err)298 void error_propagate(Error **dst_errp, Error *local_err)
299 {
300     if (!local_err) {
301         return;
302     }
303     error_handle(dst_errp, local_err);
304 }
305 
error_propagate_prepend(Error ** dst_errp,Error * err,const char * fmt,...)306 void error_propagate_prepend(Error **dst_errp, Error *err,
307                              const char *fmt, ...)
308 {
309     va_list ap;
310 
311     if (dst_errp && !*dst_errp) {
312         va_start(ap, fmt);
313         error_vprepend(&err, fmt, ap);
314         va_end(ap);
315     } /* else error is being ignored, don't bother with prepending */
316     error_propagate(dst_errp, err);
317 }
318