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