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