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 }; 22 23 Error *error_abort; 24 25 void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...) 26 { 27 Error *err; 28 va_list ap; 29 int saved_errno = errno; 30 31 if (errp == NULL) { 32 return; 33 } 34 assert(*errp == NULL); 35 36 err = g_malloc0(sizeof(*err)); 37 38 va_start(ap, fmt); 39 err->msg = g_strdup_vprintf(fmt, ap); 40 va_end(ap); 41 err->err_class = err_class; 42 43 if (errp == &error_abort) { 44 error_report("%s", error_get_pretty(err)); 45 abort(); 46 } 47 48 *errp = err; 49 50 errno = saved_errno; 51 } 52 53 void error_set_errno(Error **errp, int os_errno, ErrorClass err_class, 54 const char *fmt, ...) 55 { 56 Error *err; 57 char *msg1; 58 va_list ap; 59 int saved_errno = errno; 60 61 if (errp == NULL) { 62 return; 63 } 64 assert(*errp == NULL); 65 66 err = g_malloc0(sizeof(*err)); 67 68 va_start(ap, fmt); 69 msg1 = g_strdup_vprintf(fmt, ap); 70 if (os_errno != 0) { 71 err->msg = g_strdup_printf("%s: %s", msg1, strerror(os_errno)); 72 g_free(msg1); 73 } else { 74 err->msg = msg1; 75 } 76 va_end(ap); 77 err->err_class = err_class; 78 79 if (errp == &error_abort) { 80 error_report("%s", error_get_pretty(err)); 81 abort(); 82 } 83 84 *errp = err; 85 86 errno = saved_errno; 87 } 88 89 void error_setg_file_open(Error **errp, int os_errno, const char *filename) 90 { 91 error_setg_errno(errp, os_errno, "Could not open '%s'", filename); 92 } 93 94 #ifdef _WIN32 95 96 void error_set_win32(Error **errp, int win32_err, ErrorClass err_class, 97 const char *fmt, ...) 98 { 99 Error *err; 100 char *msg1; 101 va_list ap; 102 103 if (errp == NULL) { 104 return; 105 } 106 assert(*errp == NULL); 107 108 err = g_malloc0(sizeof(*err)); 109 110 va_start(ap, fmt); 111 msg1 = g_strdup_vprintf(fmt, ap); 112 if (win32_err != 0) { 113 char *msg2 = g_win32_error_message(win32_err); 114 err->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2, 115 (unsigned)win32_err); 116 g_free(msg2); 117 g_free(msg1); 118 } else { 119 err->msg = msg1; 120 } 121 va_end(ap); 122 err->err_class = err_class; 123 124 if (errp == &error_abort) { 125 error_report("%s", error_get_pretty(err)); 126 abort(); 127 } 128 129 *errp = err; 130 } 131 132 #endif 133 134 Error *error_copy(const Error *err) 135 { 136 Error *err_new; 137 138 err_new = g_malloc0(sizeof(*err)); 139 err_new->msg = g_strdup(err->msg); 140 err_new->err_class = err->err_class; 141 142 return err_new; 143 } 144 145 bool error_is_set(Error **errp) 146 { 147 return (errp && *errp); 148 } 149 150 ErrorClass error_get_class(const Error *err) 151 { 152 return err->err_class; 153 } 154 155 const char *error_get_pretty(Error *err) 156 { 157 return err->msg; 158 } 159 160 void error_free(Error *err) 161 { 162 if (err) { 163 g_free(err->msg); 164 g_free(err); 165 } 166 } 167 168 void error_propagate(Error **dst_err, Error *local_err) 169 { 170 if (local_err && dst_err == &error_abort) { 171 error_report("%s", error_get_pretty(local_err)); 172 abort(); 173 } else if (dst_err && !*dst_err) { 174 *dst_err = local_err; 175 } else if (local_err) { 176 error_free(local_err); 177 } 178 } 179