qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

error.c (6742B)


      1 /*
      2  * QEMU Error Objects
      3  *
      4  * Copyright IBM, Corp. 2011
      5  * Copyright (C) 2011-2015 Red Hat, Inc.
      6  *
      7  * Authors:
      8  *  Anthony Liguori   <aliguori@us.ibm.com>
      9  *  Markus Armbruster <armbru@redhat.com>,
     10  *
     11  * This work is licensed under the terms of the GNU LGPL, version 2.  See
     12  * the COPYING.LIB file in the top-level directory.
     13  */
     14 
     15 #include "qemu/osdep.h"
     16 #include "qapi/error.h"
     17 #include "qemu/error-report.h"
     18 
     19 struct Error
     20 {
     21     char *msg;
     22     ErrorClass err_class;
     23     const char *src, *func;
     24     int line;
     25     GString *hint;
     26 };
     27 
     28 Error *error_abort;
     29 Error *error_fatal;
     30 
     31 static void error_handle_fatal(Error **errp, Error *err)
     32 {
     33     if (errp == &error_abort) {
     34         fprintf(stderr, "Unexpected error in %s() at %s:%d:\n",
     35                 err->func, err->src, err->line);
     36         error_report("%s", error_get_pretty(err));
     37         if (err->hint) {
     38             error_printf("%s", err->hint->str);
     39         }
     40         abort();
     41     }
     42     if (errp == &error_fatal) {
     43         error_report_err(err);
     44         exit(1);
     45     }
     46 }
     47 
     48 static void error_setv(Error **errp,
     49                        const char *src, int line, const char *func,
     50                        ErrorClass err_class, const char *fmt, va_list ap,
     51                        const char *suffix)
     52 {
     53     Error *err;
     54     int saved_errno = errno;
     55 
     56     if (errp == NULL) {
     57         return;
     58     }
     59     assert(*errp == NULL);
     60 
     61     err = g_malloc0(sizeof(*err));
     62     err->msg = g_strdup_vprintf(fmt, ap);
     63     if (suffix) {
     64         char *msg = err->msg;
     65         err->msg = g_strdup_printf("%s: %s", msg, suffix);
     66         g_free(msg);
     67     }
     68     err->err_class = err_class;
     69     err->src = src;
     70     err->line = line;
     71     err->func = func;
     72 
     73     error_handle_fatal(errp, err);
     74     *errp = err;
     75 
     76     errno = saved_errno;
     77 }
     78 
     79 void error_set_internal(Error **errp,
     80                         const char *src, int line, const char *func,
     81                         ErrorClass err_class, const char *fmt, ...)
     82 {
     83     va_list ap;
     84 
     85     va_start(ap, fmt);
     86     error_setv(errp, src, line, func, err_class, fmt, ap, NULL);
     87     va_end(ap);
     88 }
     89 
     90 void error_setg_internal(Error **errp,
     91                          const char *src, int line, const char *func,
     92                          const char *fmt, ...)
     93 {
     94     va_list ap;
     95 
     96     va_start(ap, fmt);
     97     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap, NULL);
     98     va_end(ap);
     99 }
    100 
    101 void error_setg_errno_internal(Error **errp,
    102                                const char *src, int line, const char *func,
    103                                int os_errno, const char *fmt, ...)
    104 {
    105     va_list ap;
    106     int saved_errno = errno;
    107 
    108     va_start(ap, fmt);
    109     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR, fmt, ap,
    110                os_errno != 0 ? strerror(os_errno) : NULL);
    111     va_end(ap);
    112 
    113     errno = saved_errno;
    114 }
    115 
    116 void error_setg_file_open_internal(Error **errp,
    117                                    const char *src, int line, const char *func,
    118                                    int os_errno, const char *filename)
    119 {
    120     error_setg_errno_internal(errp, src, line, func, os_errno,
    121                               "Could not open '%s'", filename);
    122 }
    123 
    124 void error_vprepend(Error *const *errp, const char *fmt, va_list ap)
    125 {
    126     GString *newmsg;
    127 
    128     if (!errp) {
    129         return;
    130     }
    131 
    132     newmsg = g_string_new(NULL);
    133     g_string_vprintf(newmsg, fmt, ap);
    134     g_string_append(newmsg, (*errp)->msg);
    135     g_free((*errp)->msg);
    136     (*errp)->msg = g_string_free(newmsg, 0);
    137 }
    138 
    139 void error_prepend(Error *const *errp, const char *fmt, ...)
    140 {
    141     va_list ap;
    142 
    143     va_start(ap, fmt);
    144     error_vprepend(errp, fmt, ap);
    145     va_end(ap);
    146 }
    147 
    148 void error_append_hint(Error *const *errp, const char *fmt, ...)
    149 {
    150     va_list ap;
    151     int saved_errno = errno;
    152     Error *err;
    153 
    154     if (!errp) {
    155         return;
    156     }
    157     err = *errp;
    158     assert(err && errp != &error_abort && errp != &error_fatal);
    159 
    160     if (!err->hint) {
    161         err->hint = g_string_new(NULL);
    162     }
    163     va_start(ap, fmt);
    164     g_string_append_vprintf(err->hint, fmt, ap);
    165     va_end(ap);
    166 
    167     errno = saved_errno;
    168 }
    169 
    170 #ifdef _WIN32
    171 
    172 void error_setg_win32_internal(Error **errp,
    173                                const char *src, int line, const char *func,
    174                                int win32_err, const char *fmt, ...)
    175 {
    176     va_list ap;
    177     char *suffix = NULL;
    178 
    179     if (errp == NULL) {
    180         return;
    181     }
    182 
    183     if (win32_err != 0) {
    184         suffix = g_win32_error_message(win32_err);
    185     }
    186 
    187     va_start(ap, fmt);
    188     error_setv(errp, src, line, func, ERROR_CLASS_GENERIC_ERROR,
    189                fmt, ap, suffix);
    190     va_end(ap);
    191 
    192     g_free(suffix);
    193 }
    194 
    195 #endif
    196 
    197 Error *error_copy(const Error *err)
    198 {
    199     Error *err_new;
    200 
    201     err_new = g_malloc0(sizeof(*err));
    202     err_new->msg = g_strdup(err->msg);
    203     err_new->err_class = err->err_class;
    204     err_new->src = err->src;
    205     err_new->line = err->line;
    206     err_new->func = err->func;
    207     if (err->hint) {
    208         err_new->hint = g_string_new(err->hint->str);
    209     }
    210 
    211     return err_new;
    212 }
    213 
    214 ErrorClass error_get_class(const Error *err)
    215 {
    216     return err->err_class;
    217 }
    218 
    219 const char *error_get_pretty(const Error *err)
    220 {
    221     return err->msg;
    222 }
    223 
    224 void error_report_err(Error *err)
    225 {
    226     error_report("%s", error_get_pretty(err));
    227     if (err->hint) {
    228         error_printf("%s", err->hint->str);
    229     }
    230     error_free(err);
    231 }
    232 
    233 void warn_report_err(Error *err)
    234 {
    235     warn_report("%s", error_get_pretty(err));
    236     if (err->hint) {
    237         error_printf("%s", err->hint->str);
    238     }
    239     error_free(err);
    240 }
    241 
    242 void error_reportf_err(Error *err, const char *fmt, ...)
    243 {
    244     va_list ap;
    245 
    246     va_start(ap, fmt);
    247     error_vprepend(&err, fmt, ap);
    248     va_end(ap);
    249     error_report_err(err);
    250 }
    251 
    252 
    253 void warn_reportf_err(Error *err, const char *fmt, ...)
    254 {
    255     va_list ap;
    256 
    257     va_start(ap, fmt);
    258     error_vprepend(&err, fmt, ap);
    259     va_end(ap);
    260     warn_report_err(err);
    261 }
    262 
    263 void error_free(Error *err)
    264 {
    265     if (err) {
    266         g_free(err->msg);
    267         if (err->hint) {
    268             g_string_free(err->hint, true);
    269         }
    270         g_free(err);
    271     }
    272 }
    273 
    274 void error_free_or_abort(Error **errp)
    275 {
    276     assert(errp && *errp);
    277     error_free(*errp);
    278     *errp = NULL;
    279 }
    280 
    281 void error_propagate(Error **dst_errp, Error *local_err)
    282 {
    283     if (!local_err) {
    284         return;
    285     }
    286     error_handle_fatal(dst_errp, local_err);
    287     if (dst_errp && !*dst_errp) {
    288         *dst_errp = local_err;
    289     } else {
    290         error_free(local_err);
    291     }
    292 }
    293 
    294 void error_propagate_prepend(Error **dst_errp, Error *err,
    295                              const char *fmt, ...)
    296 {
    297     va_list ap;
    298 
    299     if (dst_errp && !*dst_errp) {
    300         va_start(ap, fmt);
    301         error_vprepend(&err, fmt, ap);
    302         va_end(ap);
    303     } /* else error is being ignored, don't bother with prepending */
    304     error_propagate(dst_errp, err);
    305 }