xref: /openbmc/qemu/util/error.c (revision 0a9516c2)
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-common.h"
16 #include "qapi/error.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_append_hint(Error **errp, const char *fmt, ...)
126 {
127     va_list ap;
128     int saved_errno = errno;
129     Error *err;
130 
131     if (!errp) {
132         return;
133     }
134     err = *errp;
135     assert(err && errp != &error_abort);
136 
137     if (!err->hint) {
138         err->hint = g_string_new(NULL);
139     }
140     va_start(ap, fmt);
141     g_string_append_vprintf(err->hint, fmt, ap);
142     va_end(ap);
143 
144     errno = saved_errno;
145 }
146 
147 #ifdef _WIN32
148 
149 void error_setg_win32_internal(Error **errp,
150                                const char *src, int line, const char *func,
151                                int win32_err, const char *fmt, ...)
152 {
153     va_list ap;
154     char *msg1, *msg2;
155 
156     if (errp == NULL) {
157         return;
158     }
159 
160     va_start(ap, fmt);
161     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
162     va_end(ap);
163 
164     if (win32_err != 0) {
165         msg1 = (*errp)->msg;
166         msg2 = g_win32_error_message(win32_err);
167         (*errp)->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2,
168                                        (unsigned)win32_err);
169         g_free(msg2);
170         g_free(msg1);
171     }
172 }
173 
174 #endif
175 
176 Error *error_copy(const Error *err)
177 {
178     Error *err_new;
179 
180     err_new = g_malloc0(sizeof(*err));
181     err_new->msg = g_strdup(err->msg);
182     err_new->err_class = err->err_class;
183     err_new->src = err->src;
184     err_new->line = err->line;
185     err_new->func = err->func;
186     if (err->hint) {
187         err_new->hint = g_string_new(err->hint->str);
188     }
189 
190     return err_new;
191 }
192 
193 ErrorClass error_get_class(const Error *err)
194 {
195     return err->err_class;
196 }
197 
198 const char *error_get_pretty(Error *err)
199 {
200     return err->msg;
201 }
202 
203 void error_report_err(Error *err)
204 {
205     error_report("%s", error_get_pretty(err));
206     if (err->hint) {
207         error_printf_unless_qmp("%s\n", err->hint->str);
208     }
209     error_free(err);
210 }
211 
212 void error_free(Error *err)
213 {
214     if (err) {
215         g_free(err->msg);
216         if (err->hint) {
217             g_string_free(err->hint, true);
218         }
219         g_free(err);
220     }
221 }
222 
223 void error_free_or_abort(Error **errp)
224 {
225     assert(errp && *errp);
226     error_free(*errp);
227     *errp = NULL;
228 }
229 
230 void error_propagate(Error **dst_errp, Error *local_err)
231 {
232     if (!local_err) {
233         return;
234     }
235     error_handle_fatal(dst_errp, local_err);
236     if (dst_errp && !*dst_errp) {
237         *dst_errp = local_err;
238     } else {
239         error_free(local_err);
240     }
241 }
242