#include "monitor.h"
#include "readline.h"
#include "console.h"
-#include "block.h"
+#include "blockdev.h"
#include "audio/audio.h"
#include "disas.h"
#include "balloon.h"
#include "qint.h"
#include "qfloat.h"
#include "qlist.h"
-#include "qdict.h"
#include "qbool.h"
#include "qstring.h"
-#include "qerror.h"
#include "qjson.h"
#include "json-streamer.h"
#include "json-parser.h"
* 'F' filename
* 'B' block device name
* 's' string (accept optional quote)
+ * 'O' option string of the form NAME=VALUE,...
+ * parsed according to QemuOptsList given by its name
+ * Example: 'device:O' uses qemu_device_opts.
+ * Restriction: only lists with empty desc are supported
+ * TODO lift the restriction
* 'i' 32 bit integer
* 'l' target long (32 or 64 bit)
* 'M' just like 'l', except in user mode the value is
* multiplied by 2^20 (think Mebibyte)
- * 'b' double
+ * 'f' double
* user mode accepts an optional G, g, M, m, K, k suffix,
* which multiplies the value by 2^30 for suffixes G and
* g, 2^20 for M and m, 2^10 for K and k
*
* '?' optional type (for all types, except '/')
* '.' other form of optional type (for 'i' and 'l')
+ * 'b' boolean
+ * user mode accepts "on" or "off"
* '-' optional parameter (eg. '-f')
*
*/
return (mon->flags & MONITOR_USE_CONTROL);
}
+/* Return non-zero iff we have a current monitor, and it is in QMP mode. */
+int monitor_cur_is_qmp(void)
+{
+ return cur_mon && monitor_ctrl_mode(cur_mon);
+}
+
static void monitor_read_command(Monitor *mon, int show_prompt)
{
if (!mon->rs)
void *opaque)
{
if (monitor_ctrl_mode(mon)) {
- qemu_error_new(QERR_MISSING_PARAMETER, "password");
+ qerror_report(QERR_MISSING_PARAMETER, "password");
return -EINVAL;
} else if (mon->rs) {
readline_start(mon->rs, "Password: ", 1, readline_func, opaque);
case QEVENT_STOP:
event_name = "STOP";
break;
+ case QEVENT_RESUME:
+ event_name = "RESUME";
+ break;
case QEVENT_VNC_CONNECTED:
event_name = "VNC_CONNECTED";
break;
help_cmd(mon, qdict_get_try_str(qdict, "name"));
}
-static void do_commit(Monitor *mon, const QDict *qdict)
-{
- int all_devices;
- DriveInfo *dinfo;
- const char *device = qdict_get_str(qdict, "device");
-
- all_devices = !strcmp(device, "all");
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if (!all_devices)
- if (strcmp(bdrv_get_device_name(dinfo->bdrv), device))
- continue;
- bdrv_commit(dinfo->bdrv);
- }
-}
-
static void user_monitor_complete(void *opaque, QObject *ret_data)
{
MonitorCompletionData *data = (MonitorCompletionData *)opaque;
if (cmd->name == NULL) {
if (monitor_ctrl_mode(mon)) {
- qemu_error_new(QERR_COMMAND_NOT_FOUND, item);
+ qerror_report(QERR_COMMAND_NOT_FOUND, item);
return -1;
}
goto help;
} else {
if (monitor_ctrl_mode(mon)) {
/* handler not converted yet */
- qemu_error_new(QERR_COMMAND_NOT_FOUND, item);
+ qerror_report(QERR_COMMAND_NOT_FOUND, item);
return -1;
} else {
cmd->mhandler.info(mon);
qdict_get_str(qdict, "package"));
}
-/**
- * do_info_version(): Show QEMU version
- *
- * Return a QDict with the following information:
- *
- * - "qemu": QEMU's version
- * - "package": package's version
- *
- * Example:
- *
- * { "qemu": "0.11.50", "package": "" }
- */
static void do_info_version(Monitor *mon, QObject **ret_data)
{
*ret_data = qobject_from_jsonf("{ 'qemu': %s, 'package': %s }",
monitor_printf(mon, "%s\n", qdict_get_str(qdict, "name"));
}
-/**
- * do_info_name(): Show VM name
- *
- * Return a QDict with the following information:
- *
- * - "name": VM's name (optional)
- *
- * Example:
- *
- * { "name": "qemu-name" }
- */
static void do_info_name(Monitor *mon, QObject **ret_data)
{
*ret_data = qemu_name ? qobject_from_jsonf("{'name': %s }", qemu_name) :
return qobject_from_jsonf("{ 'name': %s }", p);
}
-/**
- * do_info_commands(): List QMP available commands
- *
- * Each command is represented by a QDict, the returned QObject is a QList
- * of all commands.
- *
- * The QDict contains:
- *
- * - "name": command's name
- *
- * Example:
- *
- * { [ { "name": "query-balloon" }, { "name": "system_powerdown" } ] }
- */
static void do_info_commands(Monitor *mon, QObject **ret_data)
{
QList *cmd_list;
*ret_data = QOBJECT(cmd_list);
}
-#if defined(TARGET_I386)
-static void do_info_hpet_print(Monitor *mon, const QObject *data)
-{
- monitor_printf(mon, "HPET is %s by QEMU\n",
- qdict_get_bool(qobject_to_qdict(data), "enabled") ?
- "enabled" : "disabled");
-}
-
-/**
- * do_info_hpet(): Show HPET state
- *
- * Return a QDict with the following information:
- *
- * - "enabled": true if hpet if enabled, false otherwise
- *
- * Example:
- *
- * { "enabled": true }
- */
-static void do_info_hpet(Monitor *mon, QObject **ret_data)
-{
- *ret_data = qobject_from_jsonf("{ 'enabled': %i }", !no_hpet);
-}
-#endif
-
static void do_info_uuid_print(Monitor *mon, const QObject *data)
{
monitor_printf(mon, "%s\n", qdict_get_str(qobject_to_qdict(data), "UUID"));
}
-/**
- * do_info_uuid(): Show VM UUID
- *
- * Return a QDict with the following information:
- *
- * - "UUID": Universally Unique Identifier
- *
- * Example:
- *
- * { "UUID": "550e8400-e29b-41d4-a716-446655440000" }
- */
static void do_info_uuid(Monitor *mon, QObject **ret_data)
{
char uuid[64];
qlist_iter(cpu_list, print_cpu_iter, mon);
}
-/**
- * do_info_cpus(): Show CPU information
- *
- * Return a QList. Each CPU is represented by a QDict, which contains:
- *
- * - "cpu": CPU index
- * - "current": true if this is the current CPU, false otherwise
- * - "halted": true if the cpu is halted, false otherwise
- * - Current program counter. The key's name depends on the architecture:
- * "pc": i386/x86)64
- * "nip": PPC
- * "pc" and "npc": sparc
- * "PC": mips
- *
- * Example:
- *
- * [ { "CPU": 0, "current": true, "halted": false, "pc": 3227107138 },
- * { "CPU": 1, "current": false, "halted": true, "pc": 7108165 } ]
- */
static void do_info_cpus(Monitor *mon, QObject **ret_data)
{
CPUState *env;
{
int index = qdict_get_int(qdict, "index");
if (mon_set_cpu(index) < 0) {
- qemu_error_new(QERR_INVALID_PARAMETER, "index");
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, "index",
+ "a CPU number");
return -1;
}
return 0;
*/
static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
- exit(0);
- return 0;
-}
-
-static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
-{
- if (bdrv_is_inserted(bs)) {
- if (!force) {
- if (!bdrv_is_removable(bs)) {
- qemu_error_new(QERR_DEVICE_NOT_REMOVABLE,
- bdrv_get_device_name(bs));
- return -1;
- }
- if (bdrv_is_locked(bs)) {
- qemu_error_new(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
- return -1;
- }
- }
- bdrv_close(bs);
- }
- return 0;
-}
-
-static int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
- BlockDriverState *bs;
- int force = qdict_get_int(qdict, "force");
- const char *filename = qdict_get_str(qdict, "device");
-
- bs = bdrv_find(filename);
- if (!bs) {
- qemu_error_new(QERR_DEVICE_NOT_FOUND, filename);
- return -1;
- }
- return eject_device(mon, bs, force);
-}
-
-static int do_block_set_passwd(Monitor *mon, const QDict *qdict,
- QObject **ret_data)
-{
- BlockDriverState *bs;
-
- bs = bdrv_find(qdict_get_str(qdict, "device"));
- if (!bs) {
- qemu_error_new(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
- return -1;
- }
-
- if (bdrv_set_key(bs, qdict_get_str(qdict, "password")) < 0) {
- qemu_error_new(QERR_INVALID_PASSWORD);
- return -1;
- }
+ monitor_suspend(mon);
+ no_shutdown = 0;
+ qemu_system_shutdown_request();
return 0;
}
-static int do_change_block(Monitor *mon, const char *device,
- const char *filename, const char *fmt)
-{
- BlockDriverState *bs;
- BlockDriver *drv = NULL;
-
- bs = bdrv_find(device);
- if (!bs) {
- qemu_error_new(QERR_DEVICE_NOT_FOUND, device);
- return -1;
- }
- if (fmt) {
- drv = bdrv_find_whitelisted_format(fmt);
- if (!drv) {
- qemu_error_new(QERR_INVALID_BLOCK_FORMAT, fmt);
- return -1;
- }
- }
- if (eject_device(mon, bs, 0) < 0) {
- return -1;
- }
- if (bdrv_open2(bs, filename, BDRV_O_RDWR, drv) < 0) {
- return -1;
- }
- return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
-}
-
static int change_vnc_password(const char *password)
{
if (vnc_display_password(NULL, password) < 0) {
- qemu_error_new(QERR_SET_PASSWD_FAILED);
+ qerror_report(QERR_SET_PASSWD_FAILED);
return -1;
}
}
} else {
if (vnc_display_open(NULL, target) < 0) {
- qemu_error_new(QERR_VNC_SERVER_FAILED, target);
+ qerror_report(QERR_VNC_SERVER_FAILED, target);
return -1;
}
}
return ret;
}
-static void do_screen_dump(Monitor *mon, const QDict *qdict)
+static int do_screen_dump(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
vga_hw_screen_dump(qdict_get_str(qdict, "filename"));
+ return 0;
}
static void do_logfile(Monitor *mon, const QDict *qdict)
f = fopen(filename, "wb");
if (!f) {
- qemu_error_new(QERR_OPEN_FILE_FAILED, filename);
+ qerror_report(QERR_OPEN_FILE_FAILED, filename);
return -1;
}
while (size != 0) {
f = fopen(filename, "wb");
if (!f) {
- qemu_error_new(QERR_OPEN_FILE_FAILED, filename);
+ qerror_report(QERR_OPEN_FILE_FAILED, filename);
return -1;
}
while (size != 0) {
{ 0x17, "i" },
{ 0x18, "o" },
{ 0x19, "p" },
-
+ { 0x1a, "bracket_left" },
+ { 0x1b, "bracket_right" },
{ 0x1c, "ret" },
{ 0x1e, "a" },
{ 0x24, "j" },
{ 0x25, "k" },
{ 0x26, "l" },
+ { 0x27, "semicolon" },
+ { 0x28, "apostrophe" },
+ { 0x29, "grave_accent" },
+ { 0x2b, "backslash" },
{ 0x2c, "z" },
{ 0x2d, "x" },
{ 0x2e, "c" },
}
}
-/**
- * do_info_kvm(): Show KVM information
- *
- * Return a QDict with the following information:
- *
- * - "enabled": true if KVM support is enabled, false otherwise
- * - "present": true if QEMU has KVM support, false otherwise
- *
- * Example:
- *
- * { "enabled": true, "present": true }
- */
static void do_info_kvm(Monitor *mon, QObject **ret_data)
{
#ifdef CONFIG_KVM
monitor_printf(mon, "\n");
}
-/**
- * do_info_status(): VM status
- *
- * Return a QDict with the following information:
- *
- * - "running": true if the VM is running, or false if it is paused
- * - "singlestep": true if the VM is in single step mode, false otherwise
- *
- * Example:
- *
- * { "running": true, "singlestep": false }
- */
static void do_info_status(Monitor *mon, QObject **ret_data)
{
*ret_data = qobject_from_jsonf("{ 'running': %i, 'singlestep': %i }",
vm_running, singlestep);
}
-static void print_balloon_stat(const char *key, QObject *obj, void *opaque)
-{
- Monitor *mon = opaque;
-
- if (strcmp(key, "actual"))
- monitor_printf(mon, ",%s=%" PRId64, key,
- qint_get_int(qobject_to_qint(obj)));
-}
-
-static void monitor_print_balloon(Monitor *mon, const QObject *data)
-{
- QDict *qdict;
-
- qdict = qobject_to_qdict(data);
- if (!qdict_haskey(qdict, "actual"))
- return;
-
- monitor_printf(mon, "balloon: actual=%" PRId64,
- qdict_get_int(qdict, "actual") >> 20);
- qdict_iter(qdict, print_balloon_stat, mon);
- monitor_printf(mon, "\n");
-}
-
-/**
- * do_info_balloon(): Balloon information
- *
- * Make an asynchronous request for balloon info. When the request completes
- * a QDict will be returned according to the following specification:
- *
- * - "actual": current balloon value in bytes
- * The following fields may or may not be present:
- * - "mem_swapped_in": Amount of memory swapped in (bytes)
- * - "mem_swapped_out": Amount of memory swapped out (bytes)
- * - "major_page_faults": Number of major faults
- * - "minor_page_faults": Number of minor faults
- * - "free_mem": Total amount of free and unused memory (bytes)
- * - "total_mem": Total amount of available memory (bytes)
- *
- * Example:
- *
- * { "actual": 1073741824, "mem_swapped_in": 0, "mem_swapped_out": 0,
- * "major_page_faults": 142, "minor_page_faults": 239245,
- * "free_mem": 1014185984, "total_mem": 1044668416 }
- */
-static int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque)
-{
- int ret;
-
- if (kvm_enabled() && !kvm_has_sync_mmu()) {
- qemu_error_new(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
- return -1;
- }
-
- ret = qemu_balloon_status(cb, opaque);
- if (!ret) {
- qemu_error_new(QERR_DEVICE_NOT_ACTIVE, "balloon");
- return -1;
- }
-
- return 0;
-}
-
-/**
- * do_balloon(): Request VM to change its memory allocation
- */
-static int do_balloon(Monitor *mon, const QDict *params,
- MonitorCompletion cb, void *opaque)
-{
- int ret;
-
- if (kvm_enabled() && !kvm_has_sync_mmu()) {
- qemu_error_new(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
- return -1;
- }
-
- ret = qemu_balloon(qdict_get_int(params, "value"), cb, opaque);
- if (ret == 0) {
- qemu_error_new(QERR_DEVICE_NOT_ACTIVE, "balloon");
- return -1;
- }
-
- cb(opaque, NULL);
- return 0;
-}
-
static qemu_acl *find_acl(Monitor *mon, const char *name)
{
qemu_acl *acl = qemu_acl_find(name);
fd = qemu_chr_get_msgfd(mon->chr);
if (fd == -1) {
- qemu_error_new(QERR_FD_NOT_SUPPLIED);
+ qerror_report(QERR_FD_NOT_SUPPLIED);
return -1;
}
if (qemu_isdigit(fdname[0])) {
- qemu_error_new(QERR_INVALID_PARAMETER, "fdname");
- return -1;
- }
-
- fd = dup(fd);
- if (fd == -1) {
- if (errno == EMFILE)
- qemu_error_new(QERR_TOO_MANY_FILES);
- else
- qemu_error_new(QERR_UNDEFINED_ERROR);
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, "fdname",
+ "a name not starting with a digit");
return -1;
}
return 0;
}
- qemu_error_new(QERR_FD_NOT_FOUND, fdname);
+ qerror_report(QERR_FD_NOT_FOUND, fdname);
return -1;
}
.help = "show the active virtual memory mappings",
.mhandler.info = mem_info,
},
- {
- .name = "hpet",
- .args_type = "",
- .params = "",
- .help = "show state of HPET",
- .user_print = do_info_hpet_print,
- .mhandler.info_new = do_info_hpet,
- },
#endif
{
.name = "jit",
static target_long monitor_get_psr (const struct MonitorDef *md, int val)
{
CPUState *env = mon_get_cpu();
- return GET_PSR(env);
+
+ return cpu_get_psr(env);
}
#endif
qdict_put(qdict, key, qstring_from_str(buf));
}
break;
+ case 'O':
+ {
+ QemuOptsList *opts_list;
+ QemuOpts *opts;
+
+ opts_list = qemu_find_opts(key);
+ if (!opts_list || opts_list->desc->name) {
+ goto bad_type;
+ }
+ while (qemu_isspace(*p)) {
+ p++;
+ }
+ if (!*p)
+ break;
+ if (get_str(buf, sizeof(buf), &p) < 0) {
+ goto fail;
+ }
+ opts = qemu_opts_parse(opts_list, buf, 1);
+ if (!opts) {
+ goto fail;
+ }
+ qemu_opts_to_qdict(opts, qdict);
+ qemu_opts_del(opts);
+ }
+ break;
case '/':
{
int count, format, size;
qdict_put(qdict, key, qint_from_int(val));
}
break;
- case 'b':
+ case 'f':
case 'T':
{
double val;
if (get_double(mon, &val, &p) < 0) {
goto fail;
}
- if (c == 'b' && *p) {
+ if (c == 'f' && *p) {
switch (*p) {
case 'K': case 'k':
val *= 1 << 10; p++; break;
qdict_put(qdict, key, qfloat_from_double(val));
}
break;
+ case 'b':
+ {
+ const char *beg;
+ int val;
+
+ while (qemu_isspace(*p)) {
+ p++;
+ }
+ beg = p;
+ while (qemu_isgraph(*p)) {
+ p++;
+ }
+ if (p - beg == 2 && !memcmp(beg, "on", p - beg)) {
+ val = 1;
+ } else if (p - beg == 3 && !memcmp(beg, "off", p - beg)) {
+ val = 0;
+ } else {
+ monitor_printf(mon, "Expected 'on' or 'off'\n");
+ goto fail;
+ }
+ qdict_put(qdict, key, qbool_from_int(val));
+ }
+ break;
case '-':
{
const char *tmp = p;
}
}
-static void monitor_print_error(Monitor *mon)
-{
- qerror_print(mon->error);
- QDECREF(mon->error);
- mon->error = NULL;
-}
-
static int is_async_return(const QObject *data)
{
if (data && qobject_type(data) == QTYPE_QDICT) {
static void handler_audit(Monitor *mon, const mon_cmd_t *cmd, int ret)
{
- if (ret && !monitor_has_error(mon)) {
- /*
- * If it returns failure, it must have passed on error.
- *
- * Action: Report an internal error to the client if in QMP.
- */
- if (monitor_ctrl_mode(mon)) {
- qemu_error_new(QERR_UNDEFINED_ERROR);
+ if (monitor_ctrl_mode(mon)) {
+ if (ret && !monitor_has_error(mon)) {
+ /*
+ * If it returns failure, it must have passed on error.
+ *
+ * Action: Report an internal error to the client if in QMP.
+ */
+ qerror_report(QERR_UNDEFINED_ERROR);
+ MON_DEBUG("command '%s' returned failure but did not pass an error\n",
+ cmd->name);
}
- MON_DEBUG("command '%s' returned failure but did not pass an error\n",
- cmd->name);
- }
#ifdef CONFIG_DEBUG_MONITOR
- if (!ret && monitor_has_error(mon)) {
- /*
- * If it returns success, it must not have passed an error.
- *
- * Action: Report the passed error to the client.
- */
- MON_DEBUG("command '%s' returned success but passed an error\n",
- cmd->name);
- }
+ if (!ret && monitor_has_error(mon)) {
+ /*
+ * If it returns success, it must not have passed an error.
+ *
+ * Action: Report the passed error to the client.
+ */
+ MON_DEBUG("command '%s' returned success but passed an error\n",
+ cmd->name);
+ }
- if (mon_print_count_get(mon) > 0 && strcmp(cmd->name, "info") != 0) {
- /*
- * Handlers should not call Monitor print functions.
- *
- * Action: Ignore them in QMP.
- *
- * (XXX: we don't check any 'info' or 'query' command here
- * because the user print function _is_ called by do_info(), hence
- * we will trigger this check. This problem will go away when we
- * make 'query' commands real and kill do_info())
- */
- MON_DEBUG("command '%s' called print functions %d time(s)\n",
- cmd->name, mon_print_count_get(mon));
- }
+ if (mon_print_count_get(mon) > 0 && strcmp(cmd->name, "info") != 0) {
+ /*
+ * Handlers should not call Monitor print functions.
+ *
+ * Action: Ignore them in QMP.
+ *
+ * (XXX: we don't check any 'info' or 'query' command here
+ * because the user print function _is_ called by do_info(), hence
+ * we will trigger this check. This problem will go away when we
+ * make 'query' commands real and kill do_info())
+ */
+ MON_DEBUG("command '%s' called print functions %d time(s)\n",
+ cmd->name, mon_print_count_get(mon));
+ }
#endif
+ } else {
+ assert(!monitor_has_error(mon));
+ QDECREF(mon->error);
+ mon->error = NULL;
+ }
}
static void monitor_call_handler(Monitor *mon, const mon_cmd_t *cmd,
if (!cmd)
goto out;
- qemu_errors_to_mon(mon);
-
if (monitor_handler_is_async(cmd)) {
user_async_cmd_handler(mon, cmd, qdict);
} else if (monitor_handler_ported(cmd)) {
cmd->mhandler.cmd(mon, qdict);
}
- if (monitor_has_error(mon))
- monitor_print_error(mon);
-
- qemu_errors_to_previous();
-
out:
QDECREF(qdict);
}
static int check_opt(const CmdArgs *cmd_args, const char *name, QDict *args)
{
if (!cmd_args->optional) {
- qemu_error_new(QERR_MISSING_PARAMETER, name);
+ qerror_report(QERR_MISSING_PARAMETER, name);
return -1;
}
case 'B':
case 's':
if (qobject_type(value) != QTYPE_QSTRING) {
- qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "string");
+ qerror_report(QERR_INVALID_PARAMETER_TYPE, name, "string");
return -1;
}
break;
for (i = 0; keys[i]; i++) {
QObject *obj = qdict_get(args, keys[i]);
if (!obj) {
- qemu_error_new(QERR_MISSING_PARAMETER, name);
+ qerror_report(QERR_MISSING_PARAMETER, name);
return -1;
}
if (qobject_type(obj) != QTYPE_QINT) {
- qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "int");
+ qerror_report(QERR_INVALID_PARAMETER_TYPE, name, "int");
return -1;
}
}
case 'l':
case 'M':
if (qobject_type(value) != QTYPE_QINT) {
- qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "int");
+ qerror_report(QERR_INVALID_PARAMETER_TYPE, name, "int");
return -1;
}
break;
- case 'b':
+ case 'f':
case 'T':
if (qobject_type(value) != QTYPE_QINT && qobject_type(value) != QTYPE_QFLOAT) {
- qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "number");
+ qerror_report(QERR_INVALID_PARAMETER_TYPE, name, "number");
+ return -1;
+ }
+ break;
+ case 'b':
+ if (qobject_type(value) != QTYPE_QBOOL) {
+ qerror_report(QERR_INVALID_PARAMETER_TYPE, name, "bool");
return -1;
}
break;
case '-':
if (qobject_type(value) != QTYPE_QINT &&
qobject_type(value) != QTYPE_QBOOL) {
- qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "bool");
+ qerror_report(QERR_INVALID_PARAMETER_TYPE, name, "bool");
return -1;
}
if (qobject_type(value) == QTYPE_QBOOL) {
qint_from_int(qbool_get_int(qobject_to_qbool(value))));
}
break;
+ case 'O':
default:
/* impossible */
abort();
cmd_args->type = cmd_args->flag = cmd_args->optional = 0;
}
+static int check_opts(QemuOptsList *opts_list, QDict *args)
+{
+ assert(!opts_list->desc->name);
+ return 0;
+}
+
/*
* This is not trivial, we have to parse Monitor command's argument
* type syntax to be able to check the arguments provided by clients.
int err;
const char *p;
CmdArgs cmd_args;
+ QemuOptsList *opts_list;
if (cmd->args_type == NULL) {
return (qdict_size(args) == 0 ? 0 : -1);
err = 0;
cmd_args_init(&cmd_args);
+ opts_list = NULL;
for (p = cmd->args_type;; p++) {
if (*p == ':') {
if (cmd_args.type == '-') {
cmd_args.flag = *p++;
cmd_args.optional = 1;
+ } else if (cmd_args.type == 'O') {
+ opts_list = qemu_find_opts(qstring_get_str(cmd_args.name));
+ assert(opts_list);
} else if (*p == '?') {
cmd_args.optional = 1;
p++;
}
assert(*p == ',' || *p == '\0');
- err = check_arg(&cmd_args, args);
-
- QDECREF(cmd_args.name);
- cmd_args_init(&cmd_args);
+ if (opts_list) {
+ err = check_opts(opts_list, args);
+ opts_list = NULL;
+ } else {
+ err = check_arg(&cmd_args, args);
+ QDECREF(cmd_args.name);
+ cmd_args_init(&cmd_args);
+ }
if (err < 0) {
break;
const char *cmd_name, *info_item;
args = NULL;
- qemu_errors_to_mon(mon);
obj = json_parser_parse(tokens, NULL);
if (!obj) {
// FIXME: should be triggered in json_parser_parse()
- qemu_error_new(QERR_JSON_PARSING);
+ qerror_report(QERR_JSON_PARSING);
goto err_out;
} else if (qobject_type(obj) != QTYPE_QDICT) {
- qemu_error_new(QERR_QMP_BAD_INPUT_OBJECT, "object");
+ qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "object");
qobject_decref(obj);
goto err_out;
}
obj = qdict_get(input, "execute");
if (!obj) {
- qemu_error_new(QERR_QMP_BAD_INPUT_OBJECT, "execute");
+ qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "execute");
goto err_input;
} else if (qobject_type(obj) != QTYPE_QSTRING) {
- qemu_error_new(QERR_QMP_BAD_INPUT_OBJECT, "string");
+ qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute", "string");
goto err_input;
}
cmd_name = qstring_get_str(qobject_to_qstring(obj));
if (invalid_qmp_mode(mon, cmd_name)) {
- qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
+ qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
goto err_input;
}
* converted into 'query-' commands
*/
if (compare_cmd(cmd_name, "info")) {
- qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
+ qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
goto err_input;
} else if (strstart(cmd_name, "query-", &info_item)) {
cmd = monitor_find_command("info");
} else {
cmd = monitor_find_command(cmd_name);
if (!cmd || !monitor_handler_ported(cmd)) {
- qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
+ qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
goto err_input;
}
}
obj = qdict_get(input, "arguments");
if (!obj) {
args = qdict_new();
+ } else if (qobject_type(obj) != QTYPE_QDICT) {
+ qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "arguments", "object");
+ goto err_input;
} else {
args = qobject_to_qdict(obj);
QINCREF(args);
monitor_protocol_emitter(mon, NULL);
out:
QDECREF(args);
- qemu_errors_to_previous();
}
/**
}
if (monitor_ctrl_mode(mon)) {
- qemu_error_new(QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs));
+ qerror_report(QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs));
return -1;
}
return err;
}
-
-typedef struct QemuErrorSink QemuErrorSink;
-struct QemuErrorSink {
- enum {
- ERR_SINK_FILE,
- ERR_SINK_MONITOR,
- } dest;
- union {
- FILE *fp;
- Monitor *mon;
- };
- QemuErrorSink *previous;
-};
-
-static QemuErrorSink *qemu_error_sink;
-
-void qemu_errors_to_file(FILE *fp)
-{
- QemuErrorSink *sink;
-
- sink = qemu_mallocz(sizeof(*sink));
- sink->dest = ERR_SINK_FILE;
- sink->fp = fp;
- sink->previous = qemu_error_sink;
- qemu_error_sink = sink;
-}
-
-void qemu_errors_to_mon(Monitor *mon)
-{
- QemuErrorSink *sink;
-
- sink = qemu_mallocz(sizeof(*sink));
- sink->dest = ERR_SINK_MONITOR;
- sink->mon = mon;
- sink->previous = qemu_error_sink;
- qemu_error_sink = sink;
-}
-
-void qemu_errors_to_previous(void)
-{
- QemuErrorSink *sink;
-
- assert(qemu_error_sink != NULL);
- sink = qemu_error_sink;
- qemu_error_sink = sink->previous;
- qemu_free(sink);
-}
-
-void qemu_error(const char *fmt, ...)
-{
- va_list args;
-
- assert(qemu_error_sink != NULL);
- switch (qemu_error_sink->dest) {
- case ERR_SINK_FILE:
- va_start(args, fmt);
- vfprintf(qemu_error_sink->fp, fmt, args);
- va_end(args);
- break;
- case ERR_SINK_MONITOR:
- va_start(args, fmt);
- monitor_vprintf(qemu_error_sink->mon, fmt, args);
- va_end(args);
- break;
- }
-}
-
-void qemu_error_internal(const char *file, int linenr, const char *func,
- const char *fmt, ...)
-{
- va_list va;
- QError *qerror;
-
- assert(qemu_error_sink != NULL);
-
- va_start(va, fmt);
- qerror = qerror_from_info(file, linenr, func, fmt, &va);
- va_end(va);
-
- switch (qemu_error_sink->dest) {
- case ERR_SINK_FILE:
- qerror_print(qerror);
- QDECREF(qerror);
- break;
- case ERR_SINK_MONITOR:
- monitor_set_error(qemu_error_sink->mon, qerror);
- break;
- }
-}