aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2010-03-17 09:44:37 -0500
committerAnthony Liguori <aliguori@us.ibm.com>2010-03-17 09:44:37 -0500
commit4a39943bd1fd2ac7e3163f9d9b056394519661f3 (patch)
treeeab01e0258d2344117873952b589bac333bb0ea3
parent7d834c7450245335db0a7055ccdc783ccab21935 (diff)
parent8bc27249f0f62524887ea355a6604722edd276a9 (diff)
Merge remote branch 'markus/qerror' into staging
-rw-r--r--Makefile.target1
-rw-r--r--audio/audio.c4
-rw-r--r--hw/pc.c35
-rw-r--r--hw/pci-hotplug.c14
-rw-r--r--hw/pci.c14
-rw-r--r--hw/qdev-properties.c36
-rw-r--r--hw/qdev.c236
-rw-r--r--hw/qdev.h2
-rw-r--r--hw/scsi-bus.c4
-rw-r--r--hw/scsi-disk.c7
-rw-r--r--hw/scsi-generic.c9
-rw-r--r--hw/usb-bus.c4
-rw-r--r--hw/usb-msd.c4
-rw-r--r--hw/usb-net.c2
-rw-r--r--hw/usb-serial.c9
-rw-r--r--hw/virtio-net.c5
-rw-r--r--hw/virtio-pci.c4
-rw-r--r--hw/virtio-serial-bus.c2
-rw-r--r--monitor.c337
-rw-r--r--monitor.h7
-rw-r--r--net.c32
-rw-r--r--net/dump.c5
-rw-r--r--net/slirp.c28
-rw-r--r--net/socket.c12
-rw-r--r--net/tap-bsd.c7
-rw-r--r--net/tap-linux.c9
-rw-r--r--net/tap-solaris.c4
-rw-r--r--net/tap-win32.c2
-rw-r--r--net/tap.c3
-rw-r--r--qemu-config.c56
-rw-r--r--qemu-config.h3
-rw-r--r--qemu-error.c227
-rw-r--r--qemu-error.h47
-rw-r--r--qemu-monitor.hx7
-rw-r--r--qemu-option.c93
-rw-r--r--qemu-option.h6
-rw-r--r--qemu-tool.c30
-rw-r--r--qerror.c83
-rw-r--r--qerror.h51
-rw-r--r--savevm.c27
-rw-r--r--slirp/misc.c2
-rw-r--r--sysemu.h13
-rw-r--r--usb-linux.c8
-rw-r--r--vl.c44
-rw-r--r--vnc.c5
45 files changed, 1007 insertions, 533 deletions
diff --git a/Makefile.target b/Makefile.target
index ab3c438fa..56c665231 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -172,6 +172,7 @@ endif #CONFIG_BSD_USER
ifdef CONFIG_SOFTMMU
obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.o
+obj-y += qemu-error.o
# virtio has to be here due to weird dependency between PCI and virtio-net.
# need to fix this properly
obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o
diff --git a/audio/audio.c b/audio/audio.c
index 2a20e5be1..dbf0b96f3 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -330,10 +330,10 @@ void AUD_vlog (const char *cap, const char *fmt, va_list ap)
{
if (conf.log_to_monitor) {
if (cap) {
- monitor_printf(cur_mon, "%s: ", cap);
+ monitor_printf(default_mon, "%s: ", cap);
}
- monitor_vprintf(cur_mon, fmt, ap);
+ monitor_vprintf(default_mon, fmt, ap);
}
else {
if (cap) {
diff --git a/hw/pc.c b/hw/pc.c
index e50a48848..2b3063df8 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -230,40 +230,40 @@ static int boot_device2nibble(char boot_device)
return 0;
}
-/* copy/pasted from cmos_init, should be made a general function
- and used there as well */
-static int pc_boot_set(void *opaque, const char *boot_device)
+static int set_boot_dev(RTCState *s, const char *boot_device, int fd_bootchk)
{
- Monitor *mon = cur_mon;
#define PC_MAX_BOOT_DEVICES 3
- RTCState *s = (RTCState *)opaque;
int nbds, bds[3] = { 0, };
int i;
nbds = strlen(boot_device);
if (nbds > PC_MAX_BOOT_DEVICES) {
- monitor_printf(mon, "Too many boot devices for PC\n");
+ error_report("Too many boot devices for PC");
return(1);
}
for (i = 0; i < nbds; i++) {
bds[i] = boot_device2nibble(boot_device[i]);
if (bds[i] == 0) {
- monitor_printf(mon, "Invalid boot device for PC: '%c'\n",
- boot_device[i]);
+ error_report("Invalid boot device for PC: '%c'",
+ boot_device[i]);
return(1);
}
}
rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]);
- rtc_set_memory(s, 0x38, (bds[2] << 4));
+ rtc_set_memory(s, 0x38, (bds[2] << 4) | (fd_bootchk ? 0x0 : 0x1));
return(0);
}
+static int pc_boot_set(void *opaque, const char *boot_device)
+{
+ return set_boot_dev(opaque, boot_device, 0);
+}
+
/* hd_table must contain 4 block drivers */
static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
const char *boot_device, DriveInfo **hd_table)
{
RTCState *s = rtc_state;
- int nbds, bds[3] = { 0, };
int val;
int fd0, fd1, nb;
int i;
@@ -302,22 +302,9 @@ static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
rtc_set_memory(s, 0x5f, smp_cpus - 1);
/* set boot devices, and disable floppy signature check if requested */
-#define PC_MAX_BOOT_DEVICES 3
- nbds = strlen(boot_device);
- if (nbds > PC_MAX_BOOT_DEVICES) {
- fprintf(stderr, "Too many boot devices for PC\n");
+ if (set_boot_dev(s, boot_device, fd_bootchk)) {
exit(1);
}
- for (i = 0; i < nbds; i++) {
- bds[i] = boot_device2nibble(boot_device[i]);
- if (bds[i] == 0) {
- fprintf(stderr, "Invalid boot device for PC: '%c'\n",
- boot_device[i]);
- exit(1);
- }
- }
- rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]);
- rtc_set_memory(s, 0x38, (bds[2] << 4) | (fd_bootchk ? 0x0 : 0x1));
/* floppy type */
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index bd82c6aab..eb3701bc8 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -54,7 +54,7 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
return NULL;
}
- opts = qemu_opts_parse(&qemu_net_opts, opts_str ? opts_str : "", NULL);
+ opts = qemu_opts_parse(&qemu_net_opts, opts_str ? opts_str : "", 0);
if (!opts) {
monitor_printf(mon, "parsing network options '%s' failed\n",
opts_str ? opts_str : "");
@@ -73,14 +73,15 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
return pci_nic_init(&nd_table[ret], "rtl8139", devaddr);
}
-static int scsi_hot_add(DeviceState *adapter, DriveInfo *dinfo, int printinfo)
+static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
+ DriveInfo *dinfo, int printinfo)
{
SCSIBus *scsibus;
SCSIDevice *scsidev;
scsibus = DO_UPCAST(SCSIBus, qbus, QLIST_FIRST(&adapter->child_bus));
if (!scsibus || strcmp(scsibus->qbus.info->name, "SCSI") != 0) {
- qemu_error("Device is not a SCSI adapter\n");
+ error_report("Device is not a SCSI adapter");
return -1;
}
@@ -97,7 +98,8 @@ static int scsi_hot_add(DeviceState *adapter, DriveInfo *dinfo, int printinfo)
dinfo->unit = scsidev->id;
if (printinfo)
- qemu_error("OK bus %d, unit %d\n", scsibus->busnr, scsidev->id);
+ monitor_printf(mon, "OK bus %d, unit %d\n",
+ scsibus->busnr, scsidev->id);
return 0;
}
@@ -131,7 +133,7 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "no pci device with address %s\n", pci_addr);
goto err;
}
- if (scsi_hot_add(&dev->qdev, dinfo, 1) != 0) {
+ if (scsi_hot_add(mon, &dev->qdev, dinfo, 1) != 0) {
goto err;
}
break;
@@ -203,7 +205,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
if (qdev_init(&dev->qdev) < 0)
dev = NULL;
if (dev && dinfo) {
- if (scsi_hot_add(&dev->qdev, dinfo, 0) != 0) {
+ if (scsi_hot_add(mon, &dev->qdev, dinfo, 0) != 0) {
qdev_unplug(&dev->qdev);
dev = NULL;
}
diff --git a/hw/pci.c b/hw/pci.c
index eb2043e50..0dbca173e 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -589,12 +589,12 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
if (!bus->devices[devfn])
goto found;
}
- qemu_error("PCI: no devfn available for %s, all in use\n", name);
+ error_report("PCI: no devfn available for %s, all in use", name);
return NULL;
found: ;
} else if (bus->devices[devfn]) {
- qemu_error("PCI: devfn %d not available for %s, in use by %s\n", devfn,
- name, bus->devices[devfn]->name);
+ error_report("PCI: devfn %d not available for %s, in use by %s",
+ devfn, name, bus->devices[devfn]->name);
return NULL;
}
pci_dev->bus = bus;
@@ -1476,8 +1476,8 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
bus = pci_get_bus_devfn(&devfn, devaddr);
if (!bus) {
- qemu_error("Invalid PCI device address %s for device %s\n",
- devaddr, pci_nic_names[i]);
+ error_report("Invalid PCI device address %s for device %s",
+ devaddr, pci_nic_names[i]);
return NULL;
}
@@ -1768,8 +1768,8 @@ static int pci_add_option_rom(PCIDevice *pdev)
size = get_image_size(path);
if (size < 0) {
- qemu_error("%s: failed to find romfile \"%s\"\n", __FUNCTION__,
- pdev->romfile);
+ error_report("%s: failed to find romfile \"%s\"",
+ __FUNCTION__, pdev->romfile);
return -1;
}
if (size & (size - 1)) {
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 24671aff9..92d679374 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -402,17 +402,11 @@ PropertyInfo qdev_prop_vlan = {
/* --- pointer --- */
-static int print_ptr(DeviceState *dev, Property *prop, char *dest, size_t len)
-{
- void **ptr = qdev_get_prop_ptr(dev, prop);
- return snprintf(dest, len, "<%p>", *ptr);
-}
-
+/* Not a proper property, just for dirty hacks. TODO Remove it! */
PropertyInfo qdev_prop_ptr = {
.name = "ptr",
.type = PROP_TYPE_PTR,
.size = sizeof(void*),
- .print = print_ptr,
};
/* --- mac address --- */
@@ -547,31 +541,31 @@ int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
int ret;
prop = qdev_prop_find(dev, name);
- if (!prop) {
- fprintf(stderr, "property \"%s.%s\" not found\n",
- dev->info->name, name);
- return -1;
- }
- if (!prop->info->parse) {
- fprintf(stderr, "property \"%s.%s\" has no parser\n",
- dev->info->name, name);
+ /*
+ * TODO Properties without a parse method are just for dirty
+ * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
+ * marked for removal. The test !prop->info->parse should be
+ * removed along with it.
+ */
+ if (!prop || !prop->info->parse) {
+ qerror_report(QERR_PROPERTY_NOT_FOUND, dev->info->name, name);
return -1;
}
ret = prop->info->parse(dev, prop, value);
if (ret < 0) {
switch (ret) {
case -EEXIST:
- fprintf(stderr, "property \"%s.%s\": \"%s\" is already in use\n",
- dev->info->name, name, value);
+ qerror_report(QERR_PROPERTY_VALUE_IN_USE,
+ dev->info->name, name, value);
break;
default:
case -EINVAL:
- fprintf(stderr, "property \"%s.%s\": failed to parse \"%s\"\n",
- dev->info->name, name, value);
+ qerror_report(QERR_PROPERTY_VALUE_BAD,
+ dev->info->name, name, value);
break;
case -ENOENT:
- fprintf(stderr, "property \"%s.%s\": could not find \"%s\"\n",
- dev->info->name, name, value);
+ qerror_report(QERR_PROPERTY_VALUE_NOT_FOUND,
+ dev->info->name, name, value);
break;
}
return -1;
diff --git a/hw/qdev.c b/hw/qdev.c
index b63489006..17a46a7bb 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -29,7 +29,6 @@
#include "qdev.h"
#include "sysemu.h"
#include "monitor.h"
-#include "qerror.h"
static int qdev_hotplug = 0;
@@ -78,13 +77,32 @@ static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
return NULL;
}
+static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
+{
+ DeviceState *dev;
+
+ assert(bus->info == info->bus_info);
+ dev = qemu_mallocz(info->size);
+ dev->info = info;
+ dev->parent_bus = bus;
+ qdev_prop_set_defaults(dev, dev->info->props);
+ qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
+ qdev_prop_set_globals(dev);
+ QLIST_INSERT_HEAD(&bus->children, dev, sibling);
+ if (qdev_hotplug) {
+ assert(bus->allow_hotplug);
+ dev->hotplugged = 1;
+ }
+ dev->state = DEV_STATE_CREATED;
+ return dev;
+}
+
/* Create a new device. This only initializes the device state structure
and allows properties to be set. qdev_init should be called to
initialize the actual device emulation. */
DeviceState *qdev_create(BusState *bus, const char *name)
{
DeviceInfo *info;
- DeviceState *dev;
if (!bus) {
if (!main_system_bus) {
@@ -98,42 +116,23 @@ DeviceState *qdev_create(BusState *bus, const char *name)
hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
}
- dev = qemu_mallocz(info->size);
- dev->info = info;
- dev->parent_bus = bus;
- qdev_prop_set_defaults(dev, dev->info->props);
- qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
- qdev_prop_set_globals(dev);
- QLIST_INSERT_HEAD(&bus->children, dev, sibling);
- if (qdev_hotplug) {
- assert(bus->allow_hotplug);
- dev->hotplugged = 1;
- }
- dev->state = DEV_STATE_CREATED;
- return dev;
+ return qdev_create_from_info(bus, info);
}
-static int qdev_print_devinfo(DeviceInfo *info, char *dest, int len)
+static void qdev_print_devinfo(DeviceInfo *info)
{
- int pos = 0;
- int ret;
-
- ret = snprintf(dest+pos, len-pos, "name \"%s\", bus %s",
- info->name, info->bus_info->name);
- pos += MIN(len-pos,ret);
+ error_printf("name \"%s\", bus %s",
+ info->name, info->bus_info->name);
if (info->alias) {
- ret = snprintf(dest+pos, len-pos, ", alias \"%s\"", info->alias);
- pos += MIN(len-pos,ret);
+ error_printf(", alias \"%s\"", info->alias);
}
if (info->desc) {
- ret = snprintf(dest+pos, len-pos, ", desc \"%s\"", info->desc);
- pos += MIN(len-pos,ret);
+ error_printf(", desc \"%s\"", info->desc);
}
if (info->no_user) {
- ret = snprintf(dest+pos, len-pos, ", no-user");
- pos += MIN(len-pos,ret);
+ error_printf(", no-user");
}
- return pos;
+ error_printf("\n");
}
static int set_property(const char *name, const char *value, void *opaque)
@@ -146,8 +145,6 @@ static int set_property(const char *name, const char *value, void *opaque)
return 0;
if (qdev_prop_parse(dev, name, value) == -1) {
- qemu_error("can't set property \"%s\" to \"%s\" for \"%s\"\n",
- name, value, dev->info->name);
return -1;
}
return 0;
@@ -157,14 +154,15 @@ int qdev_device_help(QemuOpts *opts)
{
const char *driver;
DeviceInfo *info;
- char msg[256];
Property *prop;
driver = qemu_opt_get(opts, "driver");
if (driver && !strcmp(driver, "?")) {
for (info = device_info_list; info != NULL; info = info->next) {
- qdev_print_devinfo(info, msg, sizeof(msg));
- qemu_error("%s\n", msg);
+ if (info->no_user) {
+ continue; /* not available, don't show */
+ }
+ qdev_print_devinfo(info);
}
return 1;
}
@@ -179,7 +177,16 @@ int qdev_device_help(QemuOpts *opts)
}
for (prop = info->props; prop && prop->name; prop++) {
- qemu_error("%s.%s=%s\n", info->name, prop->name, prop->info->name);
+ /*
+ * TODO Properties without a parser are just for dirty hacks.
+ * qdev_prop_ptr is the only such PropertyInfo. It's marked
+ * for removal. This conditional should be removed along with
+ * it.
+ */
+ if (!prop->info->parse) {
+ continue; /* no way to set it, don't show */
+ }
+ error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
}
return 1;
}
@@ -193,19 +200,15 @@ DeviceState *qdev_device_add(QemuOpts *opts)
driver = qemu_opt_get(opts, "driver");
if (!driver) {
- qemu_error("-device: no driver specified\n");
+ qerror_report(QERR_MISSING_PARAMETER, "driver");
return NULL;
}
/* find driver */
info = qdev_find_info(NULL, driver);
- if (!info) {
- qemu_error_new(QERR_DEVICE_NOT_FOUND, driver);
- return NULL;
- }
- if (info->no_user) {
- qemu_error("device \"%s\" can't be added via command line\n",
- info->name);
+ if (!info || info->no_user) {
+ qerror_report(QERR_INVALID_PARAMETER, "driver");
+ error_printf_unless_qmp("Try with argument '?' for a list.\n");
return NULL;
}
@@ -213,22 +216,29 @@ DeviceState *qdev_device_add(QemuOpts *opts)
path = qemu_opt_get(opts, "bus");
if (path != NULL) {
bus = qbus_find(path);
+ if (!bus) {
+ return NULL;
+ }
+ if (bus->info != info->bus_info) {
+ qerror_report(QERR_BAD_BUS_FOR_DEVICE,
+ driver, bus->info->name);
+ return NULL;
+ }
} else {
bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
- }
- if (!bus) {
- qemu_error("Did not find %s bus for %s\n",
- path ? path : info->bus_info->name, info->name);
- return NULL;
+ if (!bus) {
+ qerror_report(QERR_NO_BUS_FOR_DEVICE,
+ info->name, info->bus_info->name);
+ return NULL;
+ }
}
if (qdev_hotplug && !bus->allow_hotplug) {
- qemu_error("Bus %s does not support hotplugging\n",
- bus->name);
+ qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
return NULL;
}
/* create device, set properties */
- qdev = qdev_create(bus, driver);
+ qdev = qdev_create_from_info(bus, info);
id = qemu_opts_id(opts);
if (id) {
qdev->id = id;
@@ -238,7 +248,7 @@ DeviceState *qdev_device_add(QemuOpts *opts)
return NULL;
}
if (qdev_init(qdev) < 0) {
- qemu_error("Error initializing device %s\n", driver);
+ qerror_report(QERR_DEVICE_INIT_FAILED, driver);
return NULL;
}
qdev->opts = opts;
@@ -277,8 +287,8 @@ int qdev_init(DeviceState *dev)
int qdev_unplug(DeviceState *dev)
{
if (!dev->parent_bus->allow_hotplug) {
- qemu_error("Bus %s does not support hotplugging\n",
- dev->parent_bus->name);
+ error_report("Bus %s does not support hotplugging",
+ dev->parent_bus->name);
return -1;
}
assert(dev->info->unplug != NULL);
@@ -465,35 +475,33 @@ static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
return NULL;
}
-static void qbus_list_bus(DeviceState *dev, char *dest, int len)
+static void qbus_list_bus(DeviceState *dev)
{
BusState *child;
const char *sep = " ";
- int pos = 0;
- pos += snprintf(dest+pos, len-pos,"child busses at \"%s\":",
- dev->id ? dev->id : dev->info->name);
+ error_printf("child busses at \"%s\":",
+ dev->id ? dev->id : dev->info->name);
QLIST_FOREACH(child, &dev->child_bus, sibling) {
- pos += snprintf(dest+pos, len-pos, "%s\"%s\"", sep, child->name);
+ error_printf("%s\"%s\"", sep, child->name);
sep = ", ";
}
+ error_printf("\n");
}
-static void qbus_list_dev(BusState *bus, char *dest, int len)
+static void qbus_list_dev(BusState *bus)
{
DeviceState *dev;
const char *sep = " ";
- int pos = 0;
- pos += snprintf(dest+pos, len-pos, "devices at \"%s\":",
- bus->name);
+ error_printf("devices at \"%s\":", bus->name);
QLIST_FOREACH(dev, &bus->children, sibling) {
- pos += snprintf(dest+pos, len-pos, "%s\"%s\"",
- sep, dev->info->name);
+ error_printf("%s\"%s\"", sep, dev->info->name);
if (dev->id)
- pos += snprintf(dest+pos, len-pos, "/\"%s\"", dev->id);
+ error_printf("/\"%s\"", dev->id);
sep = ", ";
}
+ error_printf("\n");
}
static BusState *qbus_find_bus(DeviceState *dev, char *elem)
@@ -540,7 +548,7 @@ static BusState *qbus_find(const char *path)
{
DeviceState *dev;
BusState *bus;
- char elem[128], msg[256];
+ char elem[128];
int pos, len;
/* find start element */
@@ -549,62 +557,75 @@ static BusState *qbus_find(const char *path)
pos = 0;
} else {
if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
- qemu_error("path parse error (\"%s\")\n", path);
- return NULL;
+ assert(!path[0]);
+ elem[0] = len = 0;
}
bus = qbus_find_recursive(main_system_bus, elem, NULL);
if (!bus) {
- qemu_error("bus \"%s\" not found\n", elem);
+ qerror_report(QERR_BUS_NOT_FOUND, elem);
return NULL;
}
pos = len;
}
for (;;) {
+ assert(path[pos] == '/' || !path[pos]);
+ while (path[pos] == '/') {
+ pos++;
+ }
if (path[pos] == '\0') {
- /* we are done */
return bus;
}
/* find device */
- if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
- qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
- return NULL;
+ if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
+ assert(0);
+ elem[0] = len = 0;
}
pos += len;
dev = qbus_find_dev(bus, elem);
if (!dev) {
- qbus_list_dev(bus, msg, sizeof(msg));
- qemu_error("device \"%s\" not found\n%s\n", elem, msg);
+ qerror_report(QERR_DEVICE_NOT_FOUND, elem);
+ if (!monitor_cur_is_qmp()) {
+ qbus_list_dev(bus);
+ }
return NULL;
}
+
+ assert(path[pos] == '/' || !path[pos]);
+ while (path[pos] == '/') {
+ pos++;
+ }
if (path[pos] == '\0') {
/* last specified element is a device. If it has exactly
* one child bus accept it nevertheless */
switch (dev->num_child_bus) {
case 0:
- qemu_error("device has no child bus (%s)\n", path);
+ qerror_report(QERR_DEVICE_NO_BUS, elem);
return NULL;
case 1:
return QLIST_FIRST(&dev->child_bus);
default:
- qbus_list_bus(dev, msg, sizeof(msg));
- qemu_error("device has multiple child busses (%s)\n%s\n",
- path, msg);
+ qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
+ if (!monitor_cur_is_qmp()) {
+ qbus_list_bus(dev);
+ }
return NULL;
}
}
/* find bus */
- if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
- qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
- return NULL;
+ if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
+ assert(0);
+ elem[0] = len = 0;
}
pos += len;
bus = qbus_find_bus(dev, elem);
if (!bus) {
- qbus_list_bus(dev, msg, sizeof(msg));
- qemu_error("child bus \"%s\" not found\n%s\n", elem, msg);
+ qerror_report(QERR_BUS_NOT_FOUND, elem);
+ if (!monitor_cur_is_qmp()) {
+ qbus_list_bus(dev);
+ }
return NULL;
}
}
@@ -684,6 +705,12 @@ static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
if (!props)
return;
while (props->name) {
+ /*
+ * TODO Properties without a print method are just for dirty
+ * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
+ * marked for removal. The test props->info->print should be
+ * removed along with it.
+ */
if (props->info->print) {
props->info->print(dev, props, buf, sizeof(buf));
qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
@@ -735,25 +762,42 @@ void do_info_qtree(Monitor *mon)
void do_info_qdm(Monitor *mon)
{
DeviceInfo *info;
- char msg[256];
for (info = device_info_list; info != NULL; info = info->next) {
- qdev_print_devinfo(info, msg, sizeof(msg));
- monitor_printf(mon, "%s\n", msg);
+ qdev_print_devinfo(info);
}
}
-void do_device_add(Monitor *mon, const QDict *qdict)
+/**
+ * do_device_add(): Add a device
+ *
+ * Argument qdict contains
+ * - "driver": the name of the new device's driver
+ * - "bus": the device's parent bus (device tree path)
+ * - "id": the device's ID (must be unique)
+ * - device properties
+ *
+ * Example:
+ *
+ * { "driver": "usb-net", "id": "eth1", "netdev": "netdev1" }
+ */
+int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
QemuOpts *opts;
- opts = qemu_opts_parse(&qemu_device_opts,
- qdict_get_str(qdict, "config"), "driver");
- if (opts) {
- if (qdev_device_help(opts) || qdev_device_add(opts) == NULL) {
- qemu_opts_del(opts);
- }
+ opts = qemu_opts_from_qdict(&qemu_device_opts, qdict);
+ if (!opts) {
+ return -1;
+ }
+ if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
+ qemu_opts_del(opts);
+ return 0;
+ }
+ if (!qdev_device_add(opts)) {
+ qemu_opts_del(opts);
+ return -1;
}
+ return 0;
}
void do_device_del(Monitor *mon, const QDict *qdict)
@@ -763,7 +807,7 @@ void do_device_del(Monitor *mon, const QDict *qdict)
dev = qdev_find_recursive(main_system_bus, id);
if (NULL == dev) {
- qemu_error("Device '%s' not found\n", id);
+ error_report("Device '%s' not found", id);
return;
}
qdev_unplug(dev);
diff --git a/hw/qdev.h b/hw/qdev.h
index adfcf795c..9475705b7 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -175,7 +175,7 @@ void qbus_free(BusState *bus);
void do_info_qtree(Monitor *mon);
void do_info_qdm(Monitor *mon);
-void do_device_add(Monitor *mon, const QDict *qdict);
+int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
void do_device_del(Monitor *mon, const QDict *qdict);
/*** qdev-properties.c ***/
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index a2f9cc1cc..383240bc0 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -1,5 +1,5 @@
#include "hw.h"
-#include "sysemu.h"
+#include "qemu-error.h"
#include "scsi.h"
#include "scsi-defs.h"
#include "block.h"
@@ -41,7 +41,7 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
}
}
if (dev->id >= bus->ndev) {
- qemu_error("bad scsi device id: %d\n", dev->id);
+ error_report("bad scsi device id: %d", dev->id);
goto err;
}
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 8f7ffc143..da56d2bc1 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -19,8 +19,6 @@
* the host adapter emulator.
*/
-#include <qemu-common.h>
-#include <sysemu.h>
//#define DEBUG_SCSI
#ifdef DEBUG_SCSI
@@ -34,6 +32,7 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
#include "qemu-common.h"
+#include "qemu-error.h"
#include "block.h"
#include "scsi.h"
#include "scsi-defs.h"
@@ -1026,13 +1025,13 @@ static int scsi_disk_initfn(SCSIDevice *dev)
uint64_t nb_sectors;
if (!s->qdev.conf.dinfo || !s->qdev.conf.dinfo->bdrv) {
- qemu_error("scsi-disk: drive property not set\n");
+ error_report("scsi-disk: drive property not set");
return -1;
}
s->bs = s->qdev.conf.dinfo->bdrv;
if (bdrv_is_sg(s->bs)) {
- qemu_error("scsi-disk: unwanted /dev/sg*\n");
+ error_report("scsi-disk: unwanted /dev/sg*");
return -1;
}
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index de778efa3..c9aa853cc 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -12,6 +12,7 @@
*/
#include "qemu-common.h"
+#include "qemu-error.h"
#include "block.h"
#include "scsi.h"
@@ -463,27 +464,27 @@ static int scsi_generic_initfn(SCSIDevice *dev)
struct sg_scsi_id scsiid;
if (!s->qdev.conf.dinfo || !s->qdev.conf.dinfo->bdrv) {
- qemu_error("scsi-generic: drive property not set\n");
+ error_report("scsi-generic: drive property not set");
return -1;
}
s->bs = s->qdev.conf.dinfo->bdrv;
/* check we are really using a /dev/sg* file */
if (!bdrv_is_sg(s->bs)) {
- qemu_error("scsi-generic: not /dev/sg*\n");
+ error_report("scsi-generic: not /dev/sg*");
return -1;
}
/* check we are using a driver managing SG_IO (version 3 and after */
if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
sg_version < 30000) {
- qemu_error("scsi-generic: scsi generic interface too old\n");
+ error_report("scsi-generic: scsi generic interface too old");
return -1;
}
/* get LUN of the /dev/sg? */
if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
- qemu_error("scsi-generic: SG_GET_SCSI_ID ioctl failed\n");
+ error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
return -1;
}
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 7c823147a..e2d87f2d1 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -291,14 +291,14 @@ USBDevice *usbdevice_create(const char *cmdline)
if (info == NULL) {
#if 0
/* no error because some drivers are not converted (yet) */
- qemu_error("usbdevice %s not found\n", driver);
+ error_report("usbdevice %s not found", driver);
#endif
return NULL;
}
if (!usb->usbdevice_init) {
if (params) {
- qemu_error("usbdevice %s accepts no params\n", driver);
+ error_report("usbdevice %s accepts no params", driver);
return NULL;
}
return usb_create_simple(bus, usb->qdev.name);
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 1a11bc557..e90a47e0e 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -524,7 +524,7 @@ static int usb_msd_initfn(USBDevice *dev)
MSDState *s = DO_UPCAST(MSDState, dev, dev);
if (!s->conf.dinfo || !s->conf.dinfo->bdrv) {
- qemu_error("usb-msd: drive property not set\n");
+ error_report("usb-msd: drive property not set");
return -1;
}
@@ -535,7 +535,7 @@ static int usb_msd_initfn(USBDevice *dev)
usb_msd_handle_reset(dev);
if (bdrv_key_required(s->conf.dinfo->bdrv)) {
- if (s->dev.qdev.hotplugged) {
+ if (cur_mon) {
monitor_read_bdrv_key_start(cur_mon, s->conf.dinfo->bdrv,
usb_msd_password_cb, s);
s->dev.auto_attach = 0;
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 6875f112f..4c17435c8 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1478,7 +1478,7 @@ static USBDevice *usb_net_init(const char *cmdline)
QemuOpts *opts;
int idx;
- opts = qemu_opts_parse(&qemu_net_opts, cmdline, NULL);
+ opts = qemu_opts_parse(&qemu_net_opts, cmdline, 0);
if (!opts) {
return NULL;
}
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index 1410b11b2..69f0e44f1 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -9,6 +9,7 @@
*/
#include "qemu-common.h"
+#include "qemu-error.h"
#include "usb.h"
#include "qemu-char.h"
@@ -564,26 +565,26 @@ static USBDevice *usb_serial_init(const char *filename)
if (strstart(filename, "vendorid=", &p)) {
vendorid = strtol(p, &e, 16);
if (e == p || (*e && *e != ',' && *e != ':')) {
- qemu_error("bogus vendor ID %s\n", p);
+ error_report("bogus vendor ID %s", p);
return NULL;
}
filename = e;
} else if (strstart(filename, "productid=", &p)) {
productid = strtol(p, &e, 16);
if (e == p || (*e && *e != ',' && *e != ':')) {
- qemu_error("bogus product ID %s\n", p);
+ error_report("bogus product ID %s", p);
return NULL;
}
filename = e;
} else {
- qemu_error("unrecognized serial USB option %s\n", filename);
+ error_report("unrecognized serial USB option %s", filename);
return NULL;
}
while(*filename == ',')
filename++;
}
if (!*filename) {
- qemu_error("character device specification needed\n");
+ error_report("character device specification needed");
return NULL;
}
filename++;
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 5c0093e87..be33c68bb 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -15,6 +15,7 @@
#include "net.h"
#include "net/checksum.h"
#include "net/tap.h"
+#include "qemu-error.h"
#include "qemu-timer.h"
#include "virtio-net.h"
@@ -764,7 +765,7 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
if (version_id >= 7) {
if (qemu_get_be32(f) && !peer_has_vnet_hdr(n)) {
- qemu_error("virtio-net: saved image requires vnet_hdr=on\n");
+ error_report("virtio-net: saved image requires vnet_hdr=on");
return -1;
}
@@ -793,7 +794,7 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
if (version_id >= 11) {
if (qemu_get_byte(f) && !peer_has_ufo(n)) {
- qemu_error("virtio-net: saved image requires TUN_F_UFO support\n");
+ error_report("virtio-net: saved image requires TUN_F_UFO support");
return -1;
}
}
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 799f664d8..6eb19cdf8 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -19,7 +19,7 @@
#include "virtio-blk.h"
#include "virtio-net.h"
#include "pci.h"
-#include "sysemu.h"
+#include "qemu-error.h"
#include "msix.h"
#include "net.h"
#include "block_int.h"
@@ -459,7 +459,7 @@ static int virtio_blk_init_pci(PCIDevice *pci_dev)
proxy->class_code = PCI_CLASS_STORAGE_SCSI;
if (!proxy->block.dinfo) {
- qemu_error("virtio-blk-pci: drive property not set\n");
+ error_report("virtio-blk-pci: drive property not set");
return -1;
}
vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block);
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index d0e021932..17c1ec1d0 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -485,7 +485,7 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
plugging_port0 = port->is_console && !find_port_by_id(port->vser, 0);
if (port->vser->config.nr_ports == bus->max_nr_ports && !plugging_port0) {
- qemu_error("virtio-serial-bus: Maximum device limit reached\n");
+ error_report("virtio-serial-bus: Maximum device limit reached");
return -1;
}
dev->info = info;
diff --git a/monitor.c b/monitor.c
index 672ae474b..f0ec84d52 100644
--- a/monitor.c
+++ b/monitor.c
@@ -67,6 +67,11 @@
* '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
@@ -177,7 +182,8 @@ static QLIST_HEAD(mon_list, Monitor) mon_list;
static const mon_cmd_t mon_cmds[];
static const mon_cmd_t info_cmds[];
-Monitor *cur_mon = NULL;
+Monitor *cur_mon;
+Monitor *default_mon;
static void monitor_command_cb(Monitor *mon, const char *cmdline,
void *opaque);
@@ -193,6 +199,12 @@ static inline int monitor_ctrl_mode(const Monitor *mon)
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)
@@ -207,7 +219,7 @@ static int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
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);
@@ -606,7 +618,7 @@ static int do_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
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;
@@ -638,7 +650,7 @@ static int do_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
} 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);
@@ -960,7 +972,7 @@ static int do_cpu_set(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
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, "index");
return -1;
}
return 0;
@@ -1013,12 +1025,12 @@ 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,
+ qerror_report(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));
+ qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
return -1;
}
}
@@ -1035,7 +1047,7 @@ static int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
bs = bdrv_find(filename);
if (!bs) {
- qemu_error_new(QERR_DEVICE_NOT_FOUND, filename);
+ qerror_report(QERR_DEVICE_NOT_FOUND, filename);
return -1;
}
return eject_device(mon, bs, force);
@@ -1048,12 +1060,12 @@ static int do_block_set_passwd(Monitor *mon, const QDict *qdict,
bs = bdrv_find(qdict_get_str(qdict, "device"));
if (!bs) {
- qemu_error_new(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
+ qerror_report(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);
+ qerror_report(QERR_INVALID_PASSWORD);
return -1;
}
@@ -1068,13 +1080,13 @@ static int do_change_block(Monitor *mon, const char *device,
bs = bdrv_find(device);
if (!bs) {
- qemu_error_new(QERR_DEVICE_NOT_FOUND, device);
+ qerror_report(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);
+ qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt);
return -1;
}
}
@@ -1090,7 +1102,7 @@ static int do_change_block(Monitor *mon, const char *device,
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;
}
@@ -1118,7 +1130,7 @@ static int do_change_vnc(Monitor *mon, const char *target, const char *arg)
}
} 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;
}
}
@@ -1490,7 +1502,7 @@ static int do_memory_save(Monitor *mon, const QDict *qdict, QObject **ret_data)
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) {
@@ -1526,7 +1538,7 @@ static int do_physical_memory_save(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) {
@@ -2300,13 +2312,13 @@ 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");
+ qerror_report(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");
+ qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon");
return -1;
}
@@ -2322,13 +2334,13 @@ static int do_balloon(Monitor *mon, const QDict *params,
int ret;
if (kvm_enabled() && !kvm_has_sync_mmu()) {
- qemu_error_new(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
+ qerror_report(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");
+ qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon");
return -1;
}
@@ -2469,21 +2481,21 @@ static int do_getfd(Monitor *mon, const QDict *qdict, QObject **ret_data)
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");
+ qerror_report(QERR_INVALID_PARAMETER, "fdname");
return -1;
}
fd = dup(fd);
if (fd == -1) {
if (errno == EMFILE)
- qemu_error_new(QERR_TOO_MANY_FILES);
+ qerror_report(QERR_TOO_MANY_FILES);
else
- qemu_error_new(QERR_UNDEFINED_ERROR);
+ qerror_report(QERR_UNDEFINED_ERROR);
return -1;
}
@@ -2522,7 +2534,7 @@ static int do_closefd(Monitor *mon, const QDict *qdict, QObject **ret_data)
return 0;
}
- qemu_error_new(QERR_FD_NOT_FOUND, fdname);
+ qerror_report(QERR_FD_NOT_FOUND, fdname);
return -1;
}
@@ -2533,7 +2545,7 @@ static void do_loadvm(Monitor *mon, const QDict *qdict)
vm_stop(0);
- if (load_vmstate(mon, name) >= 0 && saved_vm_running)
+ if (load_vmstate(name) >= 0 && saved_vm_running)
vm_start();
}
@@ -3638,6 +3650,31 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
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;
@@ -3857,11 +3894,16 @@ fail:
return NULL;
}
-static void monitor_print_error(Monitor *mon)
+void monitor_set_error(Monitor *mon, QError *qerror)
{
- qerror_print(mon->error);
- QDECREF(mon->error);
- mon->error = NULL;
+ /* report only the first error */
+ if (!mon->error) {
+ mon->error = qerror;
+ } else {
+ MON_DEBUG("Additional error report at %s:%d\n",
+ qerror->file, qerror->linenr);
+ QDECREF(qerror);
+ }
}
static int is_async_return(const QObject *data)
@@ -3875,45 +3917,49 @@ static int is_async_return(const QObject *data)
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,
@@ -3958,8 +4004,6 @@ static void handle_user_command(Monitor *mon, const char *cmdline)
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)) {
@@ -3968,11 +4012,6 @@ static void handle_user_command(Monitor *mon, const char *cmdline)
cmd->mhandler.cmd(mon, qdict);
}
- if (monitor_has_error(mon))
- monitor_print_error(mon);
-
- qemu_errors_to_previous();
-
out:
QDECREF(qdict);
}
@@ -4209,7 +4248,7 @@ typedef struct CmdArgs {
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;
}
@@ -4242,7 +4281,7 @@ static int check_arg(const CmdArgs *cmd_args, QDict *args)
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;
@@ -4253,11 +4292,11 @@ static int check_arg(const CmdArgs *cmd_args, QDict *args)
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;
}
}
@@ -4267,21 +4306,21 @@ static int check_arg(const CmdArgs *cmd_args, QDict *args)
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 '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 '-':
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) {
@@ -4290,6 +4329,7 @@ static int check_arg(const CmdArgs *cmd_args, QDict *args)
qint_from_int(qbool_get_int(qobject_to_qbool(value))));
}
break;
+ case 'O':
default:
/* impossible */
abort();
@@ -4304,6 +4344,12 @@ static void cmd_args_init(CmdArgs *cmd_args)
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.
@@ -4316,6 +4362,7 @@ static int monitor_check_qmp_args(const mon_cmd_t *cmd, QDict *args)
int err;
const char *p;
CmdArgs cmd_args;
+ QemuOptsList *opts_list;
if (cmd->args_type == NULL) {
return (qdict_size(args) == 0 ? 0 : -1);
@@ -4323,6 +4370,7 @@ static int monitor_check_qmp_args(const mon_cmd_t *cmd, QDict *args)
err = 0;
cmd_args_init(&cmd_args);
+ opts_list = NULL;
for (p = cmd->args_type;; p++) {
if (*p == ':') {
@@ -4331,16 +4379,23 @@ static int monitor_check_qmp_args(const mon_cmd_t *cmd, QDict *args)
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;
@@ -4374,15 +4429,14 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
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;
}
@@ -4394,17 +4448,17 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
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, "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;
}
@@ -4413,7 +4467,7 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
* 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");
@@ -4422,7 +4476,7 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
} 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;
}
}
@@ -4455,7 +4509,6 @@ err_out:
monitor_protocol_emitter(mon, NULL);
out:
QDECREF(args);
- qemu_errors_to_previous();
}
/**
@@ -4624,8 +4677,8 @@ void monitor_init(CharDriverState *chr, int flags)
}
QLIST_INSERT_HEAD(&mon_list, mon, entry);
- if (!cur_mon || (flags & MONITOR_IS_DEFAULT))
- cur_mon = mon;
+ if (!default_mon || (flags & MONITOR_IS_DEFAULT))
+ default_mon = mon;
}
static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
@@ -4656,7 +4709,7 @@ int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
}
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;
}
@@ -4673,99 +4726,3 @@ int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
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:
- /* report only the first error */
- if (!qemu_error_sink->mon->error) {
- qemu_error_sink->mon->error = qerror;
- } else {
- MON_DEBUG("Additional error report at %s:%d\n", qerror->file,
- qerror->linenr);
- QDECREF(qerror);
- }
- break;
- }
-}
diff --git a/monitor.h b/monitor.h
index e5f2d2ba7..bd4ae34d4 100644
--- a/monitor.h
+++ b/monitor.h
@@ -3,10 +3,13 @@
#include "qemu-common.h"
#include "qemu-char.h"
+#include "qemu-error.h"
+#include "qerror.h"
#include "qdict.h"
#include "block.h"
extern Monitor *cur_mon;
+extern Monitor *default_mon;
/* flags for monitor_init */
#define MONITOR_IS_DEFAULT 0x01
@@ -28,6 +31,8 @@ typedef enum MonitorEvent {
QEVENT_MAX,
} MonitorEvent;
+int monitor_cur_is_qmp(void);
+
void monitor_protocol_event(MonitorEvent event, QObject *data);
void monitor_init(CharDriverState *chr, int flags);
@@ -48,4 +53,6 @@ void monitor_flush(Monitor *mon);
typedef void (MonitorCompletion)(void *opaque, QObject *ret_data);
+void monitor_set_error(Monitor *mon, QError *qerror);
+
#endif /* !MONITOR_H */
diff --git a/net.c b/net.c
index e47f72762..1092bdcaa 100644
--- a/net.c
+++ b/net.c
@@ -733,7 +733,7 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models,
return i;
}
- qemu_error("qemu: Unsupported NIC model: %s\n", nd->model);
+ error_report("qemu: Unsupported NIC model: %s", nd->model);
return -1;
}
@@ -744,7 +744,7 @@ int net_handle_fd_param(Monitor *mon, const char *param)
fd = monitor_get_fd(mon, param);
if (fd == -1) {
- qemu_error("No file descriptor named %s found", param);
+ error_report("No file descriptor named %s found", param);
return -1;
}
@@ -765,7 +765,7 @@ static int net_init_nic(QemuOpts *opts,
idx = nic_get_free_idx();
if (idx == -1 || nb_nics >= MAX_NICS) {
- qemu_error("Too Many NICs\n");
+ error_report("Too Many NICs");
return -1;
}
@@ -776,7 +776,7 @@ static int net_init_nic(QemuOpts *opts,
if ((netdev = qemu_opt_get(opts, "netdev"))) {
nd->netdev = qemu_find_netdev(netdev);
if (!nd->netdev) {
- qemu_error("netdev '%s' not found\n", netdev);
+ error_report("netdev '%s' not found", netdev);
return -1;
}
} else {
@@ -802,7 +802,7 @@ static int net_init_nic(QemuOpts *opts,
if (qemu_opt_get(opts, "macaddr") &&
net_parse_macaddr(nd->macaddr, qemu_opt_get(opts, "macaddr")) < 0) {
- qemu_error("invalid syntax for ethernet address\n");
+ error_report("invalid syntax for ethernet address");
return -1;
}
@@ -810,7 +810,7 @@ static int net_init_nic(QemuOpts *opts,
DEV_NVECTORS_UNSPECIFIED);
if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
(nd->nvectors < 0 || nd->nvectors > 0x7ffffff)) {
- qemu_error("invalid # of vectors: %d\n", nd->nvectors);
+ error_report("invalid # of vectors: %d", nd->nvectors);
return -1;
}
@@ -1060,12 +1060,12 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
if (!is_netdev) {
if (!type) {
- qemu_error("No type specified for -net\n");
+ error_report("No type specified for -net");
return -1;
}
} else {
if (!type) {
- qemu_error("No type specified for -netdev\n");
+ error_report("No type specified for -netdev");
return -1;
}
@@ -1077,21 +1077,21 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
strcmp(type, "vde") != 0 &&
#endif
strcmp(type, "socket") != 0) {
- qemu_error("The '%s' network backend type is not valid with -netdev\n",
- type);
+ error_report("The '%s' network backend type is not valid with -netdev",
+ type);
return -1;
}
if (qemu_opt_get(opts, "vlan")) {
- qemu_error("The 'vlan' parameter is not valid with -netdev\n");
+ error_report("The 'vlan' parameter is not valid with -netdev");
return -1;
}
if (qemu_opt_get(opts, "name")) {
- qemu_error("The 'name' parameter is not valid with -netdev\n");
+ error_report("The 'name' parameter is not valid with -netdev");
return -1;
}
if (!qemu_opts_id(opts)) {
- qemu_error("The id= parameter is required with -netdev\n");
+ error_report("The id= parameter is required with -netdev");
return -1;
}
}
@@ -1124,7 +1124,7 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
}
}
- qemu_error("Invalid -net type '%s'\n", type);
+ error_report("Invalid -net type '%s'", type);
return -1;
}
@@ -1159,7 +1159,7 @@ void net_host_device_add(Monitor *mon, const QDict *qdict)
return;
}
- opts = qemu_opts_parse(&qemu_net_opts, opts_str ? opts_str : "", NULL);
+ opts = qemu_opts_parse(&qemu_net_opts, opts_str ? opts_str : "", 0);
if (!opts) {
monitor_printf(mon, "parsing network options '%s' failed\n",
opts_str ? opts_str : "");
@@ -1364,7 +1364,7 @@ int net_client_parse(QemuOptsList *opts_list, const char *optarg)
}
#endif
- if (!qemu_opts_parse(opts_list, optarg, "type")) {
+ if (!qemu_opts_parse(opts_list, optarg, 1)) {
return -1;
}
diff --git a/net/dump.c b/net/dump.c
index d50b4eeac..6db7ecf95 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -25,6 +25,7 @@
#include "dump.h"
#include "qemu-common.h"
#include "sysemu.h"
+#include "qemu-error.h"
#include "qemu-log.h"
typedef struct DumpState {
@@ -107,7 +108,7 @@ static int net_dump_init(VLANState *vlan, const char *device,
fd = open(filename, O_CREAT | O_WRONLY | O_BINARY, 0644);
if (fd < 0) {
- qemu_error("-net dump: can't open %s\n", filename);
+ error_report("-net dump: can't open %s", filename);
return -1;
}
@@ -120,7 +121,7 @@ static int net_dump_init(VLANState *vlan, const char *device,
hdr.linktype = 1;
if (write(fd, &hdr, sizeof(hdr)) < sizeof(hdr)) {
- qemu_error("-net dump write error: %s\n", strerror(errno));
+ error_report("-net dump write error: %s", strerror(errno));
close(fd);
return -1;
}
diff --git a/net/slirp.c b/net/slirp.c
index 7f846ec6f..b41c60a39 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -413,14 +413,14 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str,
if (slirp_add_hostfwd(s->slirp, is_udp, host_addr, host_port, guest_addr,
guest_port) < 0) {
- qemu_error("could not set up host forwarding rule '%s'\n",
- redir_str);
+ error_report("could not set up host forwarding rule '%s'",
+ redir_str);
return -1;
}
return 0;
fail_syntax:
- qemu_error("invalid host forwarding rule '%s'\n", redir_str);
+ error_report("invalid host forwarding rule '%s'", redir_str);
return -1;
}
@@ -473,10 +473,10 @@ static void slirp_smb_cleanup(SlirpState *s)
snprintf(cmd, sizeof(cmd), "rm -rf %s", s->smb_dir);
ret = system(cmd);
if (ret == -1 || !WIFEXITED(ret)) {
- qemu_error("'%s' failed.\n", cmd);
+ error_report("'%s' failed.", cmd);
} else if (WEXITSTATUS(ret)) {
- qemu_error("'%s' failed. Error code: %d\n",
- cmd, WEXITSTATUS(ret));
+ error_report("'%s' failed. Error code: %d",
+ cmd, WEXITSTATUS(ret));
}
s->smb_dir[0] = '\0';
}
@@ -493,7 +493,7 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
snprintf(s->smb_dir, sizeof(s->smb_dir), "/tmp/qemu-smb.%ld-%d",
(long)getpid(), instance++);
if (mkdir(s->smb_dir, 0700) < 0) {
- qemu_error("could not create samba server dir '%s'\n", s->smb_dir);
+ error_report("could not create samba server dir '%s'", s->smb_dir);
return -1;
}
snprintf(smb_conf, sizeof(smb_conf), "%s/%s", s->smb_dir, "smb.conf");
@@ -501,8 +501,8 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
f = fopen(smb_conf, "w");
if (!f) {
slirp_smb_cleanup(s);
- qemu_error("could not create samba server configuration file '%s'\n",
- smb_conf);
+ error_report("could not create samba server configuration file '%s'",
+ smb_conf);
return -1;
}
fprintf(f,
@@ -533,7 +533,7 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
if (slirp_add_exec(s->slirp, 0, smb_cmdline, &vserver_addr, 139) < 0) {
slirp_smb_cleanup(s);
- qemu_error("conflicting/invalid smbserver address\n");
+ error_report("conflicting/invalid smbserver address");
return -1;
}
return 0;
@@ -618,14 +618,14 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
snprintf(buf, sizeof(buf), "guestfwd.tcp:%d", port);
fwd->hd = qemu_chr_open(buf, p, NULL);
if (!fwd->hd) {
- qemu_error("could not open guest forwarding device '%s'\n", buf);
+ error_report("could not open guest forwarding device '%s'", buf);
qemu_free(fwd);
return -1;
}
if (slirp_add_exec(s->slirp, 3, fwd->hd, &server, port) < 0) {
- qemu_error("conflicting/invalid host:port in guest forwarding "
- "rule '%s'\n", config_str);
+ error_report("conflicting/invalid host:port in guest forwarding "
+ "rule '%s'", config_str);
qemu_free(fwd);
return -1;
}
@@ -638,7 +638,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
return 0;
fail_syntax:
- qemu_error("invalid guest forwarding rule '%s'\n", config_str);
+ error_report("invalid guest forwarding rule '%s'", config_str);
return -1;
}
diff --git a/net/socket.c b/net/socket.c
index 442a9c790..1c4e153e3 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -28,9 +28,9 @@
#include "net.h"
#include "qemu-char.h"
#include "qemu-common.h"
+#include "qemu-error.h"
#include "qemu-option.h"
#include "qemu_socket.h"
-#include "sysemu.h"
typedef struct NetSocketState {
VLANClientState nc;
@@ -506,7 +506,7 @@ int net_init_socket(QemuOpts *opts,
if (qemu_opt_get(opts, "listen") ||
qemu_opt_get(opts, "connect") ||
qemu_opt_get(opts, "mcast")) {
- qemu_error("listen=, connect= and mcast= is invalid with fd=\n");
+ error_report("listen=, connect= and mcast= is invalid with fd=");
return -1;
}
@@ -525,7 +525,7 @@ int net_init_socket(QemuOpts *opts,
if (qemu_opt_get(opts, "fd") ||
qemu_opt_get(opts, "connect") ||
qemu_opt_get(opts, "mcast")) {
- qemu_error("fd=, connect= and mcast= is invalid with listen=\n");
+ error_report("fd=, connect= and mcast= is invalid with listen=");
return -1;
}
@@ -540,7 +540,7 @@ int net_init_socket(QemuOpts *opts,
if (qemu_opt_get(opts, "fd") ||
qemu_opt_get(opts, "listen") ||
qemu_opt_get(opts, "mcast")) {
- qemu_error("fd=, listen= and mcast= is invalid with connect=\n");
+ error_report("fd=, listen= and mcast= is invalid with connect=");
return -1;
}
@@ -555,7 +555,7 @@ int net_init_socket(QemuOpts *opts,
if (qemu_opt_get(opts, "fd") ||
qemu_opt_get(opts, "connect") ||
qemu_opt_get(opts, "listen")) {
- qemu_error("fd=, connect= and listen= is invalid with mcast=\n");
+ error_report("fd=, connect= and listen= is invalid with mcast=");
return -1;
}
@@ -565,7 +565,7 @@ int net_init_socket(QemuOpts *opts,
return -1;
}
} else {
- qemu_error("-socket requires fd=, listen=, connect= or mcast=\n");
+ error_report("-socket requires fd=, listen=, connect= or mcast=");
return -1;
}
diff --git a/net/tap-bsd.c b/net/tap-bsd.c
index 815997dc7..e51d06848 100644
--- a/net/tap-bsd.c
+++ b/net/tap-bsd.c
@@ -69,7 +69,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
}
}
if (fd < 0) {
- qemu_error("warning: could not open %s (%s): no virtual network emulation\n", dname, strerror(errno));
+ error_report("warning: could not open %s (%s): no virtual network emulation",
+ dname, strerror(errno));
return -1;
}
#else
@@ -89,8 +90,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
*vnet_hdr = 0;
if (vnet_hdr_required && !*vnet_hdr) {
- qemu_error("vnet_hdr=1 requested, but no kernel "
- "support for IFF_VNET_HDR available");
+ error_report("vnet_hdr=1 requested, but no kernel "
+ "support for IFF_VNET_HDR available");
close(fd);
return -1;
}
diff --git a/net/tap-linux.c b/net/tap-linux.c
index 6af9e824d..03b83012f 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -31,6 +31,7 @@
#include "sysemu.h"
#include "qemu-common.h"
+#include "qemu-error.h"
int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required)
{
@@ -57,8 +58,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
}
if (vnet_hdr_required && !*vnet_hdr) {
- qemu_error("vnet_hdr=1 requested, but no kernel "
- "support for IFF_VNET_HDR available");
+ error_report("vnet_hdr=1 requested, but no kernel "
+ "support for IFF_VNET_HDR available");
close(fd);
return -1;
}
@@ -96,7 +97,7 @@ int tap_set_sndbuf(int fd, QemuOpts *opts)
}
if (ioctl(fd, TUNSETSNDBUF, &sndbuf) == -1 && qemu_opt_get(opts, "sndbuf")) {
- qemu_error("TUNSETSNDBUF ioctl failed: %s\n", strerror(errno));
+ error_report("TUNSETSNDBUF ioctl failed: %s", strerror(errno));
return -1;
}
return 0;
@@ -107,7 +108,7 @@ int tap_probe_vnet_hdr(int fd)
struct ifreq ifr;
if (ioctl(fd, TUNGETIFF, &ifr) != 0) {
- qemu_error("TUNGETIFF ioctl() failed: %s\n", strerror(errno));
+ error_report("TUNGETIFF ioctl() failed: %s", strerror(errno));
return 0;
}
diff --git a/net/tap-solaris.c b/net/tap-solaris.c
index 0b428617b..50d127ad3 100644
--- a/net/tap-solaris.c
+++ b/net/tap-solaris.c
@@ -186,8 +186,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
*vnet_hdr = 0;
if (vnet_hdr_required && !*vnet_hdr) {
- qemu_error("vnet_hdr=1 requested, but no kernel "
- "support for IFF_VNET_HDR available");
+ error_report("vnet_hdr=1 requested, but no kernel "
+ "support for IFF_VNET_HDR available");
close(fd);
return -1;
}
diff --git a/net/tap-win32.c b/net/tap-win32.c
index 8370c803b..a5c2ce9e3 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -706,7 +706,7 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
ifname = qemu_opt_get(opts, "ifname");
if (!ifname) {
- qemu_error("tap: no interface name\n");
+ error_report("tap: no interface name");
return -1;
}
diff --git a/net/tap.c b/net/tap.c
index 7a7320c1a..672b0ee0b 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -38,6 +38,7 @@
#include "sysemu.h"
#include "qemu-char.h"
#include "qemu-common.h"
+#include "qemu-error.h"
#include "net/tap-linux.h"
@@ -393,7 +394,7 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
qemu_opt_get(opts, "script") ||
qemu_opt_get(opts, "downscript") ||
qemu_opt_get(opts, "vnet_hdr")) {
- qemu_error("ifname=, script=, downscript= and vnet_hdr= is invalid with fd=\n");
+ error_report("ifname=, script=, downscript= and vnet_hdr= is invalid with fd=");
return -1;
}
diff --git a/qemu-config.c b/qemu-config.c
index 246fae6f9..150157ca7 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -1,4 +1,5 @@
#include "qemu-common.h"
+#include "qemu-error.h"
#include "qemu-option.h"
#include "qemu-config.h"
#include "sysemu.h"
@@ -85,6 +86,7 @@ QemuOptsList qemu_drive_opts = {
QemuOptsList qemu_chardev_opts = {
.name = "chardev",
+ .implied_opt_name = "backend",
.head = QTAILQ_HEAD_INITIALIZER(qemu_chardev_opts.head),
.desc = {
{
@@ -151,6 +153,7 @@ QemuOptsList qemu_chardev_opts = {
QemuOptsList qemu_device_opts = {
.name = "device",
+ .implied_opt_name = "driver",
.head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
.desc = {
/*
@@ -164,6 +167,7 @@ QemuOptsList qemu_device_opts = {
QemuOptsList qemu_netdev_opts = {
.name = "netdev",
+ .implied_opt_name = "type",
.head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head),
.desc = {
/*
@@ -176,6 +180,7 @@ QemuOptsList qemu_netdev_opts = {
QemuOptsList qemu_net_opts = {
.name = "net",
+ .implied_opt_name = "type",
.head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head),
.desc = {
/*
@@ -226,6 +231,7 @@ QemuOptsList qemu_global_opts = {
QemuOptsList qemu_mon_opts = {
.name = "mon",
+ .implied_opt_name = "chardev",
.head = QTAILQ_HEAD_INITIALIZER(qemu_mon_opts.head),
.desc = {
{
@@ -303,7 +309,7 @@ static QemuOptsList *lists[] = {
NULL,
};
-static QemuOptsList *find_list(const char *group)
+QemuOptsList *qemu_find_opts(const char *group)
{
int i;
@@ -312,7 +318,7 @@ static QemuOptsList *find_list(const char *group)
break;
}
if (lists[i] == NULL) {
- qemu_error("there is no option group \"%s\"\n", group);
+ error_report("there is no option group \"%s\"", group);
}
return lists[i];
}
@@ -326,19 +332,19 @@ int qemu_set_option(const char *str)
rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
if (rc < 3 || str[offset] != '=') {
- qemu_error("can't parse: \"%s\"\n", str);
+ error_report("can't parse: \"%s\"", str);
return -1;
}
- list = find_list(group);
+ list = qemu_find_opts(group);
if (list == NULL) {
return -1;
}
opts = qemu_opts_find(list, id);
if (!opts) {
- qemu_error("there is no %s \"%s\" defined\n",
- list->name, id);
+ error_report("there is no %s \"%s\" defined",
+ list->name, id);
return -1;
}
@@ -356,7 +362,7 @@ int qemu_global_option(const char *str)
rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
if (rc < 2 || str[offset] != '=') {
- qemu_error("can't parse: \"%s\"\n", str);
+ error_report("can't parse: \"%s\"", str);
return -1;
}
@@ -424,13 +430,17 @@ void qemu_config_write(FILE *fp)
}
}
-int qemu_config_parse(FILE *fp)
+int qemu_config_parse(FILE *fp, const char *fname)
{
char line[1024], group[64], id[64], arg[64], value[1024];
+ Location loc;
QemuOptsList *list = NULL;
QemuOpts *opts = NULL;
+ int res = -1, lno = 0;
+ loc_push_none(&loc);
while (fgets(line, sizeof(line), fp) != NULL) {
+ loc_set_file(fname, ++lno);
if (line[0] == '\n') {
/* skip empty lines */
continue;
@@ -441,35 +451,41 @@ int qemu_config_parse(FILE *fp)
}
if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
/* group with id */
- list = find_list(group);
+ list = qemu_find_opts(group);
if (list == NULL)
- return -1;
+ goto out;
opts = qemu_opts_create(list, id, 1);
continue;
}
if (sscanf(line, "[%63[^]]]", group) == 1) {
/* group without id */
- list = find_list(group);
+ list = qemu_find_opts(group);
if (list == NULL)
- return -1;
+ goto out;
opts = qemu_opts_create(list, NULL, 0);
continue;
}
if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
/* arg = value */
if (opts == NULL) {
- fprintf(stderr, "no group defined\n");
- return -1;
+ error_report("no group defined");
+ goto out;
}
if (qemu_opt_set(opts, arg, value) != 0) {
- fprintf(stderr, "failed to set \"%s\" for %s\n",
- arg, group);
- return -1;
+ error_report("failed to set \"%s\" for %s", arg, group);
+ goto out;
}
continue;
}
- fprintf(stderr, "parse error: %s\n", line);
- return -1;
+ error_report("parse error");
+ goto out;
}
- return 0;
+ if (ferror(fp)) {
+ error_report("error reading file");
+ goto out;
+ }
+ res = 0;
+out:
+ loc_pop(&loc);
+ return res;
}
diff --git a/qemu-config.h b/qemu-config.h
index b335c4292..f217c589f 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -11,11 +11,12 @@ extern QemuOptsList qemu_global_opts;
extern QemuOptsList qemu_mon_opts;
extern QemuOptsList qemu_cpudef_opts;
+QemuOptsList *qemu_find_opts(const char *group);
int qemu_set_option(const char *str);
int qemu_global_option(const char *str);
void qemu_add_globals(void);
void qemu_config_write(FILE *fp);
-int qemu_config_parse(FILE *fp);
+int qemu_config_parse(FILE *fp, const char *fname);
#endif /* QEMU_CONFIG_H */
diff --git a/qemu-error.c b/qemu-error.c
new file mode 100644
index 000000000..5d5fe3742
--- /dev/null
+++ b/qemu-error.c
@@ -0,0 +1,227 @@
+/*
+ * Error reporting
+ *
+ * Copyright (C) 2010 Red Hat Inc.
+ *
+ * Authors:
+ * Markus Armbruster <armbru@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <stdio.h>
+#include "monitor.h"
+#include "sysemu.h"
+
+/*
+ * Print to current monitor if we have one, else to stderr.
+ * TODO should return int, so callers can calculate width, but that
+ * requires surgery to monitor_vprintf(). Left for another day.
+ */
+void error_vprintf(const char *fmt, va_list ap)
+{
+ if (cur_mon) {
+ monitor_vprintf(cur_mon, fmt, ap);
+ } else {
+ vfprintf(stderr, fmt, ap);
+ }
+}
+
+/*
+ * Print to current monitor if we have one, else to stderr.
+ * TODO just like error_vprintf()
+ */
+void error_printf(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ error_vprintf(fmt, ap);
+ va_end(ap);
+}
+
+void error_printf_unless_qmp(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (!monitor_cur_is_qmp()) {
+ va_start(ap, fmt);
+ error_vprintf(fmt, ap);
+ va_end(ap);
+ }
+}
+
+static Location std_loc = {
+ .kind = LOC_NONE
+};
+static Location *cur_loc = &std_loc;
+
+/*
+ * Push location saved in LOC onto the location stack, return it.
+ * The top of that stack is the current location.
+ * Needs a matching loc_pop().
+ */
+Location *loc_push_restore(Location *loc)
+{
+ assert(!loc->prev);
+ loc->prev = cur_loc;
+ cur_loc = loc;
+ return loc;
+}
+
+/*
+ * Initialize *LOC to "nowhere", push it onto the location stack.
+ * The top of that stack is the current location.
+ * Needs a matching loc_pop().
+ * Return LOC.
+ */
+Location *loc_push_none(Location *loc)
+{
+ loc->kind = LOC_NONE;
+ loc->prev = NULL;
+ return loc_push_restore(loc);
+}
+
+/*
+ * Pop the location stack.
+ * LOC must be the current location, i.e. the top of the stack.
+ */
+Location *loc_pop(Location *loc)
+{
+ assert(cur_loc == loc && loc->prev);
+ cur_loc = loc->prev;
+ loc->prev = NULL;
+ return loc;
+}
+
+/*
+ * Save the current location in LOC, return LOC.
+ */
+Location *loc_save(Location *loc)
+{
+ *loc = *cur_loc;
+ loc->prev = NULL;
+ return loc;
+}
+
+/*
+ * Change the current location to the one saved in LOC.
+ */
+void loc_restore(Location *loc)
+{
+ Location *prev = cur_loc->prev;
+ assert(!loc->prev);
+ *cur_loc = *loc;
+ cur_loc->prev = prev;
+}
+
+/*
+ * Change the current location to "nowhere in particular".
+ */
+void loc_set_none(void)
+{
+ cur_loc->kind = LOC_NONE;
+}
+
+/*
+ * Change the current location to argument ARGV[IDX..IDX+CNT-1].
+ */
+void loc_set_cmdline(char **argv, int idx, int cnt)
+{
+ cur_loc->kind = LOC_CMDLINE;
+ cur_loc->num = cnt;
+ cur_loc->ptr = argv + idx;
+}
+
+/*
+ * Change the current location to file FNAME, line LNO.
+ */
+void loc_set_file(const char *fname, int lno)
+{
+ assert (fname || cur_loc->kind == LOC_FILE);
+ cur_loc->kind = LOC_FILE;
+ cur_loc->num = lno;
+ if (fname) {
+ cur_loc->ptr = fname;
+ }
+}
+
+static const char *progname;
+
+/*
+ * Set the program name for error_print_loc().
+ */
+void error_set_progname(const char *argv0)
+{
+ const char *p = strrchr(argv0, '/');
+ progname = p ? p + 1 : argv0;
+}
+
+/*
+ * Print current location to current monitor if we have one, else to stderr.
+ */
+void error_print_loc(void)
+{
+ const char *sep = "";
+ int i;
+ const char *const *argp;
+
+ if (!cur_mon) {
+ fprintf(stderr, "%s:", progname);
+ sep = " ";
+ }
+ switch (cur_loc->kind) {
+ case LOC_CMDLINE:
+ argp = cur_loc->ptr;
+ for (i = 0; i < cur_loc->num; i++) {
+ error_printf("%s%s", sep, argp[i]);
+ sep = " ";
+ }
+ error_printf(": ");
+ break;
+ case LOC_FILE:
+ error_printf("%s:", (const char *)cur_loc->ptr);
+ if (cur_loc->num) {
+ error_printf("%d:", cur_loc->num);
+ }
+ error_printf(" ");
+ break;
+ default:
+ error_printf(sep);
+ }
+}
+
+/*
+ * Print an error message to current monitor if we have one, else to stderr.
+ * Prepend the current location and append a newline.
+ * It's wrong to call this in a QMP monitor. Use qerror_report() there.
+ */
+void error_report(const char *fmt, ...)
+{
+ va_list ap;
+
+ error_print_loc();
+ va_start(ap, fmt);
+ error_vprintf(fmt, ap);
+ va_end(ap);
+ error_printf("\n");
+}
+
+void qerror_report_internal(const char *file, int linenr, const char *func,
+ const char *fmt, ...)
+{
+ va_list va;
+ QError *qerror;
+
+ va_start(va, fmt);
+ qerror = qerror_from_info(file, linenr, func, fmt, &va);
+ va_end(va);
+
+ if (monitor_cur_is_qmp()) {
+ monitor_set_error(cur_mon, qerror);
+ } else {
+ qerror_print(qerror);
+ QDECREF(qerror);
+ }
+}
diff --git a/qemu-error.h b/qemu-error.h
new file mode 100644
index 000000000..e63c6ab31
--- /dev/null
+++ b/qemu-error.h
@@ -0,0 +1,47 @@
+/*
+ * Error reporting
+ *
+ * Copyright (C) 2010 Red Hat Inc.
+ *
+ * Authors:
+ * Markus Armbruster <armbru@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_ERROR_H
+#define QEMU_ERROR_H
+
+typedef struct Location {
+ /* all members are private to qemu-error.c */
+ enum { LOC_NONE, LOC_CMDLINE, LOC_FILE } kind;
+ int num;
+ const void *ptr;
+ struct Location *prev;
+} Location;
+
+Location *loc_push_restore(Location *loc);
+Location *loc_push_none(Location *loc);
+Location *loc_pop(Location *loc);
+Location *loc_save(Location *loc);
+void loc_restore(Location *loc);
+void loc_set_none(void);
+void loc_set_cmdline(char **argv, int idx, int cnt);
+void loc_set_file(const char *fname, int lno);
+
+void error_vprintf(const char *fmt, va_list ap);
+void error_printf(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
+void error_printf_unless_qmp(const char *fmt, ...)
+ __attribute__ ((format(printf, 1, 2)));
+void error_print_loc(void);
+void error_set_progname(const char *argv0);
+void error_report(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
+void qerror_report_internal(const char *file, int linenr, const char *func,
+ const char *fmt, ...)
+ __attribute__ ((format(printf, 4, 5)));
+
+#define qerror_report(fmt, ...) \
+ qerror_report_internal(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__)
+
+#endif
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 7f9d261cd..5308f364e 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -570,10 +570,11 @@ ETEXI
{
.name = "device_add",
- .args_type = "config:s",
- .params = "device",
+ .args_type = "device:O",
+ .params = "driver[,prop=value][,...]",
.help = "add device, like -device on the command line",
- .mhandler.cmd = do_device_add,
+ .user_print = monitor_user_noop,
+ .mhandler.cmd_new = do_device_add,
},
STEXI
diff --git a/qemu-option.c b/qemu-option.c
index de40bffc7..dc340b8dc 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -27,6 +27,8 @@
#include <string.h>
#include "qemu-common.h"
+#include "qemu-error.h"
+#include "qemu-objects.h"
#include "qemu-option.h"
/*
@@ -483,6 +485,7 @@ struct QemuOpt {
struct QemuOpts {
char *id;
QemuOptsList *list;
+ Location loc;
QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
QTAILQ_ENTRY(QemuOpts) next;
};
@@ -653,6 +656,7 @@ QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exist
opts->id = qemu_strdup(id);
}
opts->list = list;
+ loc_save(&opts->loc);
QTAILQ_INIT(&opts->head);
QTAILQ_INSERT_TAIL(&list->head, opts, next);
return opts;
@@ -749,12 +753,17 @@ int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname
return 0;
}
-QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, const char *firstname)
+QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
+ int permit_abbrev)
{
+ const char *firstname;
char value[1024], *id = NULL;
const char *p;
QemuOpts *opts;
+ assert(!permit_abbrev || list->implied_opt_name);
+ firstname = permit_abbrev ? list->implied_opt_name : NULL;
+
if (strncmp(params, "id=", 3) == 0) {
get_opt_value(value, sizeof(value), params+3);
id = qemu_strdup(value);
@@ -774,6 +783,84 @@ QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, const char *fi
return opts;
}
+static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
+{
+ char buf[32];
+ const char *value;
+ int n;
+
+ if (!strcmp(key, "id")) {
+ return;
+ }
+
+ switch (qobject_type(obj)) {
+ case QTYPE_QSTRING:
+ value = qstring_get_str(qobject_to_qstring(obj));
+ break;
+ case QTYPE_QINT:
+ n = snprintf(buf, sizeof(buf), "%" PRId64,
+ qint_get_int(qobject_to_qint(obj)));
+ assert(n < sizeof(buf));
+ value = buf;
+ break;
+ case QTYPE_QFLOAT:
+ n = snprintf(buf, sizeof(buf), "%.17g",
+ qfloat_get_double(qobject_to_qfloat(obj)));
+ assert(n < sizeof(buf));
+ value = buf;
+ break;
+ case QTYPE_QBOOL:
+ strcpy(buf, qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off");
+ value = buf;
+ break;
+ default:
+ return;
+ }
+ qemu_opt_set(opaque, key, value);
+}
+
+/*
+ * Create QemuOpts from a QDict.
+ * Use value of key "id" as ID if it exists and is a QString.
+ * Only QStrings, QInts, QFloats and QBools are copied. Entries with
+ * other types are silently ignored.
+ */
+QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
+{
+ QemuOpts *opts;
+
+ opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1);
+ if (opts == NULL)
+ return NULL;
+
+ qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
+ return opts;
+}
+
+/*
+ * Convert from QemuOpts to QDict.
+ * The QDict values are of type QString.
+ * TODO We'll want to use types appropriate for opt->desc->type, but
+ * this is enough for now.
+ */
+QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
+{
+ QemuOpt *opt;
+ QObject *val;
+
+ if (!qdict) {
+ qdict = qdict_new();
+ }
+ if (opts->id) {
+ qdict_put(qdict, "id", qstring_from_str(opts->id));
+ }
+ QTAILQ_FOREACH(opt, &opts->head, next) {
+ val = QOBJECT(qstring_from_str(opt->str));
+ qdict_put_obj(qdict, opt->name, val);
+ }
+ return qdict;
+}
+
/* Validate parsed opts against descriptions where no
* descriptions were provided in the QemuOptsList.
*/
@@ -810,13 +897,17 @@ int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
int abort_on_failure)
{
+ Location loc;
QemuOpts *opts;
int rc = 0;
+ loc_push_none(&loc);
QTAILQ_FOREACH(opts, &list->head, next) {
+ loc_restore(&opts->loc);
rc |= func(opts, opaque);
if (abort_on_failure && rc != 0)
break;
}
+ loc_pop(&loc);
return rc;
}
diff --git a/qemu-option.h b/qemu-option.h
index f3f1de755..58136f303 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -28,6 +28,7 @@
#include <stdint.h>
#include "qemu-queue.h"
+#include "qdict.h"
enum QEMUOptionParType {
OPT_FLAG,
@@ -96,6 +97,7 @@ typedef struct QemuOptDesc {
struct QemuOptsList {
const char *name;
+ const char *implied_opt_name;
QTAILQ_HEAD(, QemuOpts) head;
QemuOptDesc desc[];
};
@@ -117,7 +119,9 @@ const char *qemu_opts_id(QemuOpts *opts);
void qemu_opts_del(QemuOpts *opts);
int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc);
int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname);
-QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, const char *firstname);
+QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int permit_abbrev);
+QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict);
+QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict);
typedef int (*qemu_opts_loopfunc)(QemuOpts *opts, void *opaque);
int qemu_opts_print(QemuOpts *opts, void *dummy);
diff --git a/qemu-tool.c b/qemu-tool.c
index 18b48af31..97ca94996 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -13,9 +13,9 @@
#include "qemu-common.h"
#include "monitor.h"
-#include "sysemu.h"
#include "qemu-timer.h"
#include "qemu-log.h"
+#include "qemu-error.h"
#include <sys/time.h>
@@ -33,8 +33,6 @@ void qemu_service_io(void)
{
}
-Monitor *cur_mon;
-
void monitor_printf(Monitor *mon, const char *fmt, ...)
{
}
@@ -106,7 +104,31 @@ int64_t qemu_get_clock(QEMUClock *clock)
return (tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000)) / 1000000;
}
-void qemu_error(const char *fmt, ...)
+Location *loc_push_restore(Location *loc)
+{
+ return loc;
+}
+
+Location *loc_push_none(Location *loc)
+{
+ return loc;
+}
+
+Location *loc_pop(Location *loc)
+{
+ return loc;
+}
+
+Location *loc_save(Location *loc)
+{
+ return loc;
+}
+
+void loc_restore(Location *loc)
+{
+}
+
+void error_report(const char *fmt, ...)
{
va_list args;
diff --git a/qerror.c b/qerror.c
index 2f657f4f7..26eb70472 100644
--- a/qerror.c
+++ b/qerror.c
@@ -12,8 +12,8 @@
#include "qjson.h"
#include "qerror.h"
#include "qstring.h"
-#include "sysemu.h"
#include "qemu-common.h"
+#include "qemu-error.h"
static void qerror_destroy_obj(QObject *obj);
@@ -41,48 +41,68 @@ static const QType qerror_type = {
*/
static const QErrorStringTable qerror_table[] = {
{
+ .error_fmt = QERR_BAD_BUS_FOR_DEVICE,
+ .desc = "Device '%(device)' can't go on a %(bad_bus_type) bus",
+ },
+ {
+ .error_fmt = QERR_BUS_NOT_FOUND,
+ .desc = "Bus '%(bus)' not found",
+ },
+ {
+ .error_fmt = QERR_BUS_NO_HOTPLUG,
+ .desc = "Bus '%(bus)' does not support hotplugging",
+ },
+ {
.error_fmt = QERR_COMMAND_NOT_FOUND,
.desc = "The command %(name) has not been found",
},
{
.error_fmt = QERR_DEVICE_ENCRYPTED,
- .desc = "The %(device) is encrypted",
+ .desc = "Device '%(device)' is encrypted",
+ },
+ {
+ .error_fmt = QERR_DEVICE_INIT_FAILED,
+ .desc = "Device '%(device)' could not be initialized",
},
{
.error_fmt = QERR_DEVICE_LOCKED,
- .desc = "Device %(device) is locked",
+ .desc = "Device '%(device)' is locked",
+ },
+ {
+ .error_fmt = QERR_DEVICE_MULTIPLE_BUSSES,
+ .desc = "Device '%(device)' has multiple child busses",
},
{
.error_fmt = QERR_DEVICE_NOT_ACTIVE,
- .desc = "The %(device) device has not been activated by the guest",
+ .desc = "Device '%(device)' has not been activated by the guest",
},
{
.error_fmt = QERR_DEVICE_NOT_FOUND,
- .desc = "The %(device) device has not been found",
+ .desc = "Device '%(device)' not found",
},
{
.error_fmt = QERR_DEVICE_NOT_REMOVABLE,
- .desc = "Device %(device) is not removable",
+ .desc = "Device '%(device)' is not removable",
+ },
+ {
+ .error_fmt = QERR_DEVICE_NO_BUS,
+ .desc = "Device '%(device)' has no child bus",
},
{
.error_fmt = QERR_FD_NOT_FOUND,
- .desc = "Failed to find file descriptor named %(name)",
+ .desc = "File descriptor named '%(name)' not found",
},
{
.error_fmt = QERR_FD_NOT_SUPPLIED,
.desc = "No file descriptor supplied via SCM_RIGHTS",
},
{
- .error_fmt = QERR_OPEN_FILE_FAILED,
- .desc = "Could not open '%(filename)'",
- },
- {
.error_fmt = QERR_INVALID_BLOCK_FORMAT,
- .desc = "Invalid block format %(name)",
+ .desc = "Invalid block format '%(name)'",
},
{
.error_fmt = QERR_INVALID_PARAMETER,
- .desc = "Invalid parameter %(name)",
+ .desc = "Invalid parameter '%(name)'",
},
{
.error_fmt = QERR_INVALID_PARAMETER_TYPE,
@@ -90,7 +110,7 @@ static const QErrorStringTable qerror_table[] = {
},
{
.error_fmt = QERR_INVALID_PASSWORD,
- .desc = "The entered password is invalid",
+ .desc = "Password incorrect",
},
{
.error_fmt = QERR_JSON_PARSING,
@@ -102,7 +122,31 @@ static const QErrorStringTable qerror_table[] = {
},
{
.error_fmt = QERR_MISSING_PARAMETER,
- .desc = "Parameter %(name) is missing",
+ .desc = "Parameter '%(name)' is missing",
+ },
+ {
+ .error_fmt = QERR_NO_BUS_FOR_DEVICE,
+ .desc = "No '%(bus)' bus found for device '%(device)'",
+ },
+ {
+ .error_fmt = QERR_OPEN_FILE_FAILED,
+ .desc = "Could not open '%(filename)'",
+ },
+ {
+ .error_fmt = QERR_PROPERTY_NOT_FOUND,
+ .desc = "Property '%(device).%(property)' not found",
+ },
+ {
+ .error_fmt = QERR_PROPERTY_VALUE_BAD,
+ .desc = "Property '%(device).%(property)' doesn't take value '%(value)'",
+ },
+ {
+ .error_fmt = QERR_PROPERTY_VALUE_IN_USE,
+ .desc = "Property '%(device).%(property)' can't take value '%(value)', it's in use",
+ },
+ {
+ .error_fmt = QERR_PROPERTY_VALUE_NOT_FOUND,
+ .desc = "Property '%(device).%(property)' can't find value '%(value)'",
},
{
.error_fmt = QERR_QMP_BAD_INPUT_OBJECT,
@@ -224,6 +268,7 @@ QError *qerror_from_info(const char *file, int linenr, const char *func,
QError *qerr;
qerr = qerror_new();
+ loc_save(&qerr->loc);
qerr->linenr = linenr;
qerr->file = file;
qerr->func = func;
@@ -318,13 +363,15 @@ QString *qerror_human(const QError *qerror)
* qerror_print(): Print QError data
*
* This function will print the member 'desc' of the specified QError object,
- * it uses qemu_error() for this, so that the output is routed to the right
+ * it uses error_report() for this, so that the output is routed to the right
* place (ie. stderr or Monitor's device).
*/
-void qerror_print(const QError *qerror)
+void qerror_print(QError *qerror)
{
QString *qstring = qerror_human(qerror);
- qemu_error("%s\n", qstring_get_str(qstring));
+ loc_push_restore(&qerror->loc);
+ error_report("%s", qstring_get_str(qstring));
+ loc_pop(&qerror->loc);
QDECREF(qstring);
}
diff --git a/qerror.h b/qerror.h
index ee59615bd..88b297a96 100644
--- a/qerror.h
+++ b/qerror.h
@@ -14,6 +14,7 @@
#include "qdict.h"
#include "qstring.h"
+#include "qemu-error.h"
#include <stdarg.h>
typedef struct QErrorStringTable {
@@ -24,6 +25,7 @@ typedef struct QErrorStringTable {
typedef struct QError {
QObject_HEAD;
QDict *error;
+ Location loc;
int linenr;
const char *file;
const char *func;
@@ -34,21 +36,36 @@ QError *qerror_new(void);
QError *qerror_from_info(const char *file, int linenr, const char *func,
const char *fmt, va_list *va);
QString *qerror_human(const QError *qerror);
-void qerror_print(const QError *qerror);
+void qerror_print(QError *qerror);
QError *qobject_to_qerror(const QObject *obj);
/*
* QError class list
*/
+#define QERR_BAD_BUS_FOR_DEVICE \
+ "{ 'class': 'BadBusForDevice', 'data': { 'device': %s, 'bad_bus_type': %s } }"
+
+#define QERR_BUS_NOT_FOUND \
+ "{ 'class': 'BusNotFound', 'data': { 'bus': %s } }"
+
+#define QERR_BUS_NO_HOTPLUG \
+ "{ 'class': 'BusNoHotplug', 'data': { 'bus': %s } }"
+
#define QERR_COMMAND_NOT_FOUND \
"{ 'class': 'CommandNotFound', 'data': { 'name': %s } }"
#define QERR_DEVICE_ENCRYPTED \
"{ 'class': 'DeviceEncrypted', 'data': { 'device': %s } }"
-#define QERR_DEVICE_LOCKED \
+#define QERR_DEVICE_INIT_FAILED \
+ "{ 'class': 'DeviceInitFailed', 'data': { 'device': %s } }"
+
+#define QERR_DEVICE_LOCKED \
"{ 'class': 'DeviceLocked', 'data': { 'device': %s } }"
+#define QERR_DEVICE_MULTIPLE_BUSSES \
+ "{ 'class': 'DeviceMultipleBusses', 'data': { 'device': %s } }"
+
#define QERR_DEVICE_NOT_ACTIVE \
"{ 'class': 'DeviceNotActive', 'data': { 'device': %s } }"
@@ -58,15 +75,15 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_DEVICE_NOT_REMOVABLE \
"{ 'class': 'DeviceNotRemovable', 'data': { 'device': %s } }"
+#define QERR_DEVICE_NO_BUS \
+ "{ 'class': 'DeviceNoBus', 'data': { 'device': %s } }"
+
#define QERR_FD_NOT_FOUND \
"{ 'class': 'FdNotFound', 'data': { 'name': %s } }"
#define QERR_FD_NOT_SUPPLIED \
"{ 'class': 'FdNotSupplied', 'data': {} }"
-#define QERR_OPEN_FILE_FAILED \
- "{ 'class': 'OpenFileFailed', 'data': { 'filename': %s } }"
-
#define QERR_INVALID_BLOCK_FORMAT \
"{ 'class': 'InvalidBlockFormat', 'data': { 'name': %s } }"
@@ -88,18 +105,36 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_MISSING_PARAMETER \
"{ 'class': 'MissingParameter', 'data': { 'name': %s } }"
+#define QERR_NO_BUS_FOR_DEVICE \
+ "{ 'class': 'NoBusForDevice', 'data': { 'device': %s, 'bus': %s } }"
+
+#define QERR_OPEN_FILE_FAILED \
+ "{ 'class': 'OpenFileFailed', 'data': { 'filename': %s } }"
+
+#define QERR_PROPERTY_NOT_FOUND \
+ "{ 'class': 'PropertyNotFound', 'data': { 'device': %s, 'property': %s } }"
+
+#define QERR_PROPERTY_VALUE_BAD \
+ "{ 'class': 'PropertyValueBad', 'data': { 'device': %s, 'property': %s, 'value': %s } }"
+
+#define QERR_PROPERTY_VALUE_IN_USE \
+ "{ 'class': 'PropertyValueInUse', 'data': { 'device': %s, 'property': %s, 'value': %s } }"
+
+#define QERR_PROPERTY_VALUE_NOT_FOUND \
+ "{ 'class': 'PropertyValueNotFound', 'data': { 'device': %s, 'property': %s, 'value': %s } }"
+
#define QERR_QMP_BAD_INPUT_OBJECT \
"{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }"
#define QERR_SET_PASSWD_FAILED \
"{ 'class': 'SetPasswdFailed', 'data': {} }"
-#define QERR_UNDEFINED_ERROR \
- "{ 'class': 'UndefinedError', 'data': {} }"
-
#define QERR_TOO_MANY_FILES \
"{ 'class': 'TooManyFiles', 'data': {} }"
+#define QERR_UNDEFINED_ERROR \
+ "{ 'class': 'UndefinedError', 'data': {} }"
+
#define QERR_VNC_SERVER_FAILED \
"{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }"
diff --git a/savevm.c b/savevm.c
index 15477e9d8..086c92a70 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1737,7 +1737,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
vm_start();
}
-int load_vmstate(Monitor *mon, const char *name)
+int load_vmstate(const char *name)
{
DriveInfo *dinfo;
BlockDriverState *bs, *bs1;
@@ -1747,7 +1747,7 @@ int load_vmstate(Monitor *mon, const char *name)
bs = get_bs_snapshots();
if (!bs) {
- monitor_printf(mon, "No block device supports snapshots\n");
+ error_report("No block device supports snapshots");
return -EINVAL;
}
@@ -1759,22 +1759,21 @@ int load_vmstate(Monitor *mon, const char *name)
if (bdrv_has_snapshot(bs1)) {
ret = bdrv_snapshot_goto(bs1, name);
if (ret < 0) {
- if (bs != bs1)
- monitor_printf(mon, "Warning: ");
switch(ret) {
case -ENOTSUP:
- monitor_printf(mon,
- "Snapshots not supported on device '%s'\n",
- bdrv_get_device_name(bs1));
+ error_report("%sSnapshots not supported on device '%s'",
+ bs != bs1 ? "Warning: " : "",
+ bdrv_get_device_name(bs1));
break;
case -ENOENT:
- monitor_printf(mon, "Could not find snapshot '%s' on "
- "device '%s'\n",
- name, bdrv_get_device_name(bs1));
+ error_report("%sCould not find snapshot '%s' on device '%s'",
+ bs != bs1 ? "Warning: " : "",
+ name, bdrv_get_device_name(bs1));
break;
default:
- monitor_printf(mon, "Error %d while activating snapshot on"
- " '%s'\n", ret, bdrv_get_device_name(bs1));
+ error_report("%sError %d while activating snapshot on '%s'",
+ bs != bs1 ? "Warning: " : "",
+ ret, bdrv_get_device_name(bs1));
break;
}
/* fatal on snapshot block device */
@@ -1792,13 +1791,13 @@ int load_vmstate(Monitor *mon, const char *name)
/* restore the VM state */
f = qemu_fopen_bdrv(bs, 0);
if (!f) {
- monitor_printf(mon, "Could not open VM state file\n");
+ error_report("Could not open VM state file");
return -EINVAL;
}
ret = qemu_loadvm_state(f);
qemu_fclose(f);
if (ret < 0) {
- monitor_printf(mon, "Error %d while loading VM state\n", ret);
+ error_report("Error %d while loading VM state", ret);
return ret;
}
return 0;
diff --git a/slirp/misc.c b/slirp/misc.c
index dcb1dc117..1aeb40108 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -260,7 +260,7 @@ void lprint(const char *format, ...)
va_list args;
va_start(args, format);
- monitor_vprintf(cur_mon, format, args);
+ monitor_vprintf(default_mon, format, args);
va_end(args);
}
diff --git a/sysemu.h b/sysemu.h
index afa11b551..8a9c630eb 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -54,7 +54,7 @@ extern qemu_irq qemu_system_powerdown;
void qemu_system_reset(void);
void do_savevm(Monitor *mon, const QDict *qdict);
-int load_vmstate(Monitor *mon, const char *name);
+int load_vmstate(const char *name);
void do_delvm(Monitor *mon, const QDict *qdict);
void do_info_snapshots(Monitor *mon);
@@ -73,17 +73,6 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f);
void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f);
int qemu_loadvm_state(QEMUFile *f);
-void qemu_errors_to_file(FILE *fp);
-void qemu_errors_to_mon(Monitor *mon);
-void qemu_errors_to_previous(void);
-void qemu_error(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
-void qemu_error_internal(const char *file, int linenr, const char *func,
- const char *fmt, ...)
- __attribute__ ((format(printf, 4, 5)));
-
-#define qemu_error_new(fmt, ...) \
- qemu_error_internal(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__)
-
#ifdef _WIN32
/* Polling handling */
diff --git a/usb-linux.c b/usb-linux.c
index a9c15c6d1..d0d7cff49 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -1188,9 +1188,6 @@ static int usb_host_scan_dev(void *opaque, USBScanFunc *func)
*/
static int usb_host_read_file(char *line, size_t line_size, const char *device_file, const char *device_name)
{
-#if 0
- Monitor *mon = cur_mon;
-#endif
FILE *f;
int ret = 0;
char filename[PATH_MAX];
@@ -1201,11 +1198,6 @@ static int usb_host_read_file(char *line, size_t line_size, const char *device_f
if (f) {
ret = fgets(line, line_size, f) != NULL;
fclose(f);
-#if 0
- } else {
- if (mon)
- monitor_printf(mon, "husb: could not open %s\n", filename);
-#endif
}
return ret;
diff --git a/vl.c b/vl.c
index a3e43ad9a..01dc1aa2d 100644
--- a/vl.c
+++ b/vl.c
@@ -1813,7 +1813,7 @@ QemuOpts *drive_add(const char *file, const char *fmt, ...)
vsnprintf(optstr, sizeof(optstr), fmt, ap);
va_end(ap);
- opts = qemu_opts_parse(&qemu_drive_opts, optstr, NULL);
+ opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0);
if (!opts) {
fprintf(stderr, "%s: huh? duplicate? (%s)\n",
__FUNCTION__, optstr);
@@ -2539,7 +2539,7 @@ void do_usb_add(Monitor *mon, const QDict *qdict)
{
const char *devname = qdict_get_str(qdict, "devname");
if (usb_device_add(devname, 1) < 0) {
- qemu_error("could not add USB device '%s'\n", devname);
+ error_report("could not add USB device '%s'", devname);
}
}
@@ -2547,7 +2547,7 @@ void do_usb_del(Monitor *mon, const QDict *qdict)
{
const char *devname = qdict_get_str(qdict, "devname");
if (usb_device_del(devname) < 0) {
- qemu_error("could not delete USB device '%s'\n", devname);
+ error_report("could not delete USB device '%s'", devname);
}
}
@@ -4370,7 +4370,7 @@ static int balloon_parse(const char *arg)
if (!strncmp(arg, "virtio", 6)) {
if (arg[6] == ',') {
/* have params -> parse them */
- opts = qemu_opts_parse(&qemu_device_opts, arg+7, NULL);
+ opts = qemu_opts_parse(&qemu_device_opts, arg+7, 0);
if (!opts)
return -1;
} else {
@@ -4796,6 +4796,7 @@ static const QEMUOption *lookup_opt(int argc, char **argv,
char *r = argv[optind];
const char *optarg;
+ loc_set_cmdline(argv, optind, 1);
optind++;
/* Treat --foo the same as -foo. */
if (r[1] == '-')
@@ -4803,8 +4804,7 @@ static const QEMUOption *lookup_opt(int argc, char **argv,
popt = qemu_options;
for(;;) {
if (!popt->name) {
- fprintf(stderr, "%s: invalid option -- '%s'\n",
- argv[0], r);
+ error_report("invalid option");
exit(1);
}
if (!strcmp(popt->name, r + 1))
@@ -4813,11 +4813,11 @@ static const QEMUOption *lookup_opt(int argc, char **argv,
}
if (popt->flags & HAS_ARG) {
if (optind >= argc) {
- fprintf(stderr, "%s: option '%s' requires an argument\n",
- argv[0], r);
+ error_report("requires an argument");
exit(1);
}
optarg = argv[optind++];
+ loc_set_cmdline(argv, optind - 2, 2);
} else {
optarg = NULL;
}
@@ -4862,9 +4862,10 @@ int main(int argc, char **argv, char **envp)
int show_vnc_port = 0;
int defconfig = 1;
+ error_set_progname(argv[0]);
+
init_clocks();
- qemu_errors_to_file(stderr);
qemu_cache_utils_init(envp);
QLIST_INIT (&vm_change_state_head);
@@ -4940,18 +4941,22 @@ int main(int argc, char **argv, char **envp)
}
if (defconfig) {
+ const char *fname;
FILE *fp;
- fp = fopen(CONFIG_QEMU_CONFDIR "/qemu.conf", "r");
+
+ fname = CONFIG_QEMU_CONFDIR "/qemu.conf";
+ fp = fopen(fname, "r");
if (fp) {
- if (qemu_config_parse(fp) != 0) {
+ if (qemu_config_parse(fp, fname) != 0) {
exit(1);
}
fclose(fp);
}
- fp = fopen(CONFIG_QEMU_CONFDIR "/target-" TARGET_ARCH ".conf", "r");
+ fname = CONFIG_QEMU_CONFDIR "/target-" TARGET_ARCH ".conf";
+ fp = fopen(fname, "r");
if (fp) {
- if (qemu_config_parse(fp) != 0) {
+ if (qemu_config_parse(fp, fname) != 0) {
exit(1);
}
fclose(fp);
@@ -5360,7 +5365,7 @@ int main(int argc, char **argv, char **envp)
default_monitor = 0;
break;
case QEMU_OPTION_mon:
- opts = qemu_opts_parse(&qemu_mon_opts, optarg, "chardev");
+ opts = qemu_opts_parse(&qemu_mon_opts, optarg, 1);
if (!opts) {
fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
@@ -5368,7 +5373,7 @@ int main(int argc, char **argv, char **envp)
default_monitor = 0;
break;
case QEMU_OPTION_chardev:
- opts = qemu_opts_parse(&qemu_chardev_opts, optarg, "backend");
+ opts = qemu_opts_parse(&qemu_chardev_opts, optarg, 1);
if (!opts) {
fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
@@ -5471,7 +5476,7 @@ int main(int argc, char **argv, char **envp)
add_device_config(DEV_USB, optarg);
break;
case QEMU_OPTION_device:
- if (!qemu_opts_parse(&qemu_device_opts, optarg, "driver")) {
+ if (!qemu_opts_parse(&qemu_device_opts, optarg, 1)) {
exit(1);
}
break;
@@ -5580,7 +5585,7 @@ int main(int argc, char **argv, char **envp)
configure_rtc_date_offset(optarg, 1);
break;
case QEMU_OPTION_rtc:
- opts = qemu_opts_parse(&qemu_rtc_opts, optarg, NULL);
+ opts = qemu_opts_parse(&qemu_rtc_opts, optarg, 0);
if (!opts) {
fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
@@ -5641,7 +5646,7 @@ int main(int argc, char **argv, char **envp)
fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
exit(1);
}
- if (qemu_config_parse(fp) != 0) {
+ if (qemu_config_parse(fp, optarg) != 0) {
exit(1);
}
fclose(fp);
@@ -5666,6 +5671,7 @@ int main(int argc, char **argv, char **envp)
}
}
}
+ loc_set_none();
/* If no data_dir is specified then try to find it relative to the
executable path. */
@@ -6081,7 +6087,7 @@ int main(int argc, char **argv, char **envp)
qemu_system_reset();
if (loadvm) {
- if (load_vmstate(cur_mon, loadvm) < 0) {
+ if (load_vmstate(loadvm) < 0) {
autostart = 0;
}
}
diff --git a/vnc.c b/vnc.c
index 7ce73dca3..f10a37f74 100644
--- a/vnc.c
+++ b/vnc.c
@@ -1046,11 +1046,10 @@ static void audio_capture(void *opaque, void *buf, int size)
static void audio_add(VncState *vs)
{
- Monitor *mon = cur_mon;
struct audio_capture_ops ops;
if (vs->audio_cap) {
- monitor_printf(mon, "audio already running\n");
+ monitor_printf(default_mon, "audio already running\n");
return;
}
@@ -1060,7 +1059,7 @@ static void audio_add(VncState *vs)
vs->audio_cap = AUD_add_capture(&vs->as, &ops, vs);
if (!vs->audio_cap) {
- monitor_printf(mon, "Failed to add audio capture\n");
+ monitor_printf(default_mon, "Failed to add audio capture\n");
}
}