/* * QError Module * * Copyright (C) 2009 Red Hat Inc. * * Authors: * Luiz Capitulino <lcapitulino@redhat.com> * * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. * See the COPYING.LIB file in the top-level directory. */ #include "monitor.h" #include "qjson.h" #include "qerror.h" #include "qemu-common.h" static void qerror_destroy_obj(QObject *obj); static const QType qerror_type = { .code = QTYPE_QERROR, .destroy = qerror_destroy_obj, }; /** * qerror_new(): Create a new QError * * Return strong reference. */ static QError *qerror_new(void) { QError *qerr; qerr = g_malloc0(sizeof(*qerr)); QOBJECT_INIT(qerr, &qerror_type); return qerr; } /** * qerror_from_info(): Create a new QError from error information * * Return strong reference. */ static QError *qerror_from_info(ErrorClass err_class, const char *fmt, va_list *va) { QError *qerr; qerr = qerror_new(); loc_save(&qerr->loc); qerr->err_msg = g_strdup_vprintf(fmt, *va); qerr->err_class = err_class; return qerr; } /** * qerror_human(): Format QError data into human-readable string. */ QString *qerror_human(const QError *qerror) { return qstring_from_str(qerror->err_msg); } /** * qerror_print(): Print QError data * * This function will print the member 'desc' of the specified QError object, * it uses error_report() for this, so that the output is routed to the right * place (ie. stderr or Monitor's device). */ static void qerror_print(QError *qerror) { QString *qstring = qerror_human(qerror); loc_push_restore(&qerror->loc); error_report("%s", qstring_get_str(qstring)); loc_pop(&qerror->loc); QDECREF(qstring); } void qerror_report(ErrorClass eclass, const char *fmt, ...) { va_list va; QError *qerror; va_start(va, fmt); qerror = qerror_from_info(eclass, fmt, &va); va_end(va); if (monitor_cur_is_qmp()) { monitor_set_error(cur_mon, qerror); } else { qerror_print(qerror); QDECREF(qerror); } } /* Evil... */ struct Error { char *msg; ErrorClass err_class; }; void qerror_report_err(Error *err) { QError *qerr; qerr = qerror_new(); loc_save(&qerr->loc); qerr->err_msg = g_strdup(err->msg); qerr->err_class = err->err_class; if (monitor_cur_is_qmp()) { monitor_set_error(cur_mon, qerr); } else { qerror_print(qerr); QDECREF(qerr); } } void assert_no_error(Error *err) { if (err) { qerror_report_err(err); abort(); } } /** * qobject_to_qerror(): Convert a QObject into a QError */ static QError *qobject_to_qerror(const QObject *obj) { if (qobject_type(obj) != QTYPE_QERROR) { return NULL; } return container_of(obj, QError, base); } /** * qerror_destroy_obj(): Free all memory allocated by a QError */ static void qerror_destroy_obj(QObject *obj) { QError *qerr; assert(obj != NULL); qerr = qobject_to_qerror(obj); g_free(qerr->err_msg); g_free(qerr); }