1910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner/* 2910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner * QEMU Error Objects 3910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner * 4910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner * Copyright IBM, Corp. 2011 5910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner * 6910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner * Authors: 7910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner * Anthony Liguori <aliguori@us.ibm.com> 8910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner * 9910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner * This work is licensed under the terms of the GNU LGPL, version 2. See 10910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner * the COPYING.LIB file in the top-level directory. 11910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner */ 12910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 13910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner#include "qemu-common.h" 14910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner#include "qapi/error.h" 15910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner#include "qapi/qmp/qjson.h" 16910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner#include "qapi/qmp/qdict.h" 17910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner#include "qapi-types.h" 18910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner#include "qapi/qmp/qerror.h" 19910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 20910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnerstruct Error 21910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner{ 22910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner char *msg; 23910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner ErrorClass err_class; 24910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner}; 25910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 26910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnervoid error_set(Error **errp, ErrorClass err_class, const char *fmt, ...) 27910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner{ 28910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner Error *err; 29910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner va_list ap; 30910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner int saved_errno = errno; 31910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 32910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner if (errp == NULL) { 33910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner return; 34910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner } 35910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner assert(*errp == NULL); 36910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 37910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner err = g_malloc0(sizeof(*err)); 38910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 39910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner va_start(ap, fmt); 40910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner err->msg = g_strdup_vprintf(fmt, ap); 41910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner va_end(ap); 42910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner err->err_class = err_class; 43910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 44910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner *errp = err; 45910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 46910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner errno = saved_errno; 47910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner} 48910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 49910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnervoid error_set_errno(Error **errp, int os_errno, ErrorClass err_class, 50910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner const char *fmt, ...) 51910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner{ 52910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner Error *err; 53910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner char *msg1; 54910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner va_list ap; 55910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner int saved_errno = errno; 56910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 57910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner if (errp == NULL) { 58910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner return; 59910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner } 60910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner assert(*errp == NULL); 61910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 62910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner err = g_malloc0(sizeof(*err)); 63910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 64910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner va_start(ap, fmt); 65910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner msg1 = g_strdup_vprintf(fmt, ap); 66910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner if (os_errno != 0) { 67910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner err->msg = g_strdup_printf("%s: %s", msg1, strerror(os_errno)); 68910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner g_free(msg1); 69910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner } else { 70910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner err->msg = msg1; 71910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner } 72910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner va_end(ap); 73910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner err->err_class = err_class; 74910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 75910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner *errp = err; 76910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 77910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner errno = saved_errno; 78910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner} 79910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 80910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnervoid error_setg_file_open(Error **errp, int os_errno, const char *filename) 81910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner{ 82910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner error_setg_errno(errp, os_errno, "Could not open '%s'", filename); 83910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner} 84910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 85910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner#ifdef _WIN32 86910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 87910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnervoid error_set_win32(Error **errp, int win32_err, ErrorClass err_class, 88910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner const char *fmt, ...) 89910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner{ 90910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner Error *err; 91910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner char *msg1; 92910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner va_list ap; 93910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 94910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner if (errp == NULL) { 95910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner return; 96910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner } 97910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner assert(*errp == NULL); 98910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 99910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner err = g_malloc0(sizeof(*err)); 100910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 101910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner va_start(ap, fmt); 102910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner msg1 = g_strdup_vprintf(fmt, ap); 103910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner if (win32_err != 0) { 104910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner char *msg2 = g_win32_error_message(win32_err); 105910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner err->msg = g_strdup_printf("%s: %s (error: %x)", msg1, msg2, 106910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner (unsigned)win32_err); 107910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner g_free(msg2); 108910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner g_free(msg1); 109910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner } else { 110910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner err->msg = msg1; 111910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner } 112910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner va_end(ap); 113910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner err->err_class = err_class; 114910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 115910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner *errp = err; 116910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner} 117910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 118910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner#endif 119910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 120910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' TurnerError *error_copy(const Error *err) 121910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner{ 122910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner Error *err_new; 123910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 124910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner err_new = g_malloc0(sizeof(*err)); 125910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner err_new->msg = g_strdup(err->msg); 126910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner err_new->err_class = err->err_class; 127910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 128910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner return err_new; 129910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner} 130910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 131910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnerbool error_is_set(Error **errp) 132910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner{ 133910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner return (errp && *errp); 134910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner} 135910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 136910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' TurnerErrorClass error_get_class(const Error *err) 137910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner{ 138910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner return err->err_class; 139910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner} 140910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 141910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnerconst char *error_get_pretty(Error *err) 142910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner{ 143910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner return err->msg; 144910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner} 145910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 146910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnervoid error_free(Error *err) 147910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner{ 148910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner if (err) { 149910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner g_free(err->msg); 150910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner g_free(err); 151910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner } 152910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner} 153910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 154910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turnervoid error_propagate(Error **dst_err, Error *local_err) 155910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner{ 156910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner if (dst_err && !*dst_err) { 157910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner *dst_err = local_err; 158910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner } else if (local_err) { 159910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner error_free(local_err); 160910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner } 161910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner} 162