Home | History | Annotate | Download | only in util
      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