error.c 3.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*
 * QEMU Error Objects
 *
 * Copyright IBM, Corp. 2011
 *
 * Authors:
 *  Anthony Liguori   <aliguori@us.ibm.com>
 *
 * This work is licensed under the terms of the GNU LGPL, version 2.  See
 * the COPYING.LIB file in the top-level directory.
 */
12 13

#include "qemu-common.h"
14
#include "qapi/error.h"
15
#include "qemu/error-report.h"
16 17 18 19

struct Error
{
    char *msg;
20
    ErrorClass err_class;
21 22
};

P
Peter Crosthwaite 已提交
23 24
Error *error_abort;

25 26
static void error_setv(Error **errp, ErrorClass err_class,
                       const char *fmt, va_list ap)
27 28
{
    Error *err;
M
Max Reitz 已提交
29
    int saved_errno = errno;
30 31 32 33

    if (errp == NULL) {
        return;
    }
P
Paolo Bonzini 已提交
34
    assert(*errp == NULL);
35

36
    err = g_malloc0(sizeof(*err));
37
    err->msg = g_strdup_vprintf(fmt, ap);
38
    err->err_class = err_class;
39

P
Peter Crosthwaite 已提交
40
    if (errp == &error_abort) {
41
        error_report_err(err);
P
Peter Crosthwaite 已提交
42 43 44
        abort();
    }

45
    *errp = err;
M
Max Reitz 已提交
46 47

    errno = saved_errno;
48 49
}

50 51 52 53 54 55 56 57 58
void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    error_setv(errp, err_class, fmt, ap);
    va_end(ap);
}

59 60 61 62 63 64 65 66 67
void error_setg(Error **errp, const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    error_setv(errp, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
    va_end(ap);
}

68
void error_setg_errno(Error **errp, int os_errno, const char *fmt, ...)
69 70
{
    va_list ap;
71
    char *msg;
M
Max Reitz 已提交
72
    int saved_errno = errno;
73 74 75 76 77 78

    if (errp == NULL) {
        return;
    }

    va_start(ap, fmt);
79
    error_setv(errp, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
80 81
    va_end(ap);

82 83 84 85
    if (os_errno != 0) {
        msg = (*errp)->msg;
        (*errp)->msg = g_strdup_printf("%s: %s", msg, strerror(os_errno));
        g_free(msg);
P
Peter Crosthwaite 已提交
86 87
    }

M
Max Reitz 已提交
88
    errno = saved_errno;
89 90
}

91 92 93 94 95
void error_setg_file_open(Error **errp, int os_errno, const char *filename)
{
    error_setg_errno(errp, os_errno, "Could not open '%s'", filename);
}

96 97
#ifdef _WIN32

98
void error_setg_win32(Error **errp, int win32_err, const char *fmt, ...)
99 100
{
    va_list ap;
101
    char *msg1, *msg2;
102 103 104 105 106 107

    if (errp == NULL) {
        return;
    }

    va_start(ap, fmt);
108
    error_setv(errp, ERROR_CLASS_GENERIC_ERROR, fmt, ap);
109 110
    va_end(ap);

111
    if (win32_err != 0) {
112 113 114 115
        msg1 = (*errp)->msg;
        msg2 = g_win32_error_message(win32_err);
        (*errp)->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2,
                                       (unsigned)win32_err);
116 117
        g_free(msg2);
        g_free(msg1);
P
Peter Crosthwaite 已提交
118
    }
119 120 121 122
}

#endif

L
Luiz Capitulino 已提交
123 124 125 126 127 128
Error *error_copy(const Error *err)
{
    Error *err_new;

    err_new = g_malloc0(sizeof(*err));
    err_new->msg = g_strdup(err->msg);
129
    err_new->err_class = err->err_class;
L
Luiz Capitulino 已提交
130 131 132 133

    return err_new;
}

L
Luiz Capitulino 已提交
134 135 136 137 138
ErrorClass error_get_class(const Error *err)
{
    return err->err_class;
}

139 140 141 142 143
const char *error_get_pretty(Error *err)
{
    return err->msg;
}

144 145 146 147 148 149
void error_report_err(Error *err)
{
    error_report("%s", error_get_pretty(err));
    error_free(err);
}

150 151 152
void error_free(Error *err)
{
    if (err) {
153 154
        g_free(err->msg);
        g_free(err);
155 156 157
    }
}

158
void error_propagate(Error **dst_errp, Error *local_err)
159
{
160
    if (local_err && dst_errp == &error_abort) {
161
        error_report_err(local_err);
P
Peter Crosthwaite 已提交
162
        abort();
163 164
    } else if (dst_errp && !*dst_errp) {
        *dst_errp = local_err;
165 166 167 168
    } else if (local_err) {
        error_free(local_err);
    }
}