Annotation of qemu/qerror.c, revision 1.1.1.6

1.1       root        1: /*
1.1.1.2   root        2:  * QError Module
1.1       root        3:  *
                      4:  * Copyright (C) 2009 Red Hat Inc.
                      5:  *
                      6:  * Authors:
                      7:  *  Luiz Capitulino <lcapitulino@redhat.com>
                      8:  *
                      9:  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
                     10:  * See the COPYING.LIB file in the top-level directory.
                     11:  */
1.1.1.2   root       12: 
                     13: #include "monitor.h"
1.1       root       14: #include "qjson.h"
                     15: #include "qerror.h"
                     16: #include "qemu-common.h"
                     17: 
                     18: static void qerror_destroy_obj(QObject *obj);
                     19: 
                     20: static const QType qerror_type = {
                     21:     .code = QTYPE_QERROR,
                     22:     .destroy = qerror_destroy_obj,
                     23: };
                     24: 
                     25: /**
                     26:  * The 'desc' parameter is a printf-like string, the format of the format
                     27:  * string is:
                     28:  *
                     29:  * %(KEY)
                     30:  *
                     31:  * Where KEY is a QDict key, which has to be passed to qerror_from_info().
                     32:  *
                     33:  * Example:
                     34:  *
                     35:  * "foo error on device: %(device) slot: %(slot_nr)"
                     36:  *
                     37:  * A single percent sign can be printed if followed by a second one,
                     38:  * for example:
                     39:  *
                     40:  * "running out of foo: %(foo)%%"
1.1.1.2   root       41:  *
                     42:  * Please keep the entries in alphabetical order.
1.1.1.6 ! root       43:  * Use scripts/check-qerror.sh to check.
1.1       root       44:  */
                     45: static const QErrorStringTable qerror_table[] = {
                     46:     {
1.1.1.6 ! root       47:         .error_fmt = QERR_ADD_CLIENT_FAILED,
        !            48:         .desc      = "Could not add client",
        !            49:     },
        !            50:     {
        !            51:         .error_fmt = QERR_AMBIGUOUS_PATH,
        !            52:         .desc      = "Path '%(path)' does not uniquely identify a %(object)"
        !            53:     },
        !            54:     {
1.1.1.2   root       55:         .error_fmt = QERR_BAD_BUS_FOR_DEVICE,
                     56:         .desc      = "Device '%(device)' can't go on a %(bad_bus_type) bus",
                     57:     },
                     58:     {
1.1.1.6 ! root       59:         .error_fmt = QERR_BASE_NOT_FOUND,
        !            60:         .desc      = "Base '%(base)' not found",
        !            61:     },
        !            62:     {
1.1.1.5   root       63:         .error_fmt = QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
                     64:         .desc      = "Block format '%(format)' used by device '%(name)' does not support feature '%(feature)'",
                     65:     },
                     66:     {
1.1.1.6 ! root       67:         .error_fmt = QERR_BUS_NO_HOTPLUG,
        !            68:         .desc      = "Bus '%(bus)' does not support hotplugging",
        !            69:     },
        !            70:     {
1.1.1.2   root       71:         .error_fmt = QERR_BUS_NOT_FOUND,
                     72:         .desc      = "Bus '%(bus)' not found",
                     73:     },
                     74:     {
1.1.1.6 ! root       75:         .error_fmt = QERR_COMMAND_DISABLED,
        !            76:         .desc      = "The command %(name) has been disabled for this instance",
1.1.1.2   root       77:     },
                     78:     {
1.1       root       79:         .error_fmt = QERR_COMMAND_NOT_FOUND,
                     80:         .desc      = "The command %(name) has not been found",
                     81:     },
                     82:     {
                     83:         .error_fmt = QERR_DEVICE_ENCRYPTED,
1.1.1.2   root       84:         .desc      = "Device '%(device)' is encrypted",
                     85:     },
                     86:     {
1.1.1.6 ! root       87:         .error_fmt = QERR_DEVICE_FEATURE_BLOCKS_MIGRATION,
        !            88:         .desc      = "Migration is disabled when using feature '%(feature)' in device '%(device)'",
        !            89:     },
        !            90:     {
        !            91:         .error_fmt = QERR_DEVICE_HAS_NO_MEDIUM,
        !            92:         .desc      = "Device '%(device)' has no medium",
        !            93:     },
        !            94:     {
1.1.1.2   root       95:         .error_fmt = QERR_DEVICE_INIT_FAILED,
                     96:         .desc      = "Device '%(device)' could not be initialized",
                     97:     },
                     98:     {
                     99:         .error_fmt = QERR_DEVICE_IN_USE,
                    100:         .desc      = "Device '%(device)' is in use",
1.1       root      101:     },
                    102:     {
1.1.1.6 ! root      103:         .error_fmt = QERR_DEVICE_IS_READ_ONLY,
        !           104:         .desc      = "Device '%(device)' is read only",
1.1.1.5   root      105:     },
                    106:     {
1.1       root      107:         .error_fmt = QERR_DEVICE_LOCKED,
1.1.1.2   root      108:         .desc      = "Device '%(device)' is locked",
                    109:     },
                    110:     {
                    111:         .error_fmt = QERR_DEVICE_MULTIPLE_BUSSES,
                    112:         .desc      = "Device '%(device)' has multiple child busses",
1.1       root      113:     },
                    114:     {
1.1.1.6 ! root      115:         .error_fmt = QERR_DEVICE_NO_BUS,
        !           116:         .desc      = "Device '%(device)' has no child bus",
        !           117:     },
        !           118:     {
        !           119:         .error_fmt = QERR_DEVICE_NO_HOTPLUG,
        !           120:         .desc      = "Device '%(device)' does not support hotplugging",
        !           121:     },
        !           122:     {
1.1       root      123:         .error_fmt = QERR_DEVICE_NOT_ACTIVE,
1.1.1.2   root      124:         .desc      = "Device '%(device)' has not been activated",
                    125:     },
                    126:     {
                    127:         .error_fmt = QERR_DEVICE_NOT_ENCRYPTED,
                    128:         .desc      = "Device '%(device)' is not encrypted",
1.1       root      129:     },
                    130:     {
                    131:         .error_fmt = QERR_DEVICE_NOT_FOUND,
1.1.1.2   root      132:         .desc      = "Device '%(device)' not found",
1.1       root      133:     },
                    134:     {
                    135:         .error_fmt = QERR_DEVICE_NOT_REMOVABLE,
1.1.1.2   root      136:         .desc      = "Device '%(device)' is not removable",
                    137:     },
                    138:     {
                    139:         .error_fmt = QERR_DUPLICATE_ID,
                    140:         .desc      = "Duplicate ID '%(id)' for %(object)",
1.1       root      141:     },
                    142:     {
                    143:         .error_fmt = QERR_FD_NOT_FOUND,
1.1.1.2   root      144:         .desc      = "File descriptor named '%(name)' not found",
1.1       root      145:     },
                    146:     {
                    147:         .error_fmt = QERR_FD_NOT_SUPPLIED,
                    148:         .desc      = "No file descriptor supplied via SCM_RIGHTS",
                    149:     },
                    150:     {
1.1.1.5   root      151:         .error_fmt = QERR_FEATURE_DISABLED,
                    152:         .desc      = "The feature '%(name)' is not enabled",
                    153:     },
                    154:     {
1.1       root      155:         .error_fmt = QERR_INVALID_BLOCK_FORMAT,
1.1.1.2   root      156:         .desc      = "Invalid block format '%(name)'",
1.1       root      157:     },
                    158:     {
                    159:         .error_fmt = QERR_INVALID_PARAMETER,
1.1.1.2   root      160:         .desc      = "Invalid parameter '%(name)'",
1.1       root      161:     },
                    162:     {
1.1.1.6 ! root      163:         .error_fmt = QERR_INVALID_PARAMETER_COMBINATION,
        !           164:         .desc      = "Invalid parameter combination",
        !           165:     },
        !           166:     {
1.1       root      167:         .error_fmt = QERR_INVALID_PARAMETER_TYPE,
1.1.1.6 ! root      168:         .desc      = "Invalid parameter type for '%(name)', expected: %(expected)",
1.1       root      169:     },
                    170:     {
1.1.1.2   root      171:         .error_fmt = QERR_INVALID_PARAMETER_VALUE,
                    172:         .desc      = "Parameter '%(name)' expects %(expected)",
                    173:     },
                    174:     {
1.1       root      175:         .error_fmt = QERR_INVALID_PASSWORD,
1.1.1.2   root      176:         .desc      = "Password incorrect",
1.1       root      177:     },
                    178:     {
1.1.1.6 ! root      179:         .error_fmt = QERR_IO_ERROR,
        !           180:         .desc      = "An IO error has occurred",
1.1       root      181:     },
                    182:     {
1.1.1.4   root      183:         .error_fmt = QERR_JSON_PARSE_ERROR,
                    184:         .desc      = "JSON parse error, %(message)",
                    185: 
                    186:     },
                    187:     {
1.1.1.6 ! root      188:         .error_fmt = QERR_JSON_PARSING,
        !           189:         .desc      = "Invalid JSON syntax",
        !           190:     },
        !           191:     {
1.1       root      192:         .error_fmt = QERR_KVM_MISSING_CAP,
                    193:         .desc      = "Using KVM without %(capability), %(feature) unavailable",
                    194:     },
                    195:     {
1.1.1.6 ! root      196:         .error_fmt = QERR_MIGRATION_ACTIVE,
        !           197:         .desc      = "There's a migration process in progress",
        !           198:     },
        !           199:     {
        !           200:         .error_fmt = QERR_MIGRATION_NOT_SUPPORTED,
        !           201:         .desc      = "State blocked by non-migratable device '%(device)'",
        !           202:     },
        !           203:     {
1.1.1.2   root      204:         .error_fmt = QERR_MIGRATION_EXPECTED,
                    205:         .desc      = "An incoming migration is expected before this command can be executed",
                    206:     },
                    207:     {
1.1       root      208:         .error_fmt = QERR_MISSING_PARAMETER,
1.1.1.2   root      209:         .desc      = "Parameter '%(name)' is missing",
                    210:     },
                    211:     {
                    212:         .error_fmt = QERR_NO_BUS_FOR_DEVICE,
                    213:         .desc      = "No '%(bus)' bus found for device '%(device)'",
                    214:     },
                    215:     {
1.1.1.6 ! root      216:         .error_fmt = QERR_NOT_SUPPORTED,
        !           217:         .desc      = "Not supported",
        !           218:     },
        !           219:     {
1.1.1.2   root      220:         .error_fmt = QERR_OPEN_FILE_FAILED,
                    221:         .desc      = "Could not open '%(filename)'",
                    222:     },
                    223:     {
1.1.1.6 ! root      224:         .error_fmt = QERR_PERMISSION_DENIED,
        !           225:         .desc      = "Insufficient permission to perform this operation",
        !           226:     },
        !           227:     {
1.1.1.2   root      228:         .error_fmt = QERR_PROPERTY_NOT_FOUND,
                    229:         .desc      = "Property '%(device).%(property)' not found",
                    230:     },
                    231:     {
                    232:         .error_fmt = QERR_PROPERTY_VALUE_BAD,
                    233:         .desc      = "Property '%(device).%(property)' doesn't take value '%(value)'",
                    234:     },
                    235:     {
                    236:         .error_fmt = QERR_PROPERTY_VALUE_IN_USE,
                    237:         .desc      = "Property '%(device).%(property)' can't take value '%(value)', it's in use",
                    238:     },
                    239:     {
                    240:         .error_fmt = QERR_PROPERTY_VALUE_NOT_FOUND,
                    241:         .desc      = "Property '%(device).%(property)' can't find value '%(value)'",
1.1       root      242:     },
                    243:     {
1.1.1.6 ! root      244:         .error_fmt = QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
        !           245:         .desc      = "Property '%(device).%(property)' doesn't take "
        !           246:                      "value '%(value)', it's not a power of 2",
        !           247:     },
        !           248:     {
        !           249:         .error_fmt = QERR_PROPERTY_VALUE_OUT_OF_RANGE,
        !           250:         .desc      = "Property '%(device).%(property)' doesn't take "
        !           251:                      "value %(value) (minimum: %(min), maximum: %(max))",
        !           252:     },
        !           253:     {
        !           254:         .error_fmt = QERR_QGA_COMMAND_FAILED,
        !           255:         .desc      = "Guest agent command failed, error was '%(message)'",
        !           256:     },
        !           257:     {
        !           258:         .error_fmt = QERR_QGA_LOGGING_FAILED,
        !           259:         .desc      = "Guest agent failed to log non-optional log statement",
        !           260:     },
        !           261:     {
1.1       root      262:         .error_fmt = QERR_QMP_BAD_INPUT_OBJECT,
1.1.1.2   root      263:         .desc      = "Expected '%(expected)' in QMP input",
                    264:     },
                    265:     {
                    266:         .error_fmt = QERR_QMP_BAD_INPUT_OBJECT_MEMBER,
                    267:         .desc      = "QMP input object member '%(member)' expects '%(expected)'",
                    268:     },
                    269:     {
                    270:         .error_fmt = QERR_QMP_EXTRA_MEMBER,
                    271:         .desc      = "QMP input object member '%(member)' is unexpected",
1.1       root      272:     },
                    273:     {
1.1.1.5   root      274:         .error_fmt = QERR_RESET_REQUIRED,
                    275:         .desc      = "Resetting the Virtual Machine is required",
                    276:     },
                    277:     {
1.1       root      278:         .error_fmt = QERR_SET_PASSWD_FAILED,
                    279:         .desc      = "Could not set password",
                    280:     },
                    281:     {
                    282:         .error_fmt = QERR_TOO_MANY_FILES,
                    283:         .desc      = "Too many open files",
                    284:     },
                    285:     {
                    286:         .error_fmt = QERR_UNDEFINED_ERROR,
1.1.1.6 ! root      287:         .desc      = "An undefined error has occurred",
1.1.1.4   root      288:     },
                    289:     {
1.1.1.3   root      290:         .error_fmt = QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
                    291:         .desc      = "'%(device)' uses a %(format) feature which is not "
                    292:                      "supported by this qemu version: %(feature)",
                    293:     },
                    294:     {
1.1.1.6 ! root      295:         .error_fmt = QERR_UNSUPPORTED,
        !           296:         .desc      = "this feature or command is not currently supported",
        !           297:     },
        !           298:     {
1.1.1.5   root      299:         .error_fmt = QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION,
                    300:         .desc      = "Migration is disabled when VirtFS export path '%(path)' "
                    301:                      "is mounted in the guest using mount_tag '%(tag)'",
                    302:     },
                    303:     {
1.1       root      304:         .error_fmt = QERR_VNC_SERVER_FAILED,
                    305:         .desc      = "Could not start VNC server on %(target)",
                    306:     },
1.1.1.4   root      307:     {
1.1.1.6 ! root      308:         .error_fmt = QERR_SOCKET_CONNECT_IN_PROGRESS,
        !           309:         .desc      = "Connection can not be completed immediately",
1.1.1.4   root      310:     },
                    311:     {
1.1.1.6 ! root      312:         .error_fmt = QERR_SOCKET_CONNECT_FAILED,
        !           313:         .desc      = "Failed to connect to socket",
        !           314:     },
        !           315:     {
        !           316:         .error_fmt = QERR_SOCKET_LISTEN_FAILED,
        !           317:         .desc      = "Failed to set socket to listening mode",
        !           318:     },
        !           319:     {
        !           320:         .error_fmt = QERR_SOCKET_BIND_FAILED,
        !           321:         .desc      = "Failed to bind socket",
        !           322:     },
        !           323:     {
        !           324:         .error_fmt = QERR_SOCKET_CREATE_FAILED,
        !           325:         .desc      = "Failed to create socket",
1.1.1.4   root      326:     },
1.1       root      327:     {}
                    328: };
                    329: 
                    330: /**
                    331:  * qerror_new(): Create a new QError
                    332:  *
                    333:  * Return strong reference.
                    334:  */
                    335: QError *qerror_new(void)
                    336: {
                    337:     QError *qerr;
                    338: 
1.1.1.5   root      339:     qerr = g_malloc0(sizeof(*qerr));
1.1       root      340:     QOBJECT_INIT(qerr, &qerror_type);
                    341: 
                    342:     return qerr;
                    343: }
                    344: 
1.1.1.3   root      345: static void GCC_FMT_ATTR(2, 3) qerror_abort(const QError *qerr,
                    346:                                             const char *fmt, ...)
1.1       root      347: {
                    348:     va_list ap;
                    349: 
                    350:     fprintf(stderr, "qerror: bad call in function '%s':\n", qerr->func);
                    351:     fprintf(stderr, "qerror: -> ");
                    352: 
                    353:     va_start(ap, fmt);
                    354:     vfprintf(stderr, fmt, ap);
                    355:     va_end(ap);
                    356: 
                    357:     fprintf(stderr, "\nqerror: call at %s:%d\n", qerr->file, qerr->linenr);
                    358:     abort();
                    359: }
                    360: 
1.1.1.3   root      361: static void GCC_FMT_ATTR(2, 0) qerror_set_data(QError *qerr,
                    362:                                                const char *fmt, va_list *va)
1.1       root      363: {
                    364:     QObject *obj;
                    365: 
                    366:     obj = qobject_from_jsonv(fmt, va);
                    367:     if (!obj) {
                    368:         qerror_abort(qerr, "invalid format '%s'", fmt);
                    369:     }
                    370:     if (qobject_type(obj) != QTYPE_QDICT) {
                    371:         qerror_abort(qerr, "error format is not a QDict '%s'", fmt);
                    372:     }
                    373: 
                    374:     qerr->error = qobject_to_qdict(obj);
                    375: 
                    376:     obj = qdict_get(qerr->error, "class");
                    377:     if (!obj) {
                    378:         qerror_abort(qerr, "missing 'class' key in '%s'", fmt);
                    379:     }
                    380:     if (qobject_type(obj) != QTYPE_QSTRING) {
                    381:         qerror_abort(qerr, "'class' key value should be a QString");
                    382:     }
                    383:     
                    384:     obj = qdict_get(qerr->error, "data");
                    385:     if (!obj) {
                    386:         qerror_abort(qerr, "missing 'data' key in '%s'", fmt);
                    387:     }
                    388:     if (qobject_type(obj) != QTYPE_QDICT) {
                    389:         qerror_abort(qerr, "'data' key value should be a QDICT");
                    390:     }
                    391: }
                    392: 
                    393: static void qerror_set_desc(QError *qerr, const char *fmt)
                    394: {
                    395:     int i;
                    396: 
                    397:     // FIXME: inefficient loop
                    398: 
                    399:     for (i = 0; qerror_table[i].error_fmt; i++) {
                    400:         if (strcmp(qerror_table[i].error_fmt, fmt) == 0) {
                    401:             qerr->entry = &qerror_table[i];
                    402:             return;
                    403:         }
                    404:     }
                    405: 
                    406:     qerror_abort(qerr, "error format '%s' not found", fmt);
                    407: }
                    408: 
                    409: /**
                    410:  * qerror_from_info(): Create a new QError from error information
                    411:  *
                    412:  * The information consists of:
                    413:  *
                    414:  * - file   the file name of where the error occurred
                    415:  * - linenr the line number of where the error occurred
                    416:  * - func   the function name of where the error occurred
                    417:  * - fmt    JSON printf-like dictionary, there must exist keys 'class' and
                    418:  *          'data'
                    419:  * - va     va_list of all arguments specified by fmt
                    420:  *
                    421:  * Return strong reference.
                    422:  */
                    423: QError *qerror_from_info(const char *file, int linenr, const char *func,
                    424:                          const char *fmt, va_list *va)
                    425: {
                    426:     QError *qerr;
                    427: 
                    428:     qerr = qerror_new();
1.1.1.2   root      429:     loc_save(&qerr->loc);
1.1       root      430:     qerr->linenr = linenr;
                    431:     qerr->file = file;
                    432:     qerr->func = func;
                    433: 
                    434:     if (!fmt) {
                    435:         qerror_abort(qerr, "QDict not specified");
                    436:     }
                    437: 
                    438:     qerror_set_data(qerr, fmt, va);
                    439:     qerror_set_desc(qerr, fmt);
                    440: 
                    441:     return qerr;
                    442: }
                    443: 
1.1.1.4   root      444: static void parse_error(const QErrorStringTable *entry, int c)
1.1       root      445: {
1.1.1.4   root      446:     fprintf(stderr, "expected '%c' in '%s'", c, entry->desc);
                    447:     abort();
1.1       root      448: }
                    449: 
1.1.1.4   root      450: static const char *append_field(QDict *error, QString *outstr,
                    451:                                 const QErrorStringTable *entry,
1.1       root      452:                                 const char *start)
                    453: {
                    454:     QObject *obj;
                    455:     QDict *qdict;
                    456:     QString *key_qs;
                    457:     const char *end, *key;
                    458: 
                    459:     if (*start != '%')
1.1.1.4   root      460:         parse_error(entry, '%');
1.1       root      461:     start++;
                    462:     if (*start != '(')
1.1.1.4   root      463:         parse_error(entry, '(');
1.1       root      464:     start++;
                    465: 
                    466:     end = strchr(start, ')');
                    467:     if (!end)
1.1.1.4   root      468:         parse_error(entry, ')');
1.1       root      469: 
                    470:     key_qs = qstring_from_substr(start, 0, end - start - 1);
                    471:     key = qstring_get_str(key_qs);
                    472: 
1.1.1.4   root      473:     qdict = qobject_to_qdict(qdict_get(error, "data"));
1.1       root      474:     obj = qdict_get(qdict, key);
                    475:     if (!obj) {
1.1.1.4   root      476:         abort();
1.1       root      477:     }
                    478: 
                    479:     switch (qobject_type(obj)) {
                    480:         case QTYPE_QSTRING:
                    481:             qstring_append(outstr, qdict_get_str(qdict, key));
                    482:             break;
                    483:         case QTYPE_QINT:
                    484:             qstring_append_int(outstr, qdict_get_int(qdict, key));
                    485:             break;
                    486:         default:
1.1.1.4   root      487:             abort();
1.1       root      488:     }
                    489: 
                    490:     QDECREF(key_qs);
                    491:     return ++end;
                    492: }
                    493: 
1.1.1.4   root      494: static QString *qerror_format_desc(QDict *error,
                    495:                                    const QErrorStringTable *entry)
1.1       root      496: {
                    497:     QString *qstring;
1.1.1.4   root      498:     const char *p;
1.1       root      499: 
1.1.1.4   root      500:     assert(entry != NULL);
1.1       root      501: 
                    502:     qstring = qstring_new();
                    503: 
1.1.1.4   root      504:     for (p = entry->desc; *p != '\0';) {
1.1       root      505:         if (*p != '%') {
                    506:             qstring_append_chr(qstring, *p++);
                    507:         } else if (*(p + 1) == '%') {
                    508:             qstring_append_chr(qstring, '%');
                    509:             p += 2;
                    510:         } else {
1.1.1.4   root      511:             p = append_field(error, qstring, entry, p);
1.1       root      512:         }
                    513:     }
                    514: 
                    515:     return qstring;
                    516: }
                    517: 
1.1.1.4   root      518: QString *qerror_format(const char *fmt, QDict *error)
                    519: {
                    520:     const QErrorStringTable *entry = NULL;
                    521:     int i;
                    522: 
                    523:     for (i = 0; qerror_table[i].error_fmt; i++) {
                    524:         if (strcmp(qerror_table[i].error_fmt, fmt) == 0) {
                    525:             entry = &qerror_table[i];
                    526:             break;
                    527:         }
                    528:     }
                    529: 
                    530:     return qerror_format_desc(error, entry);
                    531: }
                    532: 
                    533: /**
                    534:  * qerror_human(): Format QError data into human-readable string.
                    535:  */
                    536: QString *qerror_human(const QError *qerror)
                    537: {
                    538:     return qerror_format_desc(qerror->error, qerror->entry);
                    539: }
                    540: 
1.1       root      541: /**
                    542:  * qerror_print(): Print QError data
                    543:  *
                    544:  * This function will print the member 'desc' of the specified QError object,
1.1.1.2   root      545:  * it uses error_report() for this, so that the output is routed to the right
1.1       root      546:  * place (ie. stderr or Monitor's device).
                    547:  */
1.1.1.2   root      548: void qerror_print(QError *qerror)
1.1       root      549: {
                    550:     QString *qstring = qerror_human(qerror);
1.1.1.2   root      551:     loc_push_restore(&qerror->loc);
                    552:     error_report("%s", qstring_get_str(qstring));
                    553:     loc_pop(&qerror->loc);
1.1       root      554:     QDECREF(qstring);
                    555: }
                    556: 
1.1.1.2   root      557: void qerror_report_internal(const char *file, int linenr, const char *func,
                    558:                             const char *fmt, ...)
                    559: {
                    560:     va_list va;
                    561:     QError *qerror;
                    562: 
                    563:     va_start(va, fmt);
                    564:     qerror = qerror_from_info(file, linenr, func, fmt, &va);
                    565:     va_end(va);
                    566: 
                    567:     if (monitor_cur_is_qmp()) {
                    568:         monitor_set_error(cur_mon, qerror);
                    569:     } else {
                    570:         qerror_print(qerror);
                    571:         QDECREF(qerror);
                    572:     }
                    573: }
                    574: 
1.1.1.5   root      575: /* Evil... */
                    576: struct Error
                    577: {
                    578:     QDict *obj;
                    579:     const char *fmt;
                    580:     char *msg;
                    581: };
                    582: 
                    583: void qerror_report_err(Error *err)
                    584: {
                    585:     QError *qerr;
                    586:     int i;
                    587: 
                    588:     qerr = qerror_new();
                    589:     loc_save(&qerr->loc);
                    590:     QINCREF(err->obj);
                    591:     qerr->error = err->obj;
                    592: 
                    593:     for (i = 0; qerror_table[i].error_fmt; i++) {
                    594:         if (strcmp(qerror_table[i].error_fmt, err->fmt) == 0) {
                    595:             qerr->entry = &qerror_table[i];
                    596:             break;
                    597:         }
                    598:     }
                    599: 
                    600:     if (monitor_cur_is_qmp()) {
                    601:         monitor_set_error(cur_mon, qerr);
                    602:     } else {
                    603:         qerror_print(qerr);
                    604:         QDECREF(qerr);
                    605:     }
                    606: }
                    607: 
1.1.1.6 ! root      608: void assert_no_error(Error *err)
        !           609: {
        !           610:     if (err) {
        !           611:         qerror_report_err(err);
        !           612:         abort();
        !           613:     }
        !           614: }
        !           615: 
1.1       root      616: /**
                    617:  * qobject_to_qerror(): Convert a QObject into a QError
                    618:  */
                    619: QError *qobject_to_qerror(const QObject *obj)
                    620: {
                    621:     if (qobject_type(obj) != QTYPE_QERROR) {
                    622:         return NULL;
                    623:     }
                    624: 
                    625:     return container_of(obj, QError, base);
                    626: }
                    627: 
                    628: /**
                    629:  * qerror_destroy_obj(): Free all memory allocated by a QError
                    630:  */
                    631: static void qerror_destroy_obj(QObject *obj)
                    632: {
                    633:     QError *qerr;
                    634: 
                    635:     assert(obj != NULL);
                    636:     qerr = qobject_to_qerror(obj);
                    637: 
                    638:     QDECREF(qerr->error);
1.1.1.5   root      639:     g_free(qerr);
1.1       root      640: }

unix.superglobalmegacorp.com