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