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 #include "qapi/error-internal.h" 19 20 Error *error_abort; 21 Error *error_fatal; 22 23 static void error_handle(Error **errp, Error *err) 24 { 25 if (errp == &error_abort) { 26 if (err->func) { 27 fprintf(stderr, "Unexpected error in %s() at %.*s:%d:\n", 28 err->func, err->src_len, err->src, err->line); 29 } else { 30 fprintf(stderr, "Unexpected error at %.*s:%d:\n", 31 err->src_len, err->src, err->line); 32 } 33 error_report("%s", error_get_pretty(err)); 34 if (err->hint) { 35 error_printf("%s", err->hint->str); 36 } 37 abort(); 38 } 39 if (errp == &error_fatal) { 40 error_report_err(err); 41 exit(1); 42 } 43 if (errp && !*errp) { 44 *errp = err; 45 } else { 46 error_free(err); 47 } 48 } 49 50 G_GNUC_PRINTF(6, 0) 51 static void error_setv(Error **errp, 52 const char *src, int line, const char *func, 53 ErrorClass err_class, const char *fmt, va_list ap, 54 const char *suffix) 55 { 56 Error *err; 57 int saved_errno = errno; 58 59 if (errp == NULL) { 60 return; 61 } 62 assert(*errp == NULL); 63 64 err = g_malloc0(sizeof(*err)); 65 err->msg = g_strdup_vprintf(fmt, ap); 66 if (suffix) { 67 char *msg = err->msg; 68 err->msg = g_strdup_printf("%s: %s", msg, suffix); 69 g_free(msg); 70 } 71 err->err_class = err_class; 72 err->src_len = -1; 73 err->src = src; 74 err->line = line; 75 err->func = func; 76 77 error_handle(errp, err); 78 79 errno = saved_errno; 80 } 81 82 void error_set_internal(Error **errp, 83 const char *src, int line, const char *func, 84 ErrorClass err_class, const char *fmt, ...) 85 { 86 va_list ap; 87 88 va_start(ap, fmt); 89 error_setv(errp, src, line, func, err_class, fmt, ap, NULL); 90 va_end(ap); 91 } 92 93 void error_setg_internal(Error **errp, 94 const char *src, int line, const char *func, 95 const char *fmt, ...) 96 { 97 va_list ap; 98 99 va_start(ap, fmt); 100 error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap, NULL); 101 va_end(ap); 102 } 103 104 void error_setg_errno_internal(Error **errp, 105 const char *src, int line, const char *func, 106 int os_errno, const char *fmt, ...) 107 { 108 va_list ap; 109 int saved_errno = errno; 110 111 va_start(ap, fmt); 112 error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap, 113 os_errno != 0 ? strerror(os_errno) : NULL); 114 va_end(ap); 115 116 errno = saved_errno; 117 } 118 119 void error_setg_file_open_internal(Error **errp, 120 const char *src, int line, const char *func, 121 int os_errno, const char *filename) 122 { 123 error_setg_errno_internal(errp, src, line, func, os_errno, 124 "Could not open '%s'", filename); 125 } 126 127 void error_vprepend(Error *const *errp, const char *fmt, va_list ap) 128 { 129 GString *newmsg; 130 131 if (!errp) { 132 return; 133 } 134 135 newmsg = g_string_new(NULL); 136 g_string_vprintf(newmsg, fmt, ap); 137 g_string_append(newmsg, (*errp)->msg); 138 g_free((*errp)->msg); 139 (*errp)->msg = g_string_free(newmsg, 0); 140 } 141 142 void error_prepend(Error *const *errp, const char *fmt, ...) 143 { 144 va_list ap; 145 146 va_start(ap, fmt); 147 error_vprepend(errp, fmt, ap); 148 va_end(ap); 149 } 150 151 void error_append_hint(Error *const *errp, const char *fmt, ...) 152 { 153 va_list ap; 154 int saved_errno = errno; 155 Error *err; 156 157 if (!errp) { 158 return; 159 } 160 err = *errp; 161 assert(err && errp != &error_abort && errp != &error_fatal); 162 163 if (!err->hint) { 164 err->hint = g_string_new(NULL); 165 } 166 va_start(ap, fmt); 167 g_string_append_vprintf(err->hint, fmt, ap); 168 va_end(ap); 169 170 errno = saved_errno; 171 } 172 173 #ifdef _WIN32 174 175 void error_setg_win32_internal(Error **errp, 176 const char *src, int line, const char *func, 177 int win32_err, const char *fmt, ...) 178 { 179 va_list ap; 180 char *suffix = NULL; 181 182 if (errp == NULL) { 183 return; 184 } 185 186 if (win32_err != 0) { 187 suffix = g_win32_error_message(win32_err); 188 } 189 190 va_start(ap, fmt); 191 error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, 192 fmt, ap, suffix); 193 va_end(ap); 194 195 g_free(suffix); 196 } 197 198 #endif 199 200 Error *error_copy(const Error *err) 201 { 202 Error *err_new; 203 204 err_new = g_malloc0(sizeof(*err)); 205 err_new->msg = g_strdup(err->msg); 206 err_new->err_class = err->err_class; 207 err_new->src = err->src; 208 err_new->line = err->line; 209 err_new->func = err->func; 210 if (err->hint) { 211 err_new->hint = g_string_new(err->hint->str); 212 } 213 214 return err_new; 215 } 216 217 ErrorClass error_get_class(const Error *err) 218 { 219 return err->err_class; 220 } 221 222 const char *error_get_pretty(const Error *err) 223 { 224 return err->msg; 225 } 226 227 void error_report_err(Error *err) 228 { 229 error_report("%s", error_get_pretty(err)); 230 if (err->hint) { 231 error_printf("%s", err->hint->str); 232 } 233 error_free(err); 234 } 235 236 void warn_report_err(Error *err) 237 { 238 warn_report("%s", error_get_pretty(err)); 239 if (err->hint) { 240 error_printf("%s", err->hint->str); 241 } 242 error_free(err); 243 } 244 245 bool warn_report_err_once_cond(bool *printed, Error *err) 246 { 247 if (*printed) { 248 error_free(err); 249 return false; 250 } 251 *printed = true; 252 warn_report_err(err); 253 return true; 254 } 255 256 void error_reportf_err(Error *err, const char *fmt, ...) 257 { 258 va_list ap; 259 260 va_start(ap, fmt); 261 error_vprepend(&err, fmt, ap); 262 va_end(ap); 263 error_report_err(err); 264 } 265 266 267 void warn_reportf_err(Error *err, const char *fmt, ...) 268 { 269 va_list ap; 270 271 va_start(ap, fmt); 272 error_vprepend(&err, fmt, ap); 273 va_end(ap); 274 warn_report_err(err); 275 } 276 277 void error_free(Error *err) 278 { 279 if (err) { 280 g_free(err->msg); 281 if (err->hint) { 282 g_string_free(err->hint, true); 283 } 284 g_free(err); 285 } 286 } 287 288 void error_free_or_abort(Error **errp) 289 { 290 assert(errp && *errp); 291 error_free(*errp); 292 *errp = NULL; 293 } 294 295 void error_propagate(Error **dst_errp, Error *local_err) 296 { 297 if (!local_err) { 298 return; 299 } 300 error_handle(dst_errp, local_err); 301 } 302 303 void error_propagate_prepend(Error **dst_errp, Error *err, 304 const char *fmt, ...) 305 { 306 va_list ap; 307 308 if (dst_errp && !*dst_errp) { 309 va_start(ap, fmt); 310 error_vprepend(&err, fmt, ap); 311 va_end(ap); 312 } /* else error is being ignored, don't bother with prepending */ 313 error_propagate(dst_errp, err); 314 } 315