1baacf047SPaolo Bonzini /* 2baacf047SPaolo Bonzini * QEMU Error Objects 3baacf047SPaolo Bonzini * 4baacf047SPaolo Bonzini * Copyright IBM, Corp. 2011 5a29a37b9SMarkus Armbruster * Copyright (C) 2011-2015 Red Hat, Inc. 6baacf047SPaolo Bonzini * 7baacf047SPaolo Bonzini * Authors: 8baacf047SPaolo Bonzini * Anthony Liguori <aliguori@us.ibm.com> 9a29a37b9SMarkus Armbruster * Markus Armbruster <armbru@redhat.com>, 10baacf047SPaolo Bonzini * 11baacf047SPaolo Bonzini * This work is licensed under the terms of the GNU LGPL, version 2. See 12baacf047SPaolo Bonzini * the COPYING.LIB file in the top-level directory. 13baacf047SPaolo Bonzini */ 14baacf047SPaolo Bonzini 15baacf047SPaolo Bonzini #include "qemu-common.h" 16baacf047SPaolo Bonzini #include "qapi/error.h" 17073a3411SCole Robinson #include "qemu/error-report.h" 18baacf047SPaolo Bonzini 19baacf047SPaolo Bonzini struct Error 20baacf047SPaolo Bonzini { 21baacf047SPaolo Bonzini char *msg; 22baacf047SPaolo Bonzini ErrorClass err_class; 231e9b65bbSMarkus Armbruster const char *src, *func; 241e9b65bbSMarkus Armbruster int line; 2550b7b000SEric Blake GString *hint; 26baacf047SPaolo Bonzini }; 27baacf047SPaolo Bonzini 285d24ee70SPeter Crosthwaite Error *error_abort; 29a29a37b9SMarkus Armbruster Error *error_fatal; 305d24ee70SPeter Crosthwaite 31a29a37b9SMarkus Armbruster static void error_handle_fatal(Error **errp, Error *err) 321e9b65bbSMarkus Armbruster { 33a29a37b9SMarkus Armbruster if (errp == &error_abort) { 341e9b65bbSMarkus Armbruster fprintf(stderr, "Unexpected error in %s() at %s:%d:\n", 351e9b65bbSMarkus Armbruster err->func, err->src, err->line); 361e9b65bbSMarkus Armbruster error_report_err(err); 371e9b65bbSMarkus Armbruster abort(); 381e9b65bbSMarkus Armbruster } 39a29a37b9SMarkus Armbruster if (errp == &error_fatal) { 40a29a37b9SMarkus Armbruster error_report_err(err); 41a29a37b9SMarkus Armbruster exit(1); 42a29a37b9SMarkus Armbruster } 43a29a37b9SMarkus Armbruster } 441e9b65bbSMarkus Armbruster 451e9b65bbSMarkus Armbruster static void error_setv(Error **errp, 461e9b65bbSMarkus Armbruster const char *src, int line, const char *func, 471e9b65bbSMarkus Armbruster ErrorClass err_class, const char *fmt, va_list ap) 48baacf047SPaolo Bonzini { 49baacf047SPaolo Bonzini Error *err; 50b276d249SMax Reitz int saved_errno = errno; 51baacf047SPaolo Bonzini 52baacf047SPaolo Bonzini if (errp == NULL) { 53baacf047SPaolo Bonzini return; 54baacf047SPaolo Bonzini } 55baacf047SPaolo Bonzini assert(*errp == NULL); 56baacf047SPaolo Bonzini 57baacf047SPaolo Bonzini err = g_malloc0(sizeof(*err)); 58baacf047SPaolo Bonzini err->msg = g_strdup_vprintf(fmt, ap); 59baacf047SPaolo Bonzini err->err_class = err_class; 601e9b65bbSMarkus Armbruster err->src = src; 611e9b65bbSMarkus Armbruster err->line = line; 621e9b65bbSMarkus Armbruster err->func = func; 63baacf047SPaolo Bonzini 64a29a37b9SMarkus Armbruster error_handle_fatal(errp, err); 65baacf047SPaolo Bonzini *errp = err; 66b276d249SMax Reitz 67b276d249SMax Reitz errno = saved_errno; 68baacf047SPaolo Bonzini } 69baacf047SPaolo Bonzini 701e9b65bbSMarkus Armbruster void error_set_internal(Error **errp, 711e9b65bbSMarkus Armbruster const char *src, int line, const char *func, 721e9b65bbSMarkus Armbruster ErrorClass err_class, const char *fmt, ...) 7355237508SMarkus Armbruster { 7455237508SMarkus Armbruster va_list ap; 7555237508SMarkus Armbruster 7655237508SMarkus Armbruster va_start(ap, fmt); 771e9b65bbSMarkus Armbruster error_setv(errp, src, line, func, err_class, fmt, ap); 7855237508SMarkus Armbruster va_end(ap); 7955237508SMarkus Armbruster } 8055237508SMarkus Armbruster 811e9b65bbSMarkus Armbruster void error_setg_internal(Error **errp, 821e9b65bbSMarkus Armbruster const char *src, int line, const char *func, 831e9b65bbSMarkus Armbruster const char *fmt, ...) 84a9499dddSMarkus Armbruster { 85a9499dddSMarkus Armbruster va_list ap; 86a9499dddSMarkus Armbruster 87a9499dddSMarkus Armbruster va_start(ap, fmt); 881e9b65bbSMarkus Armbruster error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap); 89a9499dddSMarkus Armbruster va_end(ap); 90a9499dddSMarkus Armbruster } 91a9499dddSMarkus Armbruster 921e9b65bbSMarkus Armbruster void error_setg_errno_internal(Error **errp, 931e9b65bbSMarkus Armbruster const char *src, int line, const char *func, 941e9b65bbSMarkus Armbruster int os_errno, const char *fmt, ...) 95baacf047SPaolo Bonzini { 96baacf047SPaolo Bonzini va_list ap; 9755237508SMarkus Armbruster char *msg; 98b276d249SMax Reitz int saved_errno = errno; 99baacf047SPaolo Bonzini 100baacf047SPaolo Bonzini if (errp == NULL) { 101baacf047SPaolo Bonzini return; 102baacf047SPaolo Bonzini } 103baacf047SPaolo Bonzini 104baacf047SPaolo Bonzini va_start(ap, fmt); 1051e9b65bbSMarkus Armbruster error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap); 106baacf047SPaolo Bonzini va_end(ap); 107baacf047SPaolo Bonzini 10855237508SMarkus Armbruster if (os_errno != 0) { 10955237508SMarkus Armbruster msg = (*errp)->msg; 11055237508SMarkus Armbruster (*errp)->msg = g_strdup_printf("%s: %s", msg, strerror(os_errno)); 11155237508SMarkus Armbruster g_free(msg); 1125d24ee70SPeter Crosthwaite } 1135d24ee70SPeter Crosthwaite 114b276d249SMax Reitz errno = saved_errno; 115baacf047SPaolo Bonzini } 116baacf047SPaolo Bonzini 1171e9b65bbSMarkus Armbruster void error_setg_file_open_internal(Error **errp, 1181e9b65bbSMarkus Armbruster const char *src, int line, const char *func, 1191e9b65bbSMarkus Armbruster int os_errno, const char *filename) 12054028d75SLuiz Capitulino { 1211e9b65bbSMarkus Armbruster error_setg_errno_internal(errp, src, line, func, os_errno, 1221e9b65bbSMarkus Armbruster "Could not open '%s'", filename); 12354028d75SLuiz Capitulino } 12454028d75SLuiz Capitulino 12550b7b000SEric Blake void error_append_hint(Error **errp, const char *fmt, ...) 12650b7b000SEric Blake { 12750b7b000SEric Blake va_list ap; 12850b7b000SEric Blake int saved_errno = errno; 12950b7b000SEric Blake Error *err; 13050b7b000SEric Blake 13150b7b000SEric Blake if (!errp) { 13250b7b000SEric Blake return; 13350b7b000SEric Blake } 13450b7b000SEric Blake err = *errp; 13550b7b000SEric Blake assert(err && errp != &error_abort); 13650b7b000SEric Blake 13750b7b000SEric Blake if (!err->hint) { 13850b7b000SEric Blake err->hint = g_string_new(NULL); 13950b7b000SEric Blake } 14050b7b000SEric Blake va_start(ap, fmt); 14150b7b000SEric Blake g_string_append_vprintf(err->hint, fmt, ap); 14250b7b000SEric Blake va_end(ap); 14350b7b000SEric Blake 14450b7b000SEric Blake errno = saved_errno; 14550b7b000SEric Blake } 14650b7b000SEric Blake 14720840d4cSTomoki Sekiyama #ifdef _WIN32 14820840d4cSTomoki Sekiyama 1491e9b65bbSMarkus Armbruster void error_setg_win32_internal(Error **errp, 1501e9b65bbSMarkus Armbruster const char *src, int line, const char *func, 1511e9b65bbSMarkus Armbruster int win32_err, const char *fmt, ...) 15220840d4cSTomoki Sekiyama { 15320840d4cSTomoki Sekiyama va_list ap; 15455237508SMarkus Armbruster char *msg1, *msg2; 15520840d4cSTomoki Sekiyama 15620840d4cSTomoki Sekiyama if (errp == NULL) { 15720840d4cSTomoki Sekiyama return; 15820840d4cSTomoki Sekiyama } 15920840d4cSTomoki Sekiyama 16020840d4cSTomoki Sekiyama va_start(ap, fmt); 1611e9b65bbSMarkus Armbruster error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap); 16255237508SMarkus Armbruster va_end(ap); 16355237508SMarkus Armbruster 16420840d4cSTomoki Sekiyama if (win32_err != 0) { 16555237508SMarkus Armbruster msg1 = (*errp)->msg; 16655237508SMarkus Armbruster msg2 = g_win32_error_message(win32_err); 16755237508SMarkus Armbruster (*errp)->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2, 16820840d4cSTomoki Sekiyama (unsigned)win32_err); 16920840d4cSTomoki Sekiyama g_free(msg2); 17020840d4cSTomoki Sekiyama g_free(msg1); 17120840d4cSTomoki Sekiyama } 17220840d4cSTomoki Sekiyama } 17320840d4cSTomoki Sekiyama 17420840d4cSTomoki Sekiyama #endif 17520840d4cSTomoki Sekiyama 176baacf047SPaolo Bonzini Error *error_copy(const Error *err) 177baacf047SPaolo Bonzini { 178baacf047SPaolo Bonzini Error *err_new; 179baacf047SPaolo Bonzini 180baacf047SPaolo Bonzini err_new = g_malloc0(sizeof(*err)); 181baacf047SPaolo Bonzini err_new->msg = g_strdup(err->msg); 182baacf047SPaolo Bonzini err_new->err_class = err->err_class; 18388e2ce29SEric Blake err_new->src = err->src; 18488e2ce29SEric Blake err_new->line = err->line; 18588e2ce29SEric Blake err_new->func = err->func; 18650b7b000SEric Blake if (err->hint) { 18750b7b000SEric Blake err_new->hint = g_string_new(err->hint->str); 18850b7b000SEric Blake } 189baacf047SPaolo Bonzini 190baacf047SPaolo Bonzini return err_new; 191baacf047SPaolo Bonzini } 192baacf047SPaolo Bonzini 193baacf047SPaolo Bonzini ErrorClass error_get_class(const Error *err) 194baacf047SPaolo Bonzini { 195baacf047SPaolo Bonzini return err->err_class; 196baacf047SPaolo Bonzini } 197baacf047SPaolo Bonzini 198baacf047SPaolo Bonzini const char *error_get_pretty(Error *err) 199baacf047SPaolo Bonzini { 200baacf047SPaolo Bonzini return err->msg; 201baacf047SPaolo Bonzini } 202baacf047SPaolo Bonzini 2032ee2f1e4SMarkus Armbruster void error_report_err(Error *err) 2042ee2f1e4SMarkus Armbruster { 2052ee2f1e4SMarkus Armbruster error_report("%s", error_get_pretty(err)); 20650b7b000SEric Blake if (err->hint) { 207*543202c0SMarkus Armbruster error_printf_unless_qmp("%s", err->hint->str); 20850b7b000SEric Blake } 2092ee2f1e4SMarkus Armbruster error_free(err); 2102ee2f1e4SMarkus Armbruster } 2112ee2f1e4SMarkus Armbruster 212baacf047SPaolo Bonzini void error_free(Error *err) 213baacf047SPaolo Bonzini { 214baacf047SPaolo Bonzini if (err) { 215baacf047SPaolo Bonzini g_free(err->msg); 21650b7b000SEric Blake if (err->hint) { 21750b7b000SEric Blake g_string_free(err->hint, true); 21850b7b000SEric Blake } 219baacf047SPaolo Bonzini g_free(err); 220baacf047SPaolo Bonzini } 221baacf047SPaolo Bonzini } 222baacf047SPaolo Bonzini 223a12a5a1aSEric Blake void error_free_or_abort(Error **errp) 224a12a5a1aSEric Blake { 225a12a5a1aSEric Blake assert(errp && *errp); 226a12a5a1aSEric Blake error_free(*errp); 227a12a5a1aSEric Blake *errp = NULL; 228a12a5a1aSEric Blake } 229a12a5a1aSEric Blake 23064dfefedSMarkus Armbruster void error_propagate(Error **dst_errp, Error *local_err) 231baacf047SPaolo Bonzini { 232a29a37b9SMarkus Armbruster if (!local_err) { 233a29a37b9SMarkus Armbruster return; 234a29a37b9SMarkus Armbruster } 235a29a37b9SMarkus Armbruster error_handle_fatal(dst_errp, local_err); 236a29a37b9SMarkus Armbruster if (dst_errp && !*dst_errp) { 23764dfefedSMarkus Armbruster *dst_errp = local_err; 238a29a37b9SMarkus Armbruster } else { 239baacf047SPaolo Bonzini error_free(local_err); 240baacf047SPaolo Bonzini } 241baacf047SPaolo Bonzini } 242