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 */ 12 13 #include "qemu-common.h" 14 #include "qapi/error.h" 15 #include "qemu/error-report.h" 16 17 struct Error 18 { 19 char *msg; 20 ErrorClass err_class; 21 const char *src, *func; 22 int line; 23 }; 24 25 Error *error_abort; 26 27 static void error_do_abort(Error *err) 28 { 29 fprintf(stderr, "Unexpected error in %s() at %s:%d:\n", 30 err->func, err->src, err->line); 31 error_report_err(err); 32 abort(); 33 } 34 35 static void error_setv(Error **errp, 36 const char *src, int line, const char *func, 37 ErrorClass err_class, const char *fmt, va_list ap) 38 { 39 Error *err; 40 int saved_errno = errno; 41 42 if (errp == NULL) { 43 return; 44 } 45 assert(*errp == NULL); 46 47 err = g_malloc0(sizeof(*err)); 48 err->msg = g_strdup_vprintf(fmt, ap); 49 err->err_class = err_class; 50 err->src = src; 51 err->line = line; 52 err->func = func; 53 54 if (errp == &error_abort) { 55 error_do_abort(err); 56 } 57 58 *errp = err; 59 60 errno = saved_errno; 61 } 62 63 void error_set_internal(Error **errp, 64 const char *src, int line, const char *func, 65 ErrorClass err_class, const char *fmt, ...) 66 { 67 va_list ap; 68 69 va_start(ap, fmt); 70 error_setv(errp, src, line, func, err_class, fmt, ap); 71 va_end(ap); 72 } 73 74 void error_setg_internal(Error **errp, 75 const char *src, int line, const char *func, 76 const char *fmt, ...) 77 { 78 va_list ap; 79 80 va_start(ap, fmt); 81 error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap); 82 va_end(ap); 83 } 84 85 void error_setg_errno_internal(Error **errp, 86 const char *src, int line, const char *func, 87 int os_errno, const char *fmt, ...) 88 { 89 va_list ap; 90 char *msg; 91 int saved_errno = errno; 92 93 if (errp == NULL) { 94 return; 95 } 96 97 va_start(ap, fmt); 98 error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap); 99 va_end(ap); 100 101 if (os_errno != 0) { 102 msg = (*errp)->msg; 103 (*errp)->msg = g_strdup_printf("%s: %s", msg, strerror(os_errno)); 104 g_free(msg); 105 } 106 107 errno = saved_errno; 108 } 109 110 void error_setg_file_open_internal(Error **errp, 111 const char *src, int line, const char *func, 112 int os_errno, const char *filename) 113 { 114 error_setg_errno_internal(errp, src, line, func, os_errno, 115 "Could not open '%s'", filename); 116 } 117 118 #ifdef _WIN32 119 120 void error_setg_win32_internal(Error **errp, 121 const char *src, int line, const char *func, 122 int win32_err, const char *fmt, ...) 123 { 124 va_list ap; 125 char *msg1, *msg2; 126 127 if (errp == NULL) { 128 return; 129 } 130 131 va_start(ap, fmt); 132 error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap); 133 va_end(ap); 134 135 if (win32_err != 0) { 136 msg1 = (*errp)->msg; 137 msg2 = g_win32_error_message(win32_err); 138 (*errp)->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2, 139 (unsigned)win32_err); 140 g_free(msg2); 141 g_free(msg1); 142 } 143 } 144 145 #endif 146 147 Error *error_copy(const Error *err) 148 { 149 Error *err_new; 150 151 err_new = g_malloc0(sizeof(*err)); 152 err_new->msg = g_strdup(err->msg); 153 err_new->err_class = err->err_class; 154 155 return err_new; 156 } 157 158 ErrorClass error_get_class(const Error *err) 159 { 160 return err->err_class; 161 } 162 163 const char *error_get_pretty(Error *err) 164 { 165 return err->msg; 166 } 167 168 void error_report_err(Error *err) 169 { 170 error_report("%s", error_get_pretty(err)); 171 error_free(err); 172 } 173 174 void error_free(Error *err) 175 { 176 if (err) { 177 g_free(err->msg); 178 g_free(err); 179 } 180 } 181 182 void error_propagate(Error **dst_errp, Error *local_err) 183 { 184 if (local_err && dst_errp == &error_abort) { 185 error_do_abort(local_err); 186 } else if (dst_errp && !*dst_errp) { 187 *dst_errp = local_err; 188 } else if (local_err) { 189 error_free(local_err); 190 } 191 } 192