qemu

Форк
0
/
error.c 
308 строк · 6.6 Кб
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/osdep.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
Error *error_warn;
31

32
static void error_handle(Error **errp, Error *err)
33
{
34
    if (errp == &error_abort) {
35
        fprintf(stderr, "Unexpected error in %s() at %s:%d:\n",
36
                err->func, err->src, err->line);
37
        error_report("%s", error_get_pretty(err));
38
        if (err->hint) {
39
            error_printf("%s", err->hint->str);
40
        }
41
        abort();
42
    }
43
    if (errp == &error_fatal) {
44
        error_report_err(err);
45
        exit(1);
46
    }
47
    if (errp == &error_warn) {
48
        warn_report_err(err);
49
    } else if (errp && !*errp) {
50
        *errp = err;
51
    } else {
52
        error_free(err);
53
    }
54
}
55

56
G_GNUC_PRINTF(6, 0)
57
static void error_setv(Error **errp,
58
                       const char *src, int line, const char *func,
59
                       ErrorClass err_class, const char *fmt, va_list ap,
60
                       const char *suffix)
61
{
62
    Error *err;
63
    int saved_errno = errno;
64

65
    if (errp == NULL) {
66
        return;
67
    }
68
    assert(*errp == NULL);
69

70
    err = g_malloc0(sizeof(*err));
71
    err->msg = g_strdup_vprintf(fmt, ap);
72
    if (suffix) {
73
        char *msg = err->msg;
74
        err->msg = g_strdup_printf("%s: %s", msg, suffix);
75
        g_free(msg);
76
    }
77
    err->err_class = err_class;
78
    err->src = src;
79
    err->line = line;
80
    err->func = func;
81

82
    error_handle(errp, err);
83

84
    errno = saved_errno;
85
}
86

87
void error_set_internal(Error **errp,
88
                        const char *src, int line, const char *func,
89
                        ErrorClass err_class, const char *fmt, ...)
90
{
91
    va_list ap;
92

93
    va_start(ap, fmt);
94
    error_setv(errp, src, line, func, err_class, fmt, ap, NULL);
95
    va_end(ap);
96
}
97

98
void error_setg_internal(Error **errp,
99
                         const char *src, int line, const char *func,
100
                         const char *fmt, ...)
101
{
102
    va_list ap;
103

104
    va_start(ap, fmt);
105
    error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap, NULL);
106
    va_end(ap);
107
}
108

109
void error_setg_errno_internal(Error **errp,
110
                               const char *src, int line, const char *func,
111
                               int os_errno, const char *fmt, ...)
112
{
113
    va_list ap;
114
    int saved_errno = errno;
115

116
    va_start(ap, fmt);
117
    error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap,
118
               os_errno != 0 ? strerror(os_errno) : NULL);
119
    va_end(ap);
120

121
    errno = saved_errno;
122
}
123

124
void error_setg_file_open_internal(Error **errp,
125
                                   const char *src, int line, const char *func,
126
                                   int os_errno, const char *filename)
127
{
128
    error_setg_errno_internal(errp, src, line, func, os_errno,
129
                              "Could not open '%s'", filename);
130
}
131

132
void error_vprepend(Error *const *errp, const char *fmt, va_list ap)
133
{
134
    GString *newmsg;
135

136
    if (!errp) {
137
        return;
138
    }
139

140
    newmsg = g_string_new(NULL);
141
    g_string_vprintf(newmsg, fmt, ap);
142
    g_string_append(newmsg, (*errp)->msg);
143
    g_free((*errp)->msg);
144
    (*errp)->msg = g_string_free(newmsg, 0);
145
}
146

147
void error_prepend(Error *const *errp, const char *fmt, ...)
148
{
149
    va_list ap;
150

151
    va_start(ap, fmt);
152
    error_vprepend(errp, fmt, ap);
153
    va_end(ap);
154
}
155

156
void error_append_hint(Error *const *errp, const char *fmt, ...)
157
{
158
    va_list ap;
159
    int saved_errno = errno;
160
    Error *err;
161

162
    if (!errp) {
163
        return;
164
    }
165
    err = *errp;
166
    assert(err && errp != &error_abort && errp != &error_fatal);
167

168
    if (!err->hint) {
169
        err->hint = g_string_new(NULL);
170
    }
171
    va_start(ap, fmt);
172
    g_string_append_vprintf(err->hint, fmt, ap);
173
    va_end(ap);
174

175
    errno = saved_errno;
176
}
177

178
#ifdef _WIN32
179

180
void error_setg_win32_internal(Error **errp,
181
                               const char *src, int line, const char *func,
182
                               int win32_err, const char *fmt, ...)
183
{
184
    va_list ap;
185
    char *suffix = NULL;
186

187
    if (errp == NULL) {
188
        return;
189
    }
190

191
    if (win32_err != 0) {
192
        suffix = g_win32_error_message(win32_err);
193
    }
194

195
    va_start(ap, fmt);
196
    error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR,
197
               fmt, ap, suffix);
198
    va_end(ap);
199

200
    g_free(suffix);
201
}
202

203
#endif
204

205
Error *error_copy(const Error *err)
206
{
207
    Error *err_new;
208

209
    err_new = g_malloc0(sizeof(*err));
210
    err_new->msg = g_strdup(err->msg);
211
    err_new->err_class = err->err_class;
212
    err_new->src = err->src;
213
    err_new->line = err->line;
214
    err_new->func = err->func;
215
    if (err->hint) {
216
        err_new->hint = g_string_new(err->hint->str);
217
    }
218

219
    return err_new;
220
}
221

222
ErrorClass error_get_class(const Error *err)
223
{
224
    return err->err_class;
225
}
226

227
const char *error_get_pretty(const Error *err)
228
{
229
    return err->msg;
230
}
231

232
void error_report_err(Error *err)
233
{
234
    error_report("%s", error_get_pretty(err));
235
    if (err->hint) {
236
        error_printf("%s", err->hint->str);
237
    }
238
    error_free(err);
239
}
240

241
void warn_report_err(Error *err)
242
{
243
    warn_report("%s", error_get_pretty(err));
244
    if (err->hint) {
245
        error_printf("%s", err->hint->str);
246
    }
247
    error_free(err);
248
}
249

250
void error_reportf_err(Error *err, const char *fmt, ...)
251
{
252
    va_list ap;
253

254
    va_start(ap, fmt);
255
    error_vprepend(&err, fmt, ap);
256
    va_end(ap);
257
    error_report_err(err);
258
}
259

260

261
void warn_reportf_err(Error *err, const char *fmt, ...)
262
{
263
    va_list ap;
264

265
    va_start(ap, fmt);
266
    error_vprepend(&err, fmt, ap);
267
    va_end(ap);
268
    warn_report_err(err);
269
}
270

271
void error_free(Error *err)
272
{
273
    if (err) {
274
        g_free(err->msg);
275
        if (err->hint) {
276
            g_string_free(err->hint, true);
277
        }
278
        g_free(err);
279
    }
280
}
281

282
void error_free_or_abort(Error **errp)
283
{
284
    assert(errp && *errp);
285
    error_free(*errp);
286
    *errp = NULL;
287
}
288

289
void error_propagate(Error **dst_errp, Error *local_err)
290
{
291
    if (!local_err) {
292
        return;
293
    }
294
    error_handle(dst_errp, local_err);
295
}
296

297
void error_propagate_prepend(Error **dst_errp, Error *err,
298
                             const char *fmt, ...)
299
{
300
    va_list ap;
301

302
    if (dst_errp && !*dst_errp) {
303
        va_start(ap, fmt);
304
        error_vprepend(&err, fmt, ap);
305
        va_end(ap);
306
    } /* else error is being ignored, don't bother with prepending */
307
    error_propagate(dst_errp, err);
308
}
309

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.