]>
Commit | Line | Data |
---|---|---|
d5ec4f27 LC |
1 | /* |
2 | * QEMU Error Objects | |
3 | * | |
4 | * Copyright IBM, Corp. 2011 | |
5 | * | |
6 | * Authors: | |
7 | * Anthony Liguori <aliguori@us.ibm.com> | |
8 | * | |
9 | * This work is licensed under the terms of the GNU LGPL, version 2. See | |
10 | * the COPYING.LIB file in the top-level directory. | |
11 | */ | |
e4ea5e2d SW |
12 | |
13 | #include "qemu-common.h" | |
7b1b5d19 | 14 | #include "qapi/error.h" |
073a3411 | 15 | #include "qemu/error-report.h" |
d5ec4f27 LC |
16 | |
17 | struct Error | |
18 | { | |
d5ec4f27 | 19 | char *msg; |
13f59ae8 | 20 | ErrorClass err_class; |
d5ec4f27 LC |
21 | }; |
22 | ||
5d24ee70 PC |
23 | Error *error_abort; |
24 | ||
55237508 MA |
25 | static void error_setv(Error **errp, ErrorClass err_class, |
26 | const char *fmt, va_list ap) | |
d5ec4f27 LC |
27 | { |
28 | Error *err; | |
b276d249 | 29 | int saved_errno = errno; |
d5ec4f27 LC |
30 | |
31 | if (errp == NULL) { | |
32 | return; | |
33 | } | |
d195325b | 34 | assert(*errp == NULL); |
d5ec4f27 | 35 | |
7267c094 | 36 | err = g_malloc0(sizeof(*err)); |
df1e608a | 37 | err->msg = g_strdup_vprintf(fmt, ap); |
13f59ae8 | 38 | err->err_class = err_class; |
d5ec4f27 | 39 | |
5d24ee70 | 40 | if (errp == &error_abort) { |
565f65d2 | 41 | error_report_err(err); |
5d24ee70 PC |
42 | abort(); |
43 | } | |
44 | ||
d5ec4f27 | 45 | *errp = err; |
b276d249 HR |
46 | |
47 | errno = saved_errno; | |
d5ec4f27 LC |
48 | } |
49 | ||
55237508 MA |
50 | void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...) |
51 | { | |
52 | va_list ap; | |
53 | ||
54 | va_start(ap, fmt); | |
55 | error_setv(errp, err_class, fmt, ap); | |
56 | va_end(ap); | |
57 | } | |
58 | ||
a9499ddd MA |
59 | void error_setg(Error **errp, const char *fmt, ...) |
60 | { | |
61 | va_list ap; | |
62 | ||
63 | va_start(ap, fmt); | |
64 | error_setv(errp, ERROR_CLASS_GENERIC_ERROR, fmt, ap); | |
65 | va_end(ap); | |
66 | } | |
67 | ||
4463dcb8 | 68 | void error_setg_errno(Error **errp, int os_errno, const char *fmt, ...) |
680d16dc | 69 | { |
680d16dc | 70 | va_list ap; |
55237508 | 71 | char *msg; |
b276d249 | 72 | int saved_errno = errno; |
680d16dc PB |
73 | |
74 | if (errp == NULL) { | |
75 | return; | |
76 | } | |
680d16dc PB |
77 | |
78 | va_start(ap, fmt); | |
4463dcb8 | 79 | error_setv(errp, ERROR_CLASS_GENERIC_ERROR, fmt, ap); |
680d16dc | 80 | va_end(ap); |
680d16dc | 81 | |
55237508 MA |
82 | if (os_errno != 0) { |
83 | msg = (*errp)->msg; | |
84 | (*errp)->msg = g_strdup_printf("%s: %s", msg, strerror(os_errno)); | |
85 | g_free(msg); | |
5d24ee70 PC |
86 | } |
87 | ||
b276d249 | 88 | errno = saved_errno; |
680d16dc PB |
89 | } |
90 | ||
54028d75 LC |
91 | void error_setg_file_open(Error **errp, int os_errno, const char *filename) |
92 | { | |
93 | error_setg_errno(errp, os_errno, "Could not open '%s'", filename); | |
94 | } | |
95 | ||
20840d4c TS |
96 | #ifdef _WIN32 |
97 | ||
e7cf59e8 | 98 | void error_setg_win32(Error **errp, int win32_err, const char *fmt, ...) |
20840d4c | 99 | { |
20840d4c | 100 | va_list ap; |
55237508 | 101 | char *msg1, *msg2; |
20840d4c TS |
102 | |
103 | if (errp == NULL) { | |
104 | return; | |
105 | } | |
20840d4c TS |
106 | |
107 | va_start(ap, fmt); | |
e7cf59e8 | 108 | error_setv(errp, ERROR_CLASS_GENERIC_ERROR, fmt, ap); |
55237508 MA |
109 | va_end(ap); |
110 | ||
20840d4c | 111 | if (win32_err != 0) { |
55237508 MA |
112 | msg1 = (*errp)->msg; |
113 | msg2 = g_win32_error_message(win32_err); | |
114 | (*errp)->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2, | |
115 | (unsigned)win32_err); | |
20840d4c TS |
116 | g_free(msg2); |
117 | g_free(msg1); | |
5d24ee70 | 118 | } |
20840d4c TS |
119 | } |
120 | ||
121 | #endif | |
122 | ||
79020cfc LC |
123 | Error *error_copy(const Error *err) |
124 | { | |
125 | Error *err_new; | |
126 | ||
127 | err_new = g_malloc0(sizeof(*err)); | |
128 | err_new->msg = g_strdup(err->msg); | |
13f59ae8 | 129 | err_new->err_class = err->err_class; |
79020cfc LC |
130 | |
131 | return err_new; | |
132 | } | |
133 | ||
ea25fbca LC |
134 | ErrorClass error_get_class(const Error *err) |
135 | { | |
136 | return err->err_class; | |
137 | } | |
138 | ||
d5ec4f27 LC |
139 | const char *error_get_pretty(Error *err) |
140 | { | |
d5ec4f27 LC |
141 | return err->msg; |
142 | } | |
143 | ||
2ee2f1e4 MA |
144 | void error_report_err(Error *err) |
145 | { | |
146 | error_report("%s", error_get_pretty(err)); | |
147 | error_free(err); | |
148 | } | |
149 | ||
d5ec4f27 LC |
150 | void error_free(Error *err) |
151 | { | |
152 | if (err) { | |
7267c094 AL |
153 | g_free(err->msg); |
154 | g_free(err); | |
d5ec4f27 LC |
155 | } |
156 | } | |
157 | ||
64dfefed | 158 | void error_propagate(Error **dst_errp, Error *local_err) |
d5ec4f27 | 159 | { |
64dfefed | 160 | if (local_err && dst_errp == &error_abort) { |
565f65d2 | 161 | error_report_err(local_err); |
5d24ee70 | 162 | abort(); |
64dfefed MA |
163 | } else if (dst_errp && !*dst_errp) { |
164 | *dst_errp = local_err; | |
d5ec4f27 LC |
165 | } else if (local_err) { |
166 | error_free(local_err); | |
167 | } | |
168 | } |