1/*
2 * QError Module
3 *
4 * Copyright (C) 2009 Red Hat Inc.
5 *
6 * Authors:
7 *  Luiz Capitulino <lcapitulino@redhat.com>
8 *
9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10 * See the COPYING.LIB file in the top-level directory.
11 */
12
13#include "monitor/monitor.h"
14#include "qapi/qmp/qjson.h"
15#include "qapi/qmp/qerror.h"
16#include "qemu-common.h"
17
18static void qerror_destroy_obj(QObject *obj);
19
20static const QType qerror_type = {
21    .code = QTYPE_QERROR,
22    .destroy = qerror_destroy_obj,
23};
24
25/**
26 * qerror_new(): Create a new QError
27 *
28 * Return strong reference.
29 */
30static QError *qerror_new(void)
31{
32    QError *qerr;
33
34    qerr = g_malloc0(sizeof(*qerr));
35    QOBJECT_INIT(qerr, &qerror_type);
36
37    return qerr;
38}
39
40/**
41 * qerror_from_info(): Create a new QError from error information
42 *
43 * Return strong reference.
44 */
45static QError * GCC_FMT_ATTR(2, 0)
46qerror_from_info(ErrorClass err_class, const char *fmt, va_list *va)
47{
48    QError *qerr;
49
50    qerr = qerror_new();
51    loc_save(&qerr->loc);
52
53    qerr->err_msg = g_strdup_vprintf(fmt, *va);
54    qerr->err_class = err_class;
55
56    return qerr;
57}
58
59/**
60 * qerror_human(): Format QError data into human-readable string.
61 */
62QString *qerror_human(const QError *qerror)
63{
64    return qstring_from_str(qerror->err_msg);
65}
66
67/**
68 * qerror_print(): Print QError data
69 *
70 * This function will print the member 'desc' of the specified QError object,
71 * it uses error_report() for this, so that the output is routed to the right
72 * place (ie. stderr or Monitor's device).
73 */
74static void qerror_print(QError *qerror)
75{
76    QString *qstring = qerror_human(qerror);
77    loc_push_restore(&qerror->loc);
78    error_report("%s", qstring_get_str(qstring));
79    loc_pop(&qerror->loc);
80    QDECREF(qstring);
81}
82
83void qerror_report(ErrorClass eclass, const char *fmt, ...)
84{
85    va_list va;
86    QError *qerror;
87
88    va_start(va, fmt);
89    qerror = qerror_from_info(eclass, fmt, &va);
90    va_end(va);
91
92    if (monitor_cur_is_qmp()) {
93        monitor_set_error(cur_mon, qerror);
94    } else {
95        qerror_print(qerror);
96        QDECREF(qerror);
97    }
98}
99
100/* Evil... */
101struct Error
102{
103    char *msg;
104    ErrorClass err_class;
105};
106
107void qerror_report_err(Error *err)
108{
109    QError *qerr;
110
111    qerr = qerror_new();
112    loc_save(&qerr->loc);
113    qerr->err_msg = g_strdup(err->msg);
114    qerr->err_class = err->err_class;
115
116    if (monitor_cur_is_qmp()) {
117        monitor_set_error(cur_mon, qerr);
118    } else {
119        qerror_print(qerr);
120        QDECREF(qerr);
121    }
122}
123
124void assert_no_error(Error *err)
125{
126    if (err) {
127        qerror_report_err(err);
128        abort();
129    }
130}
131
132/**
133 * qobject_to_qerror(): Convert a QObject into a QError
134 */
135static QError *qobject_to_qerror(const QObject *obj)
136{
137    if (qobject_type(obj) != QTYPE_QERROR) {
138        return NULL;
139    }
140
141    return container_of(obj, QError, base);
142}
143
144/**
145 * qerror_destroy_obj(): Free all memory allocated by a QError
146 */
147static void qerror_destroy_obj(QObject *obj)
148{
149    QError *qerr;
150
151    assert(obj != NULL);
152    qerr = qobject_to_qerror(obj);
153
154    g_free(qerr->err_msg);
155    g_free(qerr);
156}
157