1
2
3
4
5
6
7
8
9
10
11
12
13#include "qemu/osdep.h"
14#include "monitor/monitor.h"
15#include "qemu/error-report.h"
16
17
18
19
20
21typedef enum {
22 REPORT_TYPE_ERROR,
23 REPORT_TYPE_WARNING,
24 REPORT_TYPE_INFO,
25} report_type;
26
27
28bool message_with_timestamp;
29bool error_with_guestname;
30const char *error_guest_name;
31
32int error_printf(const char *fmt, ...)
33{
34 va_list ap;
35 int ret;
36
37 va_start(ap, fmt);
38 ret = error_vprintf(fmt, ap);
39 va_end(ap);
40 return ret;
41}
42
43static Location std_loc = {
44 .kind = LOC_NONE
45};
46static Location *cur_loc = &std_loc;
47
48
49
50
51
52
53Location *loc_push_restore(Location *loc)
54{
55 assert(!loc->prev);
56 loc->prev = cur_loc;
57 cur_loc = loc;
58 return loc;
59}
60
61
62
63
64
65
66
67Location *loc_push_none(Location *loc)
68{
69 loc->kind = LOC_NONE;
70 loc->prev = NULL;
71 return loc_push_restore(loc);
72}
73
74
75
76
77
78Location *loc_pop(Location *loc)
79{
80 assert(cur_loc == loc && loc->prev);
81 cur_loc = loc->prev;
82 loc->prev = NULL;
83 return loc;
84}
85
86
87
88
89Location *loc_save(Location *loc)
90{
91 *loc = *cur_loc;
92 loc->prev = NULL;
93 return loc;
94}
95
96
97
98
99void loc_restore(Location *loc)
100{
101 Location *prev = cur_loc->prev;
102 assert(!loc->prev);
103 *cur_loc = *loc;
104 cur_loc->prev = prev;
105}
106
107
108
109
110void loc_set_none(void)
111{
112 cur_loc->kind = LOC_NONE;
113}
114
115
116
117
118void loc_set_cmdline(char **argv, int idx, int cnt)
119{
120 cur_loc->kind = LOC_CMDLINE;
121 cur_loc->num = cnt;
122 cur_loc->ptr = argv + idx;
123}
124
125
126
127
128void loc_set_file(const char *fname, int lno)
129{
130 assert (fname || cur_loc->kind == LOC_FILE);
131 cur_loc->kind = LOC_FILE;
132 cur_loc->num = lno;
133 if (fname) {
134 cur_loc->ptr = fname;
135 }
136}
137
138
139
140
141static void print_loc(void)
142{
143 const char *sep = "";
144 int i;
145 const char *const *argp;
146
147 if (!monitor_cur() && g_get_prgname()) {
148 error_printf("%s:", g_get_prgname());
149 sep = " ";
150 }
151 switch (cur_loc->kind) {
152 case LOC_CMDLINE:
153 argp = cur_loc->ptr;
154 for (i = 0; i < cur_loc->num; i++) {
155 error_printf("%s%s", sep, argp[i]);
156 sep = " ";
157 }
158 error_printf(": ");
159 break;
160 case LOC_FILE:
161 error_printf("%s:", (const char *)cur_loc->ptr);
162 if (cur_loc->num) {
163 error_printf("%d:", cur_loc->num);
164 }
165 error_printf(" ");
166 break;
167 default:
168 error_printf("%s", sep);
169 }
170}
171
172static char *
173real_time_iso8601(void)
174{
175#if GLIB_CHECK_VERSION(2,62,0)
176 g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
177
178#pragma GCC diagnostic push
179#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
180 return g_date_time_format_iso8601(dt);
181#pragma GCC diagnostic pop
182#else
183 GTimeVal tv;
184 g_get_current_time(&tv);
185 return g_time_val_to_iso8601(&tv);
186#endif
187}
188
189
190
191
192
193
194
195
196static void vreport(report_type type, const char *fmt, va_list ap)
197{
198 gchar *timestr;
199
200 if (message_with_timestamp && !monitor_cur()) {
201 timestr = real_time_iso8601();
202 error_printf("%s ", timestr);
203 g_free(timestr);
204 }
205
206
207 if (error_with_guestname && error_guest_name && !monitor_cur()) {
208 error_printf("%s ", error_guest_name);
209 }
210
211 print_loc();
212
213 switch (type) {
214 case REPORT_TYPE_ERROR:
215 break;
216 case REPORT_TYPE_WARNING:
217 error_printf("warning: ");
218 break;
219 case REPORT_TYPE_INFO:
220 error_printf("info: ");
221 break;
222 }
223
224 error_vprintf(fmt, ap);
225 error_printf("\n");
226}
227
228
229
230
231
232
233
234
235void error_vreport(const char *fmt, va_list ap)
236{
237 vreport(REPORT_TYPE_ERROR, fmt, ap);
238}
239
240
241
242
243
244
245
246void warn_vreport(const char *fmt, va_list ap)
247{
248 vreport(REPORT_TYPE_WARNING, fmt, ap);
249}
250
251
252
253
254
255
256
257
258void info_vreport(const char *fmt, va_list ap)
259{
260 vreport(REPORT_TYPE_INFO, fmt, ap);
261}
262
263
264
265
266
267
268
269
270void error_report(const char *fmt, ...)
271{
272 va_list ap;
273
274 va_start(ap, fmt);
275 vreport(REPORT_TYPE_ERROR, fmt, ap);
276 va_end(ap);
277}
278
279
280
281
282
283
284
285void warn_report(const char *fmt, ...)
286{
287 va_list ap;
288
289 va_start(ap, fmt);
290 vreport(REPORT_TYPE_WARNING, fmt, ap);
291 va_end(ap);
292}
293
294
295
296
297
298
299
300
301void info_report(const char *fmt, ...)
302{
303 va_list ap;
304
305 va_start(ap, fmt);
306 vreport(REPORT_TYPE_INFO, fmt, ap);
307 va_end(ap);
308}
309
310
311
312
313
314
315bool error_report_once_cond(bool *printed, const char *fmt, ...)
316{
317 va_list ap;
318
319 assert(printed);
320 if (*printed) {
321 return false;
322 }
323 *printed = true;
324 va_start(ap, fmt);
325 vreport(REPORT_TYPE_ERROR, fmt, ap);
326 va_end(ap);
327 return true;
328}
329
330
331
332
333
334
335bool warn_report_once_cond(bool *printed, const char *fmt, ...)
336{
337 va_list ap;
338
339 assert(printed);
340 if (*printed) {
341 return false;
342 }
343 *printed = true;
344 va_start(ap, fmt);
345 vreport(REPORT_TYPE_WARNING, fmt, ap);
346 va_end(ap);
347 return true;
348}
349
350static char *qemu_glog_domains;
351
352static void qemu_log_func(const gchar *log_domain,
353 GLogLevelFlags log_level,
354 const gchar *message,
355 gpointer user_data)
356{
357 switch (log_level & G_LOG_LEVEL_MASK) {
358 case G_LOG_LEVEL_DEBUG:
359 case G_LOG_LEVEL_INFO:
360
361
362
363
364 if (qemu_glog_domains == NULL) {
365 break;
366 }
367 if (strcmp(qemu_glog_domains, "all") != 0 &&
368 (log_domain == NULL || !strstr(qemu_glog_domains, log_domain))) {
369 break;
370 }
371
372 case G_LOG_LEVEL_MESSAGE:
373 info_report("%s%s%s",
374 log_domain ?: "", log_domain ? ": " : "", message);
375
376 break;
377 case G_LOG_LEVEL_WARNING:
378 warn_report("%s%s%s",
379 log_domain ?: "", log_domain ? ": " : "", message);
380 break;
381 case G_LOG_LEVEL_CRITICAL:
382 case G_LOG_LEVEL_ERROR:
383 error_report("%s%s%s",
384 log_domain ?: "", log_domain ? ": " : "", message);
385 break;
386 }
387}
388
389void error_init(const char *argv0)
390{
391 const char *p = strrchr(argv0, '/');
392
393
394 g_set_prgname(p ? p + 1 : argv0);
395
396
397
398
399
400 g_log_set_default_handler(qemu_log_func, NULL);
401 g_warn_if_fail(qemu_glog_domains == NULL);
402 qemu_glog_domains = g_strdup(g_getenv("G_MESSAGES_DEBUG"));
403}
404