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