Merge remote branch 'markus/qerror' into staging

This commit is contained in:
Anthony Liguori 2010-03-17 09:44:37 -05:00
commit 4a39943bd1
45 changed files with 1009 additions and 535 deletions

View File

@ -172,6 +172,7 @@ endif #CONFIG_BSD_USER
ifdef CONFIG_SOFTMMU 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 = 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. # virtio has to be here due to weird dependency between PCI and virtio-net.
# need to fix this properly # need to fix this properly
obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o

View File

@ -330,10 +330,10 @@ void AUD_vlog (const char *cap, const char *fmt, va_list ap)
{ {
if (conf.log_to_monitor) { if (conf.log_to_monitor) {
if (cap) { 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 { else {
if (cap) { if (cap) {

35
hw/pc.c
View File

@ -230,40 +230,40 @@ static int boot_device2nibble(char boot_device)
return 0; return 0;
} }
/* copy/pasted from cmos_init, should be made a general function static int set_boot_dev(RTCState *s, const char *boot_device, int fd_bootchk)
and used there as well */
static int pc_boot_set(void *opaque, const char *boot_device)
{ {
Monitor *mon = cur_mon;
#define PC_MAX_BOOT_DEVICES 3 #define PC_MAX_BOOT_DEVICES 3
RTCState *s = (RTCState *)opaque;
int nbds, bds[3] = { 0, }; int nbds, bds[3] = { 0, };
int i; int i;
nbds = strlen(boot_device); nbds = strlen(boot_device);
if (nbds > PC_MAX_BOOT_DEVICES) { 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); return(1);
} }
for (i = 0; i < nbds; i++) { for (i = 0; i < nbds; i++) {
bds[i] = boot_device2nibble(boot_device[i]); bds[i] = boot_device2nibble(boot_device[i]);
if (bds[i] == 0) { if (bds[i] == 0) {
monitor_printf(mon, "Invalid boot device for PC: '%c'\n", error_report("Invalid boot device for PC: '%c'",
boot_device[i]); boot_device[i]);
return(1); return(1);
} }
} }
rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]); 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); 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 */ /* hd_table must contain 4 block drivers */
static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
const char *boot_device, DriveInfo **hd_table) const char *boot_device, DriveInfo **hd_table)
{ {
RTCState *s = rtc_state; RTCState *s = rtc_state;
int nbds, bds[3] = { 0, };
int val; int val;
int fd0, fd1, nb; int fd0, fd1, nb;
int i; 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); rtc_set_memory(s, 0x5f, smp_cpus - 1);
/* set boot devices, and disable floppy signature check if requested */ /* set boot devices, and disable floppy signature check if requested */
#define PC_MAX_BOOT_DEVICES 3 if (set_boot_dev(s, boot_device, fd_bootchk)) {
nbds = strlen(boot_device);
if (nbds > PC_MAX_BOOT_DEVICES) {
fprintf(stderr, "Too many boot devices for PC\n");
exit(1); 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 */ /* floppy type */

View File

@ -54,7 +54,7 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
return NULL; 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) { if (!opts) {
monitor_printf(mon, "parsing network options '%s' failed\n", monitor_printf(mon, "parsing network options '%s' failed\n",
opts_str ? opts_str : ""); 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); 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; SCSIBus *scsibus;
SCSIDevice *scsidev; SCSIDevice *scsidev;
scsibus = DO_UPCAST(SCSIBus, qbus, QLIST_FIRST(&adapter->child_bus)); scsibus = DO_UPCAST(SCSIBus, qbus, QLIST_FIRST(&adapter->child_bus));
if (!scsibus || strcmp(scsibus->qbus.info->name, "SCSI") != 0) { 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; return -1;
} }
@ -97,7 +98,8 @@ static int scsi_hot_add(DeviceState *adapter, DriveInfo *dinfo, int printinfo)
dinfo->unit = scsidev->id; dinfo->unit = scsidev->id;
if (printinfo) 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; 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); monitor_printf(mon, "no pci device with address %s\n", pci_addr);
goto err; goto err;
} }
if (scsi_hot_add(&dev->qdev, dinfo, 1) != 0) { if (scsi_hot_add(mon, &dev->qdev, dinfo, 1) != 0) {
goto err; goto err;
} }
break; break;
@ -203,7 +205,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
if (qdev_init(&dev->qdev) < 0) if (qdev_init(&dev->qdev) < 0)
dev = NULL; dev = NULL;
if (dev && dinfo) { 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); qdev_unplug(&dev->qdev);
dev = NULL; dev = NULL;
} }

View File

@ -589,12 +589,12 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
if (!bus->devices[devfn]) if (!bus->devices[devfn])
goto found; 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; return NULL;
found: ; found: ;
} else if (bus->devices[devfn]) { } else if (bus->devices[devfn]) {
qemu_error("PCI: devfn %d not available for %s, in use by %s\n", devfn, error_report("PCI: devfn %d not available for %s, in use by %s",
name, bus->devices[devfn]->name); devfn, name, bus->devices[devfn]->name);
return NULL; return NULL;
} }
pci_dev->bus = bus; 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); bus = pci_get_bus_devfn(&devfn, devaddr);
if (!bus) { if (!bus) {
qemu_error("Invalid PCI device address %s for device %s\n", error_report("Invalid PCI device address %s for device %s",
devaddr, pci_nic_names[i]); devaddr, pci_nic_names[i]);
return NULL; return NULL;
} }
@ -1768,8 +1768,8 @@ static int pci_add_option_rom(PCIDevice *pdev)
size = get_image_size(path); size = get_image_size(path);
if (size < 0) { if (size < 0) {
qemu_error("%s: failed to find romfile \"%s\"\n", __FUNCTION__, error_report("%s: failed to find romfile \"%s\"",
pdev->romfile); __FUNCTION__, pdev->romfile);
return -1; return -1;
} }
if (size & (size - 1)) { if (size & (size - 1)) {

View File

@ -402,17 +402,11 @@ PropertyInfo qdev_prop_vlan = {
/* --- pointer --- */ /* --- pointer --- */
static int print_ptr(DeviceState *dev, Property *prop, char *dest, size_t len) /* Not a proper property, just for dirty hacks. TODO Remove it! */
{
void **ptr = qdev_get_prop_ptr(dev, prop);
return snprintf(dest, len, "<%p>", *ptr);
}
PropertyInfo qdev_prop_ptr = { PropertyInfo qdev_prop_ptr = {
.name = "ptr", .name = "ptr",
.type = PROP_TYPE_PTR, .type = PROP_TYPE_PTR,
.size = sizeof(void*), .size = sizeof(void*),
.print = print_ptr,
}; };
/* --- mac address --- */ /* --- mac address --- */
@ -547,31 +541,31 @@ int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
int ret; int ret;
prop = qdev_prop_find(dev, name); prop = qdev_prop_find(dev, name);
if (!prop) { /*
fprintf(stderr, "property \"%s.%s\" not found\n", * TODO Properties without a parse method are just for dirty
dev->info->name, name); * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
return -1; * marked for removal. The test !prop->info->parse should be
} * removed along with it.
if (!prop->info->parse) { */
fprintf(stderr, "property \"%s.%s\" has no parser\n", if (!prop || !prop->info->parse) {
dev->info->name, name); qerror_report(QERR_PROPERTY_NOT_FOUND, dev->info->name, name);
return -1; return -1;
} }
ret = prop->info->parse(dev, prop, value); ret = prop->info->parse(dev, prop, value);
if (ret < 0) { if (ret < 0) {
switch (ret) { switch (ret) {
case -EEXIST: case -EEXIST:
fprintf(stderr, "property \"%s.%s\": \"%s\" is already in use\n", qerror_report(QERR_PROPERTY_VALUE_IN_USE,
dev->info->name, name, value); dev->info->name, name, value);
break; break;
default: default:
case -EINVAL: case -EINVAL:
fprintf(stderr, "property \"%s.%s\": failed to parse \"%s\"\n", qerror_report(QERR_PROPERTY_VALUE_BAD,
dev->info->name, name, value); dev->info->name, name, value);
break; break;
case -ENOENT: case -ENOENT:
fprintf(stderr, "property \"%s.%s\": could not find \"%s\"\n", qerror_report(QERR_PROPERTY_VALUE_NOT_FOUND,
dev->info->name, name, value); dev->info->name, name, value);
break; break;
} }
return -1; return -1;

240
hw/qdev.c
View File

@ -29,7 +29,6 @@
#include "qdev.h" #include "qdev.h"
#include "sysemu.h" #include "sysemu.h"
#include "monitor.h" #include "monitor.h"
#include "qerror.h"
static int qdev_hotplug = 0; static int qdev_hotplug = 0;
@ -78,26 +77,11 @@ static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
return NULL; return NULL;
} }
/* Create a new device. This only initializes the device state structure static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
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; DeviceState *dev;
if (!bus) { assert(bus->info == info->bus_info);
if (!main_system_bus) {
main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
}
bus = main_system_bus;
}
info = qdev_find_info(bus->info, name);
if (!info) {
hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
}
dev = qemu_mallocz(info->size); dev = qemu_mallocz(info->size);
dev->info = info; dev->info = info;
dev->parent_bus = bus; dev->parent_bus = bus;
@ -113,27 +97,42 @@ DeviceState *qdev_create(BusState *bus, const char *name)
return dev; return dev;
} }
static int qdev_print_devinfo(DeviceInfo *info, char *dest, int len) /* 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)
{ {
int pos = 0; DeviceInfo *info;
int ret;
ret = snprintf(dest+pos, len-pos, "name \"%s\", bus %s", if (!bus) {
info->name, info->bus_info->name); if (!main_system_bus) {
pos += MIN(len-pos,ret); main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
}
bus = main_system_bus;
}
info = qdev_find_info(bus->info, name);
if (!info) {
hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
}
return qdev_create_from_info(bus, info);
}
static void qdev_print_devinfo(DeviceInfo *info)
{
error_printf("name \"%s\", bus %s",
info->name, info->bus_info->name);
if (info->alias) { if (info->alias) {
ret = snprintf(dest+pos, len-pos, ", alias \"%s\"", info->alias); error_printf(", alias \"%s\"", info->alias);
pos += MIN(len-pos,ret);
} }
if (info->desc) { if (info->desc) {
ret = snprintf(dest+pos, len-pos, ", desc \"%s\"", info->desc); error_printf(", desc \"%s\"", info->desc);
pos += MIN(len-pos,ret);
} }
if (info->no_user) { if (info->no_user) {
ret = snprintf(dest+pos, len-pos, ", no-user"); error_printf(", no-user");
pos += MIN(len-pos,ret);
} }
return pos; error_printf("\n");
} }
static int set_property(const char *name, const char *value, void *opaque) 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; return 0;
if (qdev_prop_parse(dev, name, value) == -1) { 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 -1;
} }
return 0; return 0;
@ -157,14 +154,15 @@ int qdev_device_help(QemuOpts *opts)
{ {
const char *driver; const char *driver;
DeviceInfo *info; DeviceInfo *info;
char msg[256];
Property *prop; Property *prop;
driver = qemu_opt_get(opts, "driver"); driver = qemu_opt_get(opts, "driver");
if (driver && !strcmp(driver, "?")) { if (driver && !strcmp(driver, "?")) {
for (info = device_info_list; info != NULL; info = info->next) { for (info = device_info_list; info != NULL; info = info->next) {
qdev_print_devinfo(info, msg, sizeof(msg)); if (info->no_user) {
qemu_error("%s\n", msg); continue; /* not available, don't show */
}
qdev_print_devinfo(info);
} }
return 1; return 1;
} }
@ -179,7 +177,16 @@ int qdev_device_help(QemuOpts *opts)
} }
for (prop = info->props; prop && prop->name; prop++) { 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; return 1;
} }
@ -193,19 +200,15 @@ DeviceState *qdev_device_add(QemuOpts *opts)
driver = qemu_opt_get(opts, "driver"); driver = qemu_opt_get(opts, "driver");
if (!driver) { if (!driver) {
qemu_error("-device: no driver specified\n"); qerror_report(QERR_MISSING_PARAMETER, "driver");
return NULL; return NULL;
} }
/* find driver */ /* find driver */
info = qdev_find_info(NULL, driver); info = qdev_find_info(NULL, driver);
if (!info) { if (!info || info->no_user) {
qemu_error_new(QERR_DEVICE_NOT_FOUND, driver); qerror_report(QERR_INVALID_PARAMETER, "driver");
return NULL; error_printf_unless_qmp("Try with argument '?' for a list.\n");
}
if (info->no_user) {
qemu_error("device \"%s\" can't be added via command line\n",
info->name);
return NULL; return NULL;
} }
@ -213,22 +216,29 @@ DeviceState *qdev_device_add(QemuOpts *opts)
path = qemu_opt_get(opts, "bus"); path = qemu_opt_get(opts, "bus");
if (path != NULL) { if (path != NULL) {
bus = qbus_find(path); 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 { } else {
bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info); bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
} if (!bus) {
if (!bus) { qerror_report(QERR_NO_BUS_FOR_DEVICE,
qemu_error("Did not find %s bus for %s\n", info->name, info->bus_info->name);
path ? path : info->bus_info->name, info->name); return NULL;
return NULL; }
} }
if (qdev_hotplug && !bus->allow_hotplug) { if (qdev_hotplug && !bus->allow_hotplug) {
qemu_error("Bus %s does not support hotplugging\n", qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
bus->name);
return NULL; return NULL;
} }
/* create device, set properties */ /* create device, set properties */
qdev = qdev_create(bus, driver); qdev = qdev_create_from_info(bus, info);
id = qemu_opts_id(opts); id = qemu_opts_id(opts);
if (id) { if (id) {
qdev->id = id; qdev->id = id;
@ -238,7 +248,7 @@ DeviceState *qdev_device_add(QemuOpts *opts)
return NULL; return NULL;
} }
if (qdev_init(qdev) < 0) { if (qdev_init(qdev) < 0) {
qemu_error("Error initializing device %s\n", driver); qerror_report(QERR_DEVICE_INIT_FAILED, driver);
return NULL; return NULL;
} }
qdev->opts = opts; qdev->opts = opts;
@ -277,8 +287,8 @@ int qdev_init(DeviceState *dev)
int qdev_unplug(DeviceState *dev) int qdev_unplug(DeviceState *dev)
{ {
if (!dev->parent_bus->allow_hotplug) { if (!dev->parent_bus->allow_hotplug) {
qemu_error("Bus %s does not support hotplugging\n", error_report("Bus %s does not support hotplugging",
dev->parent_bus->name); dev->parent_bus->name);
return -1; return -1;
} }
assert(dev->info->unplug != NULL); assert(dev->info->unplug != NULL);
@ -465,35 +475,33 @@ static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
return NULL; return NULL;
} }
static void qbus_list_bus(DeviceState *dev, char *dest, int len) static void qbus_list_bus(DeviceState *dev)
{ {
BusState *child; BusState *child;
const char *sep = " "; const char *sep = " ";
int pos = 0;
pos += snprintf(dest+pos, len-pos,"child busses at \"%s\":", error_printf("child busses at \"%s\":",
dev->id ? dev->id : dev->info->name); dev->id ? dev->id : dev->info->name);
QLIST_FOREACH(child, &dev->child_bus, sibling) { 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 = ", "; sep = ", ";
} }
error_printf("\n");
} }
static void qbus_list_dev(BusState *bus, char *dest, int len) static void qbus_list_dev(BusState *bus)
{ {
DeviceState *dev; DeviceState *dev;
const char *sep = " "; const char *sep = " ";
int pos = 0;
pos += snprintf(dest+pos, len-pos, "devices at \"%s\":", error_printf("devices at \"%s\":", bus->name);
bus->name);
QLIST_FOREACH(dev, &bus->children, sibling) { QLIST_FOREACH(dev, &bus->children, sibling) {
pos += snprintf(dest+pos, len-pos, "%s\"%s\"", error_printf("%s\"%s\"", sep, dev->info->name);
sep, dev->info->name);
if (dev->id) if (dev->id)
pos += snprintf(dest+pos, len-pos, "/\"%s\"", dev->id); error_printf("/\"%s\"", dev->id);
sep = ", "; sep = ", ";
} }
error_printf("\n");
} }
static BusState *qbus_find_bus(DeviceState *dev, char *elem) static BusState *qbus_find_bus(DeviceState *dev, char *elem)
@ -540,7 +548,7 @@ static BusState *qbus_find(const char *path)
{ {
DeviceState *dev; DeviceState *dev;
BusState *bus; BusState *bus;
char elem[128], msg[256]; char elem[128];
int pos, len; int pos, len;
/* find start element */ /* find start element */
@ -549,62 +557,75 @@ static BusState *qbus_find(const char *path)
pos = 0; pos = 0;
} else { } else {
if (sscanf(path, "%127[^/]%n", elem, &len) != 1) { if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
qemu_error("path parse error (\"%s\")\n", path); assert(!path[0]);
return NULL; elem[0] = len = 0;
} }
bus = qbus_find_recursive(main_system_bus, elem, NULL); bus = qbus_find_recursive(main_system_bus, elem, NULL);
if (!bus) { if (!bus) {
qemu_error("bus \"%s\" not found\n", elem); qerror_report(QERR_BUS_NOT_FOUND, elem);
return NULL; return NULL;
} }
pos = len; pos = len;
} }
for (;;) { for (;;) {
assert(path[pos] == '/' || !path[pos]);
while (path[pos] == '/') {
pos++;
}
if (path[pos] == '\0') { if (path[pos] == '\0') {
/* we are done */
return bus; return bus;
} }
/* find device */ /* find device */
if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) { if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
qemu_error("path parse error (\"%s\" pos %d)\n", path, pos); assert(0);
return NULL; elem[0] = len = 0;
} }
pos += len; pos += len;
dev = qbus_find_dev(bus, elem); dev = qbus_find_dev(bus, elem);
if (!dev) { if (!dev) {
qbus_list_dev(bus, msg, sizeof(msg)); qerror_report(QERR_DEVICE_NOT_FOUND, elem);
qemu_error("device \"%s\" not found\n%s\n", elem, msg); if (!monitor_cur_is_qmp()) {
qbus_list_dev(bus);
}
return NULL; return NULL;
} }
assert(path[pos] == '/' || !path[pos]);
while (path[pos] == '/') {
pos++;
}
if (path[pos] == '\0') { if (path[pos] == '\0') {
/* last specified element is a device. If it has exactly /* last specified element is a device. If it has exactly
* one child bus accept it nevertheless */ * one child bus accept it nevertheless */
switch (dev->num_child_bus) { switch (dev->num_child_bus) {
case 0: case 0:
qemu_error("device has no child bus (%s)\n", path); qerror_report(QERR_DEVICE_NO_BUS, elem);
return NULL; return NULL;
case 1: case 1:
return QLIST_FIRST(&dev->child_bus); return QLIST_FIRST(&dev->child_bus);
default: default:
qbus_list_bus(dev, msg, sizeof(msg)); qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
qemu_error("device has multiple child busses (%s)\n%s\n", if (!monitor_cur_is_qmp()) {
path, msg); qbus_list_bus(dev);
}
return NULL; return NULL;
} }
} }
/* find bus */ /* find bus */
if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) { if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
qemu_error("path parse error (\"%s\" pos %d)\n", path, pos); assert(0);
return NULL; elem[0] = len = 0;
} }
pos += len; pos += len;
bus = qbus_find_bus(dev, elem); bus = qbus_find_bus(dev, elem);
if (!bus) { if (!bus) {
qbus_list_bus(dev, msg, sizeof(msg)); qerror_report(QERR_BUS_NOT_FOUND, elem);
qemu_error("child bus \"%s\" not found\n%s\n", elem, msg); if (!monitor_cur_is_qmp()) {
qbus_list_bus(dev);
}
return NULL; return NULL;
} }
} }
@ -684,6 +705,12 @@ static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
if (!props) if (!props)
return; return;
while (props->name) { 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) { if (props->info->print) {
props->info->print(dev, props, buf, sizeof(buf)); props->info->print(dev, props, buf, sizeof(buf));
qdev_printf("%s-prop: %s = %s\n", prefix, props->name, 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) void do_info_qdm(Monitor *mon)
{ {
DeviceInfo *info; DeviceInfo *info;
char msg[256];
for (info = device_info_list; info != NULL; info = info->next) { for (info = device_info_list; info != NULL; info = info->next) {
qdev_print_devinfo(info, msg, sizeof(msg)); qdev_print_devinfo(info);
monitor_printf(mon, "%s\n", msg);
} }
} }
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; QemuOpts *opts;
opts = qemu_opts_parse(&qemu_device_opts, opts = qemu_opts_from_qdict(&qemu_device_opts, qdict);
qdict_get_str(qdict, "config"), "driver"); if (!opts) {
if (opts) { return -1;
if (qdev_device_help(opts) || qdev_device_add(opts) == NULL) {
qemu_opts_del(opts);
}
} }
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) 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); dev = qdev_find_recursive(main_system_bus, id);
if (NULL == dev) { if (NULL == dev) {
qemu_error("Device '%s' not found\n", id); error_report("Device '%s' not found", id);
return; return;
} }
qdev_unplug(dev); qdev_unplug(dev);

View File

@ -175,7 +175,7 @@ void qbus_free(BusState *bus);
void do_info_qtree(Monitor *mon); void do_info_qtree(Monitor *mon);
void do_info_qdm(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); void do_device_del(Monitor *mon, const QDict *qdict);
/*** qdev-properties.c ***/ /*** qdev-properties.c ***/

View File

@ -1,5 +1,5 @@
#include "hw.h" #include "hw.h"
#include "sysemu.h" #include "qemu-error.h"
#include "scsi.h" #include "scsi.h"
#include "scsi-defs.h" #include "scsi-defs.h"
#include "block.h" #include "block.h"
@ -41,7 +41,7 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base)
} }
} }
if (dev->id >= bus->ndev) { 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; goto err;
} }

View File

@ -19,8 +19,6 @@
* the host adapter emulator. * the host adapter emulator.
*/ */
#include <qemu-common.h>
#include <sysemu.h>
//#define DEBUG_SCSI //#define DEBUG_SCSI
#ifdef 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) do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu-error.h"
#include "block.h" #include "block.h"
#include "scsi.h" #include "scsi.h"
#include "scsi-defs.h" #include "scsi-defs.h"
@ -1026,13 +1025,13 @@ static int scsi_disk_initfn(SCSIDevice *dev)
uint64_t nb_sectors; uint64_t nb_sectors;
if (!s->qdev.conf.dinfo || !s->qdev.conf.dinfo->bdrv) { 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; return -1;
} }
s->bs = s->qdev.conf.dinfo->bdrv; s->bs = s->qdev.conf.dinfo->bdrv;
if (bdrv_is_sg(s->bs)) { if (bdrv_is_sg(s->bs)) {
qemu_error("scsi-disk: unwanted /dev/sg*\n"); error_report("scsi-disk: unwanted /dev/sg*");
return -1; return -1;
} }

View File

@ -12,6 +12,7 @@
*/ */
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu-error.h"
#include "block.h" #include "block.h"
#include "scsi.h" #include "scsi.h"
@ -463,27 +464,27 @@ static int scsi_generic_initfn(SCSIDevice *dev)
struct sg_scsi_id scsiid; struct sg_scsi_id scsiid;
if (!s->qdev.conf.dinfo || !s->qdev.conf.dinfo->bdrv) { 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; return -1;
} }
s->bs = s->qdev.conf.dinfo->bdrv; s->bs = s->qdev.conf.dinfo->bdrv;
/* check we are really using a /dev/sg* file */ /* check we are really using a /dev/sg* file */
if (!bdrv_is_sg(s->bs)) { if (!bdrv_is_sg(s->bs)) {
qemu_error("scsi-generic: not /dev/sg*\n"); error_report("scsi-generic: not /dev/sg*");
return -1; return -1;
} }
/* check we are using a driver managing SG_IO (version 3 and after */ /* 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 || if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
sg_version < 30000) { sg_version < 30000) {
qemu_error("scsi-generic: scsi generic interface too old\n"); error_report("scsi-generic: scsi generic interface too old");
return -1; return -1;
} }
/* get LUN of the /dev/sg? */ /* get LUN of the /dev/sg? */
if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) { 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; return -1;
} }

View File

@ -291,14 +291,14 @@ USBDevice *usbdevice_create(const char *cmdline)
if (info == NULL) { if (info == NULL) {
#if 0 #if 0
/* no error because some drivers are not converted (yet) */ /* 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 #endif
return NULL; return NULL;
} }
if (!usb->usbdevice_init) { if (!usb->usbdevice_init) {
if (params) { if (params) {
qemu_error("usbdevice %s accepts no params\n", driver); error_report("usbdevice %s accepts no params", driver);
return NULL; return NULL;
} }
return usb_create_simple(bus, usb->qdev.name); return usb_create_simple(bus, usb->qdev.name);

View File

@ -524,7 +524,7 @@ static int usb_msd_initfn(USBDevice *dev)
MSDState *s = DO_UPCAST(MSDState, dev, dev); MSDState *s = DO_UPCAST(MSDState, dev, dev);
if (!s->conf.dinfo || !s->conf.dinfo->bdrv) { 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; return -1;
} }
@ -535,7 +535,7 @@ static int usb_msd_initfn(USBDevice *dev)
usb_msd_handle_reset(dev); usb_msd_handle_reset(dev);
if (bdrv_key_required(s->conf.dinfo->bdrv)) { 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, monitor_read_bdrv_key_start(cur_mon, s->conf.dinfo->bdrv,
usb_msd_password_cb, s); usb_msd_password_cb, s);
s->dev.auto_attach = 0; s->dev.auto_attach = 0;

View File

@ -1478,7 +1478,7 @@ static USBDevice *usb_net_init(const char *cmdline)
QemuOpts *opts; QemuOpts *opts;
int idx; int idx;
opts = qemu_opts_parse(&qemu_net_opts, cmdline, NULL); opts = qemu_opts_parse(&qemu_net_opts, cmdline, 0);
if (!opts) { if (!opts) {
return NULL; return NULL;
} }

View File

@ -9,6 +9,7 @@
*/ */
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu-error.h"
#include "usb.h" #include "usb.h"
#include "qemu-char.h" #include "qemu-char.h"
@ -564,26 +565,26 @@ static USBDevice *usb_serial_init(const char *filename)
if (strstart(filename, "vendorid=", &p)) { if (strstart(filename, "vendorid=", &p)) {
vendorid = strtol(p, &e, 16); vendorid = strtol(p, &e, 16);
if (e == p || (*e && *e != ',' && *e != ':')) { if (e == p || (*e && *e != ',' && *e != ':')) {
qemu_error("bogus vendor ID %s\n", p); error_report("bogus vendor ID %s", p);
return NULL; return NULL;
} }
filename = e; filename = e;
} else if (strstart(filename, "productid=", &p)) { } else if (strstart(filename, "productid=", &p)) {
productid = strtol(p, &e, 16); productid = strtol(p, &e, 16);
if (e == p || (*e && *e != ',' && *e != ':')) { if (e == p || (*e && *e != ',' && *e != ':')) {
qemu_error("bogus product ID %s\n", p); error_report("bogus product ID %s", p);
return NULL; return NULL;
} }
filename = e; filename = e;
} else { } else {
qemu_error("unrecognized serial USB option %s\n", filename); error_report("unrecognized serial USB option %s", filename);
return NULL; return NULL;
} }
while(*filename == ',') while(*filename == ',')
filename++; filename++;
} }
if (!*filename) { if (!*filename) {
qemu_error("character device specification needed\n"); error_report("character device specification needed");
return NULL; return NULL;
} }
filename++; filename++;

View File

@ -15,6 +15,7 @@
#include "net.h" #include "net.h"
#include "net/checksum.h" #include "net/checksum.h"
#include "net/tap.h" #include "net/tap.h"
#include "qemu-error.h"
#include "qemu-timer.h" #include "qemu-timer.h"
#include "virtio-net.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 (version_id >= 7) {
if (qemu_get_be32(f) && !peer_has_vnet_hdr(n)) { 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; return -1;
} }
@ -793,7 +794,7 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
if (version_id >= 11) { if (version_id >= 11) {
if (qemu_get_byte(f) && !peer_has_ufo(n)) { 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; return -1;
} }
} }

View File

@ -19,7 +19,7 @@
#include "virtio-blk.h" #include "virtio-blk.h"
#include "virtio-net.h" #include "virtio-net.h"
#include "pci.h" #include "pci.h"
#include "sysemu.h" #include "qemu-error.h"
#include "msix.h" #include "msix.h"
#include "net.h" #include "net.h"
#include "block_int.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; proxy->class_code = PCI_CLASS_STORAGE_SCSI;
if (!proxy->block.dinfo) { 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; return -1;
} }
vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block); vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block);

View File

@ -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); plugging_port0 = port->is_console && !find_port_by_id(port->vser, 0);
if (port->vser->config.nr_ports == bus->max_nr_ports && !plugging_port0) { 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; return -1;
} }
dev->info = info; dev->info = info;

337
monitor.c
View File

@ -67,6 +67,11 @@
* 'F' filename * 'F' filename
* 'B' block device name * 'B' block device name
* 's' string (accept optional quote) * '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 * 'i' 32 bit integer
* 'l' target long (32 or 64 bit) * 'l' target long (32 or 64 bit)
* 'M' just like 'l', except in user mode the value is * '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 mon_cmds[];
static const mon_cmd_t info_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, static void monitor_command_cb(Monitor *mon, const char *cmdline,
void *opaque); void *opaque);
@ -193,6 +199,12 @@ static inline int monitor_ctrl_mode(const Monitor *mon)
return (mon->flags & MONITOR_USE_CONTROL); 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) static void monitor_read_command(Monitor *mon, int show_prompt)
{ {
if (!mon->rs) if (!mon->rs)
@ -207,7 +219,7 @@ static int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
void *opaque) void *opaque)
{ {
if (monitor_ctrl_mode(mon)) { if (monitor_ctrl_mode(mon)) {
qemu_error_new(QERR_MISSING_PARAMETER, "password"); qerror_report(QERR_MISSING_PARAMETER, "password");
return -EINVAL; return -EINVAL;
} else if (mon->rs) { } else if (mon->rs) {
readline_start(mon->rs, "Password: ", 1, readline_func, opaque); 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 (cmd->name == NULL) {
if (monitor_ctrl_mode(mon)) { if (monitor_ctrl_mode(mon)) {
qemu_error_new(QERR_COMMAND_NOT_FOUND, item); qerror_report(QERR_COMMAND_NOT_FOUND, item);
return -1; return -1;
} }
goto help; goto help;
@ -638,7 +650,7 @@ static int do_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
} else { } else {
if (monitor_ctrl_mode(mon)) { if (monitor_ctrl_mode(mon)) {
/* handler not converted yet */ /* handler not converted yet */
qemu_error_new(QERR_COMMAND_NOT_FOUND, item); qerror_report(QERR_COMMAND_NOT_FOUND, item);
return -1; return -1;
} else { } else {
cmd->mhandler.info(mon); 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"); int index = qdict_get_int(qdict, "index");
if (mon_set_cpu(index) < 0) { if (mon_set_cpu(index) < 0) {
qemu_error_new(QERR_INVALID_PARAMETER, "index"); qerror_report(QERR_INVALID_PARAMETER, "index");
return -1; return -1;
} }
return 0; return 0;
@ -1013,12 +1025,12 @@ static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
if (bdrv_is_inserted(bs)) { if (bdrv_is_inserted(bs)) {
if (!force) { if (!force) {
if (!bdrv_is_removable(bs)) { if (!bdrv_is_removable(bs)) {
qemu_error_new(QERR_DEVICE_NOT_REMOVABLE, qerror_report(QERR_DEVICE_NOT_REMOVABLE,
bdrv_get_device_name(bs)); bdrv_get_device_name(bs));
return -1; return -1;
} }
if (bdrv_is_locked(bs)) { 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; return -1;
} }
} }
@ -1035,7 +1047,7 @@ static int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
bs = bdrv_find(filename); bs = bdrv_find(filename);
if (!bs) { if (!bs) {
qemu_error_new(QERR_DEVICE_NOT_FOUND, filename); qerror_report(QERR_DEVICE_NOT_FOUND, filename);
return -1; return -1;
} }
return eject_device(mon, bs, force); 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")); bs = bdrv_find(qdict_get_str(qdict, "device"));
if (!bs) { 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; return -1;
} }
if (bdrv_set_key(bs, qdict_get_str(qdict, "password")) < 0) { if (bdrv_set_key(bs, qdict_get_str(qdict, "password")) < 0) {
qemu_error_new(QERR_INVALID_PASSWORD); qerror_report(QERR_INVALID_PASSWORD);
return -1; return -1;
} }
@ -1068,13 +1080,13 @@ static int do_change_block(Monitor *mon, const char *device,
bs = bdrv_find(device); bs = bdrv_find(device);
if (!bs) { if (!bs) {
qemu_error_new(QERR_DEVICE_NOT_FOUND, device); qerror_report(QERR_DEVICE_NOT_FOUND, device);
return -1; return -1;
} }
if (fmt) { if (fmt) {
drv = bdrv_find_whitelisted_format(fmt); drv = bdrv_find_whitelisted_format(fmt);
if (!drv) { if (!drv) {
qemu_error_new(QERR_INVALID_BLOCK_FORMAT, fmt); qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt);
return -1; return -1;
} }
} }
@ -1090,7 +1102,7 @@ static int do_change_block(Monitor *mon, const char *device,
static int change_vnc_password(const char *password) static int change_vnc_password(const char *password)
{ {
if (vnc_display_password(NULL, password) < 0) { if (vnc_display_password(NULL, password) < 0) {
qemu_error_new(QERR_SET_PASSWD_FAILED); qerror_report(QERR_SET_PASSWD_FAILED);
return -1; return -1;
} }
@ -1118,7 +1130,7 @@ static int do_change_vnc(Monitor *mon, const char *target, const char *arg)
} }
} else { } else {
if (vnc_display_open(NULL, target) < 0) { if (vnc_display_open(NULL, target) < 0) {
qemu_error_new(QERR_VNC_SERVER_FAILED, target); qerror_report(QERR_VNC_SERVER_FAILED, target);
return -1; return -1;
} }
} }
@ -1490,7 +1502,7 @@ static int do_memory_save(Monitor *mon, const QDict *qdict, QObject **ret_data)
f = fopen(filename, "wb"); f = fopen(filename, "wb");
if (!f) { if (!f) {
qemu_error_new(QERR_OPEN_FILE_FAILED, filename); qerror_report(QERR_OPEN_FILE_FAILED, filename);
return -1; return -1;
} }
while (size != 0) { while (size != 0) {
@ -1526,7 +1538,7 @@ static int do_physical_memory_save(Monitor *mon, const QDict *qdict,
f = fopen(filename, "wb"); f = fopen(filename, "wb");
if (!f) { if (!f) {
qemu_error_new(QERR_OPEN_FILE_FAILED, filename); qerror_report(QERR_OPEN_FILE_FAILED, filename);
return -1; return -1;
} }
while (size != 0) { while (size != 0) {
@ -2300,13 +2312,13 @@ static int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque)
int ret; int ret;
if (kvm_enabled() && !kvm_has_sync_mmu()) { 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; return -1;
} }
ret = qemu_balloon_status(cb, opaque); ret = qemu_balloon_status(cb, opaque);
if (!ret) { if (!ret) {
qemu_error_new(QERR_DEVICE_NOT_ACTIVE, "balloon"); qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon");
return -1; return -1;
} }
@ -2322,13 +2334,13 @@ static int do_balloon(Monitor *mon, const QDict *params,
int ret; int ret;
if (kvm_enabled() && !kvm_has_sync_mmu()) { 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; return -1;
} }
ret = qemu_balloon(qdict_get_int(params, "value"), cb, opaque); ret = qemu_balloon(qdict_get_int(params, "value"), cb, opaque);
if (ret == 0) { if (ret == 0) {
qemu_error_new(QERR_DEVICE_NOT_ACTIVE, "balloon"); qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon");
return -1; 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); fd = qemu_chr_get_msgfd(mon->chr);
if (fd == -1) { if (fd == -1) {
qemu_error_new(QERR_FD_NOT_SUPPLIED); qerror_report(QERR_FD_NOT_SUPPLIED);
return -1; return -1;
} }
if (qemu_isdigit(fdname[0])) { if (qemu_isdigit(fdname[0])) {
qemu_error_new(QERR_INVALID_PARAMETER, "fdname"); qerror_report(QERR_INVALID_PARAMETER, "fdname");
return -1; return -1;
} }
fd = dup(fd); fd = dup(fd);
if (fd == -1) { if (fd == -1) {
if (errno == EMFILE) if (errno == EMFILE)
qemu_error_new(QERR_TOO_MANY_FILES); qerror_report(QERR_TOO_MANY_FILES);
else else
qemu_error_new(QERR_UNDEFINED_ERROR); qerror_report(QERR_UNDEFINED_ERROR);
return -1; return -1;
} }
@ -2522,7 +2534,7 @@ static int do_closefd(Monitor *mon, const QDict *qdict, QObject **ret_data)
return 0; return 0;
} }
qemu_error_new(QERR_FD_NOT_FOUND, fdname); qerror_report(QERR_FD_NOT_FOUND, fdname);
return -1; return -1;
} }
@ -2533,7 +2545,7 @@ static void do_loadvm(Monitor *mon, const QDict *qdict)
vm_stop(0); vm_stop(0);
if (load_vmstate(mon, name) >= 0 && saved_vm_running) if (load_vmstate(name) >= 0 && saved_vm_running)
vm_start(); vm_start();
} }
@ -3638,6 +3650,31 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
qdict_put(qdict, key, qstring_from_str(buf)); qdict_put(qdict, key, qstring_from_str(buf));
} }
break; 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 '/': case '/':
{ {
int count, format, size; int count, format, size;
@ -3857,11 +3894,16 @@ fail:
return NULL; return NULL;
} }
static void monitor_print_error(Monitor *mon) void monitor_set_error(Monitor *mon, QError *qerror)
{ {
qerror_print(mon->error); /* report only the first error */
QDECREF(mon->error); if (!mon->error) {
mon->error = NULL; 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) 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) static void handler_audit(Monitor *mon, const mon_cmd_t *cmd, int ret)
{ {
if (ret && !monitor_has_error(mon)) { if (monitor_ctrl_mode(mon)) {
/* if (ret && !monitor_has_error(mon)) {
* If it returns failure, it must have passed on error. /*
* * If it returns failure, it must have passed on error.
* Action: Report an internal error to the client if in QMP. *
*/ * Action: Report an internal error to the client if in QMP.
if (monitor_ctrl_mode(mon)) { */
qemu_error_new(QERR_UNDEFINED_ERROR); 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 #ifdef CONFIG_DEBUG_MONITOR
if (!ret && monitor_has_error(mon)) { if (!ret && monitor_has_error(mon)) {
/* /*
* If it returns success, it must not have passed an error. * If it returns success, it must not have passed an error.
* *
* Action: Report the passed error to the client. * Action: Report the passed error to the client.
*/ */
MON_DEBUG("command '%s' returned success but passed an error\n", MON_DEBUG("command '%s' returned success but passed an error\n",
cmd->name); cmd->name);
} }
if (mon_print_count_get(mon) > 0 && strcmp(cmd->name, "info") != 0) { if (mon_print_count_get(mon) > 0 && strcmp(cmd->name, "info") != 0) {
/* /*
* Handlers should not call Monitor print functions. * Handlers should not call Monitor print functions.
* *
* Action: Ignore them in QMP. * Action: Ignore them in QMP.
* *
* (XXX: we don't check any 'info' or 'query' command here * (XXX: we don't check any 'info' or 'query' command here
* because the user print function _is_ called by do_info(), hence * because the user print function _is_ called by do_info(), hence
* we will trigger this check. This problem will go away when we * we will trigger this check. This problem will go away when we
* make 'query' commands real and kill do_info()) * make 'query' commands real and kill do_info())
*/ */
MON_DEBUG("command '%s' called print functions %d time(s)\n", MON_DEBUG("command '%s' called print functions %d time(s)\n",
cmd->name, mon_print_count_get(mon)); cmd->name, mon_print_count_get(mon));
} }
#endif #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, 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) if (!cmd)
goto out; goto out;
qemu_errors_to_mon(mon);
if (monitor_handler_is_async(cmd)) { if (monitor_handler_is_async(cmd)) {
user_async_cmd_handler(mon, cmd, qdict); user_async_cmd_handler(mon, cmd, qdict);
} else if (monitor_handler_ported(cmd)) { } 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); cmd->mhandler.cmd(mon, qdict);
} }
if (monitor_has_error(mon))
monitor_print_error(mon);
qemu_errors_to_previous();
out: out:
QDECREF(qdict); QDECREF(qdict);
} }
@ -4209,7 +4248,7 @@ typedef struct CmdArgs {
static int check_opt(const CmdArgs *cmd_args, const char *name, QDict *args) static int check_opt(const CmdArgs *cmd_args, const char *name, QDict *args)
{ {
if (!cmd_args->optional) { if (!cmd_args->optional) {
qemu_error_new(QERR_MISSING_PARAMETER, name); qerror_report(QERR_MISSING_PARAMETER, name);
return -1; return -1;
} }
@ -4242,7 +4281,7 @@ static int check_arg(const CmdArgs *cmd_args, QDict *args)
case 'B': case 'B':
case 's': case 's':
if (qobject_type(value) != QTYPE_QSTRING) { 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; return -1;
} }
break; break;
@ -4253,11 +4292,11 @@ static int check_arg(const CmdArgs *cmd_args, QDict *args)
for (i = 0; keys[i]; i++) { for (i = 0; keys[i]; i++) {
QObject *obj = qdict_get(args, keys[i]); QObject *obj = qdict_get(args, keys[i]);
if (!obj) { if (!obj) {
qemu_error_new(QERR_MISSING_PARAMETER, name); qerror_report(QERR_MISSING_PARAMETER, name);
return -1; return -1;
} }
if (qobject_type(obj) != QTYPE_QINT) { 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; return -1;
} }
} }
@ -4267,21 +4306,21 @@ static int check_arg(const CmdArgs *cmd_args, QDict *args)
case 'l': case 'l':
case 'M': case 'M':
if (qobject_type(value) != QTYPE_QINT) { 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; return -1;
} }
break; break;
case 'b': case 'b':
case 'T': case 'T':
if (qobject_type(value) != QTYPE_QINT && qobject_type(value) != QTYPE_QFLOAT) { 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; return -1;
} }
break; break;
case '-': case '-':
if (qobject_type(value) != QTYPE_QINT && if (qobject_type(value) != QTYPE_QINT &&
qobject_type(value) != QTYPE_QBOOL) { qobject_type(value) != QTYPE_QBOOL) {
qemu_error_new(QERR_INVALID_PARAMETER_TYPE, name, "bool"); qerror_report(QERR_INVALID_PARAMETER_TYPE, name, "bool");
return -1; return -1;
} }
if (qobject_type(value) == QTYPE_QBOOL) { 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)))); qint_from_int(qbool_get_int(qobject_to_qbool(value))));
} }
break; break;
case 'O':
default: default:
/* impossible */ /* impossible */
abort(); abort();
@ -4304,6 +4344,12 @@ static void cmd_args_init(CmdArgs *cmd_args)
cmd_args->type = cmd_args->flag = cmd_args->optional = 0; 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 * This is not trivial, we have to parse Monitor command's argument
* type syntax to be able to check the arguments provided by clients. * 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; int err;
const char *p; const char *p;
CmdArgs cmd_args; CmdArgs cmd_args;
QemuOptsList *opts_list;
if (cmd->args_type == NULL) { if (cmd->args_type == NULL) {
return (qdict_size(args) == 0 ? 0 : -1); 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; err = 0;
cmd_args_init(&cmd_args); cmd_args_init(&cmd_args);
opts_list = NULL;
for (p = cmd->args_type;; p++) { for (p = cmd->args_type;; p++) {
if (*p == ':') { if (*p == ':') {
@ -4331,16 +4379,23 @@ static int monitor_check_qmp_args(const mon_cmd_t *cmd, QDict *args)
if (cmd_args.type == '-') { if (cmd_args.type == '-') {
cmd_args.flag = *p++; cmd_args.flag = *p++;
cmd_args.optional = 1; 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 == '?') { } else if (*p == '?') {
cmd_args.optional = 1; cmd_args.optional = 1;
p++; p++;
} }
assert(*p == ',' || *p == '\0'); assert(*p == ',' || *p == '\0');
err = check_arg(&cmd_args, args); if (opts_list) {
err = check_opts(opts_list, args);
QDECREF(cmd_args.name); opts_list = NULL;
cmd_args_init(&cmd_args); } else {
err = check_arg(&cmd_args, args);
QDECREF(cmd_args.name);
cmd_args_init(&cmd_args);
}
if (err < 0) { if (err < 0) {
break; break;
@ -4374,15 +4429,14 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
const char *cmd_name, *info_item; const char *cmd_name, *info_item;
args = NULL; args = NULL;
qemu_errors_to_mon(mon);
obj = json_parser_parse(tokens, NULL); obj = json_parser_parse(tokens, NULL);
if (!obj) { if (!obj) {
// FIXME: should be triggered in json_parser_parse() // FIXME: should be triggered in json_parser_parse()
qemu_error_new(QERR_JSON_PARSING); qerror_report(QERR_JSON_PARSING);
goto err_out; goto err_out;
} else if (qobject_type(obj) != QTYPE_QDICT) { } 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); qobject_decref(obj);
goto err_out; goto err_out;
} }
@ -4394,17 +4448,17 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
obj = qdict_get(input, "execute"); obj = qdict_get(input, "execute");
if (!obj) { if (!obj) {
qemu_error_new(QERR_QMP_BAD_INPUT_OBJECT, "execute"); qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "execute");
goto err_input; goto err_input;
} else if (qobject_type(obj) != QTYPE_QSTRING) { } 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; goto err_input;
} }
cmd_name = qstring_get_str(qobject_to_qstring(obj)); cmd_name = qstring_get_str(qobject_to_qstring(obj));
if (invalid_qmp_mode(mon, cmd_name)) { 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; goto err_input;
} }
@ -4413,7 +4467,7 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
* converted into 'query-' commands * converted into 'query-' commands
*/ */
if (compare_cmd(cmd_name, "info")) { 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; goto err_input;
} else if (strstart(cmd_name, "query-", &info_item)) { } else if (strstart(cmd_name, "query-", &info_item)) {
cmd = monitor_find_command("info"); cmd = monitor_find_command("info");
@ -4422,7 +4476,7 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
} else { } else {
cmd = monitor_find_command(cmd_name); cmd = monitor_find_command(cmd_name);
if (!cmd || !monitor_handler_ported(cmd)) { 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; goto err_input;
} }
} }
@ -4455,7 +4509,6 @@ err_out:
monitor_protocol_emitter(mon, NULL); monitor_protocol_emitter(mon, NULL);
out: out:
QDECREF(args); QDECREF(args);
qemu_errors_to_previous();
} }
/** /**
@ -4624,8 +4677,8 @@ void monitor_init(CharDriverState *chr, int flags)
} }
QLIST_INSERT_HEAD(&mon_list, mon, entry); QLIST_INSERT_HEAD(&mon_list, mon, entry);
if (!cur_mon || (flags & MONITOR_IS_DEFAULT)) if (!default_mon || (flags & MONITOR_IS_DEFAULT))
cur_mon = mon; default_mon = mon;
} }
static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque) 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)) { if (monitor_ctrl_mode(mon)) {
qemu_error_new(QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs)); qerror_report(QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs));
return -1; return -1;
} }
@ -4673,99 +4726,3 @@ int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
return err; 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;
}
}

View File

@ -3,10 +3,13 @@
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu-char.h" #include "qemu-char.h"
#include "qemu-error.h"
#include "qerror.h"
#include "qdict.h" #include "qdict.h"
#include "block.h" #include "block.h"
extern Monitor *cur_mon; extern Monitor *cur_mon;
extern Monitor *default_mon;
/* flags for monitor_init */ /* flags for monitor_init */
#define MONITOR_IS_DEFAULT 0x01 #define MONITOR_IS_DEFAULT 0x01
@ -28,6 +31,8 @@ typedef enum MonitorEvent {
QEVENT_MAX, QEVENT_MAX,
} MonitorEvent; } MonitorEvent;
int monitor_cur_is_qmp(void);
void monitor_protocol_event(MonitorEvent event, QObject *data); void monitor_protocol_event(MonitorEvent event, QObject *data);
void monitor_init(CharDriverState *chr, int flags); void monitor_init(CharDriverState *chr, int flags);
@ -48,4 +53,6 @@ void monitor_flush(Monitor *mon);
typedef void (MonitorCompletion)(void *opaque, QObject *ret_data); typedef void (MonitorCompletion)(void *opaque, QObject *ret_data);
void monitor_set_error(Monitor *mon, QError *qerror);
#endif /* !MONITOR_H */ #endif /* !MONITOR_H */

32
net.c
View File

@ -733,7 +733,7 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models,
return i; return i;
} }
qemu_error("qemu: Unsupported NIC model: %s\n", nd->model); error_report("qemu: Unsupported NIC model: %s", nd->model);
return -1; return -1;
} }
@ -744,7 +744,7 @@ int net_handle_fd_param(Monitor *mon, const char *param)
fd = monitor_get_fd(mon, param); fd = monitor_get_fd(mon, param);
if (fd == -1) { if (fd == -1) {
qemu_error("No file descriptor named %s found", param); error_report("No file descriptor named %s found", param);
return -1; return -1;
} }
@ -765,7 +765,7 @@ static int net_init_nic(QemuOpts *opts,
idx = nic_get_free_idx(); idx = nic_get_free_idx();
if (idx == -1 || nb_nics >= MAX_NICS) { if (idx == -1 || nb_nics >= MAX_NICS) {
qemu_error("Too Many NICs\n"); error_report("Too Many NICs");
return -1; return -1;
} }
@ -776,7 +776,7 @@ static int net_init_nic(QemuOpts *opts,
if ((netdev = qemu_opt_get(opts, "netdev"))) { if ((netdev = qemu_opt_get(opts, "netdev"))) {
nd->netdev = qemu_find_netdev(netdev); nd->netdev = qemu_find_netdev(netdev);
if (!nd->netdev) { if (!nd->netdev) {
qemu_error("netdev '%s' not found\n", netdev); error_report("netdev '%s' not found", netdev);
return -1; return -1;
} }
} else { } else {
@ -802,7 +802,7 @@ static int net_init_nic(QemuOpts *opts,
if (qemu_opt_get(opts, "macaddr") && if (qemu_opt_get(opts, "macaddr") &&
net_parse_macaddr(nd->macaddr, qemu_opt_get(opts, "macaddr")) < 0) { 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; return -1;
} }
@ -810,7 +810,7 @@ static int net_init_nic(QemuOpts *opts,
DEV_NVECTORS_UNSPECIFIED); DEV_NVECTORS_UNSPECIFIED);
if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
(nd->nvectors < 0 || nd->nvectors > 0x7ffffff)) { (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; return -1;
} }
@ -1060,12 +1060,12 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
if (!is_netdev) { if (!is_netdev) {
if (!type) { if (!type) {
qemu_error("No type specified for -net\n"); error_report("No type specified for -net");
return -1; return -1;
} }
} else { } else {
if (!type) { if (!type) {
qemu_error("No type specified for -netdev\n"); error_report("No type specified for -netdev");
return -1; return -1;
} }
@ -1077,21 +1077,21 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
strcmp(type, "vde") != 0 && strcmp(type, "vde") != 0 &&
#endif #endif
strcmp(type, "socket") != 0) { strcmp(type, "socket") != 0) {
qemu_error("The '%s' network backend type is not valid with -netdev\n", error_report("The '%s' network backend type is not valid with -netdev",
type); type);
return -1; return -1;
} }
if (qemu_opt_get(opts, "vlan")) { 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; return -1;
} }
if (qemu_opt_get(opts, "name")) { 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; return -1;
} }
if (!qemu_opts_id(opts)) { 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; 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; return -1;
} }
@ -1159,7 +1159,7 @@ void net_host_device_add(Monitor *mon, const QDict *qdict)
return; 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) { if (!opts) {
monitor_printf(mon, "parsing network options '%s' failed\n", monitor_printf(mon, "parsing network options '%s' failed\n",
opts_str ? opts_str : ""); opts_str ? opts_str : "");
@ -1364,7 +1364,7 @@ int net_client_parse(QemuOptsList *opts_list, const char *optarg)
} }
#endif #endif
if (!qemu_opts_parse(opts_list, optarg, "type")) { if (!qemu_opts_parse(opts_list, optarg, 1)) {
return -1; return -1;
} }

View File

@ -25,6 +25,7 @@
#include "dump.h" #include "dump.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "sysemu.h" #include "sysemu.h"
#include "qemu-error.h"
#include "qemu-log.h" #include "qemu-log.h"
typedef struct DumpState { 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); fd = open(filename, O_CREAT | O_WRONLY | O_BINARY, 0644);
if (fd < 0) { if (fd < 0) {
qemu_error("-net dump: can't open %s\n", filename); error_report("-net dump: can't open %s", filename);
return -1; return -1;
} }
@ -120,7 +121,7 @@ static int net_dump_init(VLANState *vlan, const char *device,
hdr.linktype = 1; hdr.linktype = 1;
if (write(fd, &hdr, sizeof(hdr)) < sizeof(hdr)) { 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); close(fd);
return -1; return -1;
} }

View File

@ -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, if (slirp_add_hostfwd(s->slirp, is_udp, host_addr, host_port, guest_addr,
guest_port) < 0) { guest_port) < 0) {
qemu_error("could not set up host forwarding rule '%s'\n", error_report("could not set up host forwarding rule '%s'",
redir_str); redir_str);
return -1; return -1;
} }
return 0; return 0;
fail_syntax: fail_syntax:
qemu_error("invalid host forwarding rule '%s'\n", redir_str); error_report("invalid host forwarding rule '%s'", redir_str);
return -1; return -1;
} }
@ -473,10 +473,10 @@ static void slirp_smb_cleanup(SlirpState *s)
snprintf(cmd, sizeof(cmd), "rm -rf %s", s->smb_dir); snprintf(cmd, sizeof(cmd), "rm -rf %s", s->smb_dir);
ret = system(cmd); ret = system(cmd);
if (ret == -1 || !WIFEXITED(ret)) { if (ret == -1 || !WIFEXITED(ret)) {
qemu_error("'%s' failed.\n", cmd); error_report("'%s' failed.", cmd);
} else if (WEXITSTATUS(ret)) { } else if (WEXITSTATUS(ret)) {
qemu_error("'%s' failed. Error code: %d\n", error_report("'%s' failed. Error code: %d",
cmd, WEXITSTATUS(ret)); cmd, WEXITSTATUS(ret));
} }
s->smb_dir[0] = '\0'; 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", snprintf(s->smb_dir, sizeof(s->smb_dir), "/tmp/qemu-smb.%ld-%d",
(long)getpid(), instance++); (long)getpid(), instance++);
if (mkdir(s->smb_dir, 0700) < 0) { 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; return -1;
} }
snprintf(smb_conf, sizeof(smb_conf), "%s/%s", s->smb_dir, "smb.conf"); 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"); f = fopen(smb_conf, "w");
if (!f) { if (!f) {
slirp_smb_cleanup(s); slirp_smb_cleanup(s);
qemu_error("could not create samba server configuration file '%s'\n", error_report("could not create samba server configuration file '%s'",
smb_conf); smb_conf);
return -1; return -1;
} }
fprintf(f, 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) { if (slirp_add_exec(s->slirp, 0, smb_cmdline, &vserver_addr, 139) < 0) {
slirp_smb_cleanup(s); slirp_smb_cleanup(s);
qemu_error("conflicting/invalid smbserver address\n"); error_report("conflicting/invalid smbserver address");
return -1; return -1;
} }
return 0; return 0;
@ -618,14 +618,14 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
snprintf(buf, sizeof(buf), "guestfwd.tcp:%d", port); snprintf(buf, sizeof(buf), "guestfwd.tcp:%d", port);
fwd->hd = qemu_chr_open(buf, p, NULL); fwd->hd = qemu_chr_open(buf, p, NULL);
if (!fwd->hd) { 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); qemu_free(fwd);
return -1; return -1;
} }
if (slirp_add_exec(s->slirp, 3, fwd->hd, &server, port) < 0) { if (slirp_add_exec(s->slirp, 3, fwd->hd, &server, port) < 0) {
qemu_error("conflicting/invalid host:port in guest forwarding " error_report("conflicting/invalid host:port in guest forwarding "
"rule '%s'\n", config_str); "rule '%s'", config_str);
qemu_free(fwd); qemu_free(fwd);
return -1; return -1;
} }
@ -638,7 +638,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
return 0; return 0;
fail_syntax: fail_syntax:
qemu_error("invalid guest forwarding rule '%s'\n", config_str); error_report("invalid guest forwarding rule '%s'", config_str);
return -1; return -1;
} }

View File

@ -28,9 +28,9 @@
#include "net.h" #include "net.h"
#include "qemu-char.h" #include "qemu-char.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu-error.h"
#include "qemu-option.h" #include "qemu-option.h"
#include "qemu_socket.h" #include "qemu_socket.h"
#include "sysemu.h"
typedef struct NetSocketState { typedef struct NetSocketState {
VLANClientState nc; VLANClientState nc;
@ -506,7 +506,7 @@ int net_init_socket(QemuOpts *opts,
if (qemu_opt_get(opts, "listen") || if (qemu_opt_get(opts, "listen") ||
qemu_opt_get(opts, "connect") || qemu_opt_get(opts, "connect") ||
qemu_opt_get(opts, "mcast")) { 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; return -1;
} }
@ -525,7 +525,7 @@ int net_init_socket(QemuOpts *opts,
if (qemu_opt_get(opts, "fd") || if (qemu_opt_get(opts, "fd") ||
qemu_opt_get(opts, "connect") || qemu_opt_get(opts, "connect") ||
qemu_opt_get(opts, "mcast")) { 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; return -1;
} }
@ -540,7 +540,7 @@ int net_init_socket(QemuOpts *opts,
if (qemu_opt_get(opts, "fd") || if (qemu_opt_get(opts, "fd") ||
qemu_opt_get(opts, "listen") || qemu_opt_get(opts, "listen") ||
qemu_opt_get(opts, "mcast")) { 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; return -1;
} }
@ -555,7 +555,7 @@ int net_init_socket(QemuOpts *opts,
if (qemu_opt_get(opts, "fd") || if (qemu_opt_get(opts, "fd") ||
qemu_opt_get(opts, "connect") || qemu_opt_get(opts, "connect") ||
qemu_opt_get(opts, "listen")) { 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; return -1;
} }
@ -565,7 +565,7 @@ int net_init_socket(QemuOpts *opts,
return -1; return -1;
} }
} else { } else {
qemu_error("-socket requires fd=, listen=, connect= or mcast=\n"); error_report("-socket requires fd=, listen=, connect= or mcast=");
return -1; return -1;
} }

View File

@ -69,7 +69,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
} }
} }
if (fd < 0) { 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; return -1;
} }
#else #else
@ -89,8 +90,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
*vnet_hdr = 0; *vnet_hdr = 0;
if (vnet_hdr_required && !*vnet_hdr) { if (vnet_hdr_required && !*vnet_hdr) {
qemu_error("vnet_hdr=1 requested, but no kernel " error_report("vnet_hdr=1 requested, but no kernel "
"support for IFF_VNET_HDR available"); "support for IFF_VNET_HDR available");
close(fd); close(fd);
return -1; return -1;
} }

View File

@ -31,6 +31,7 @@
#include "sysemu.h" #include "sysemu.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu-error.h"
int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required) 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) { if (vnet_hdr_required && !*vnet_hdr) {
qemu_error("vnet_hdr=1 requested, but no kernel " error_report("vnet_hdr=1 requested, but no kernel "
"support for IFF_VNET_HDR available"); "support for IFF_VNET_HDR available");
close(fd); close(fd);
return -1; 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")) { 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 -1;
} }
return 0; return 0;
@ -107,7 +108,7 @@ int tap_probe_vnet_hdr(int fd)
struct ifreq ifr; struct ifreq ifr;
if (ioctl(fd, TUNGETIFF, &ifr) != 0) { 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; return 0;
} }

View File

@ -186,8 +186,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
*vnet_hdr = 0; *vnet_hdr = 0;
if (vnet_hdr_required && !*vnet_hdr) { if (vnet_hdr_required && !*vnet_hdr) {
qemu_error("vnet_hdr=1 requested, but no kernel " error_report("vnet_hdr=1 requested, but no kernel "
"support for IFF_VNET_HDR available"); "support for IFF_VNET_HDR available");
close(fd); close(fd);
return -1; return -1;
} }

View File

@ -706,7 +706,7 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
ifname = qemu_opt_get(opts, "ifname"); ifname = qemu_opt_get(opts, "ifname");
if (!ifname) { if (!ifname) {
qemu_error("tap: no interface name\n"); error_report("tap: no interface name");
return -1; return -1;
} }

View File

@ -38,6 +38,7 @@
#include "sysemu.h" #include "sysemu.h"
#include "qemu-char.h" #include "qemu-char.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu-error.h"
#include "net/tap-linux.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, "script") ||
qemu_opt_get(opts, "downscript") || qemu_opt_get(opts, "downscript") ||
qemu_opt_get(opts, "vnet_hdr")) { 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; return -1;
} }

View File

@ -1,4 +1,5 @@
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu-error.h"
#include "qemu-option.h" #include "qemu-option.h"
#include "qemu-config.h" #include "qemu-config.h"
#include "sysemu.h" #include "sysemu.h"
@ -85,6 +86,7 @@ QemuOptsList qemu_drive_opts = {
QemuOptsList qemu_chardev_opts = { QemuOptsList qemu_chardev_opts = {
.name = "chardev", .name = "chardev",
.implied_opt_name = "backend",
.head = QTAILQ_HEAD_INITIALIZER(qemu_chardev_opts.head), .head = QTAILQ_HEAD_INITIALIZER(qemu_chardev_opts.head),
.desc = { .desc = {
{ {
@ -151,6 +153,7 @@ QemuOptsList qemu_chardev_opts = {
QemuOptsList qemu_device_opts = { QemuOptsList qemu_device_opts = {
.name = "device", .name = "device",
.implied_opt_name = "driver",
.head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head), .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
.desc = { .desc = {
/* /*
@ -164,6 +167,7 @@ QemuOptsList qemu_device_opts = {
QemuOptsList qemu_netdev_opts = { QemuOptsList qemu_netdev_opts = {
.name = "netdev", .name = "netdev",
.implied_opt_name = "type",
.head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head), .head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head),
.desc = { .desc = {
/* /*
@ -176,6 +180,7 @@ QemuOptsList qemu_netdev_opts = {
QemuOptsList qemu_net_opts = { QemuOptsList qemu_net_opts = {
.name = "net", .name = "net",
.implied_opt_name = "type",
.head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head), .head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head),
.desc = { .desc = {
/* /*
@ -226,6 +231,7 @@ QemuOptsList qemu_global_opts = {
QemuOptsList qemu_mon_opts = { QemuOptsList qemu_mon_opts = {
.name = "mon", .name = "mon",
.implied_opt_name = "chardev",
.head = QTAILQ_HEAD_INITIALIZER(qemu_mon_opts.head), .head = QTAILQ_HEAD_INITIALIZER(qemu_mon_opts.head),
.desc = { .desc = {
{ {
@ -303,7 +309,7 @@ static QemuOptsList *lists[] = {
NULL, NULL,
}; };
static QemuOptsList *find_list(const char *group) QemuOptsList *qemu_find_opts(const char *group)
{ {
int i; int i;
@ -312,7 +318,7 @@ static QemuOptsList *find_list(const char *group)
break; break;
} }
if (lists[i] == NULL) { 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]; 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); rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
if (rc < 3 || str[offset] != '=') { if (rc < 3 || str[offset] != '=') {
qemu_error("can't parse: \"%s\"\n", str); error_report("can't parse: \"%s\"", str);
return -1; return -1;
} }
list = find_list(group); list = qemu_find_opts(group);
if (list == NULL) { if (list == NULL) {
return -1; return -1;
} }
opts = qemu_opts_find(list, id); opts = qemu_opts_find(list, id);
if (!opts) { if (!opts) {
qemu_error("there is no %s \"%s\" defined\n", error_report("there is no %s \"%s\" defined",
list->name, id); list->name, id);
return -1; return -1;
} }
@ -356,7 +362,7 @@ int qemu_global_option(const char *str)
rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset); rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
if (rc < 2 || str[offset] != '=') { if (rc < 2 || str[offset] != '=') {
qemu_error("can't parse: \"%s\"\n", str); error_report("can't parse: \"%s\"", str);
return -1; 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]; char line[1024], group[64], id[64], arg[64], value[1024];
Location loc;
QemuOptsList *list = NULL; QemuOptsList *list = NULL;
QemuOpts *opts = NULL; QemuOpts *opts = NULL;
int res = -1, lno = 0;
loc_push_none(&loc);
while (fgets(line, sizeof(line), fp) != NULL) { while (fgets(line, sizeof(line), fp) != NULL) {
loc_set_file(fname, ++lno);
if (line[0] == '\n') { if (line[0] == '\n') {
/* skip empty lines */ /* skip empty lines */
continue; continue;
@ -441,35 +451,41 @@ int qemu_config_parse(FILE *fp)
} }
if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) { if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
/* group with id */ /* group with id */
list = find_list(group); list = qemu_find_opts(group);
if (list == NULL) if (list == NULL)
return -1; goto out;
opts = qemu_opts_create(list, id, 1); opts = qemu_opts_create(list, id, 1);
continue; continue;
} }
if (sscanf(line, "[%63[^]]]", group) == 1) { if (sscanf(line, "[%63[^]]]", group) == 1) {
/* group without id */ /* group without id */
list = find_list(group); list = qemu_find_opts(group);
if (list == NULL) if (list == NULL)
return -1; goto out;
opts = qemu_opts_create(list, NULL, 0); opts = qemu_opts_create(list, NULL, 0);
continue; continue;
} }
if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) { if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
/* arg = value */ /* arg = value */
if (opts == NULL) { if (opts == NULL) {
fprintf(stderr, "no group defined\n"); error_report("no group defined");
return -1; goto out;
} }
if (qemu_opt_set(opts, arg, value) != 0) { if (qemu_opt_set(opts, arg, value) != 0) {
fprintf(stderr, "failed to set \"%s\" for %s\n", error_report("failed to set \"%s\" for %s", arg, group);
arg, group); goto out;
return -1;
} }
continue; continue;
} }
fprintf(stderr, "parse error: %s\n", line); error_report("parse error");
return -1; goto out;
} }
return 0; if (ferror(fp)) {
error_report("error reading file");
goto out;
}
res = 0;
out:
loc_pop(&loc);
return res;
} }

View File

@ -11,11 +11,12 @@ extern QemuOptsList qemu_global_opts;
extern QemuOptsList qemu_mon_opts; extern QemuOptsList qemu_mon_opts;
extern QemuOptsList qemu_cpudef_opts; extern QemuOptsList qemu_cpudef_opts;
QemuOptsList *qemu_find_opts(const char *group);
int qemu_set_option(const char *str); int qemu_set_option(const char *str);
int qemu_global_option(const char *str); int qemu_global_option(const char *str);
void qemu_add_globals(void); void qemu_add_globals(void);
void qemu_config_write(FILE *fp); 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 */ #endif /* QEMU_CONFIG_H */

227
qemu-error.c Normal file
View File

@ -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);
}
}

47
qemu-error.h Normal file
View File

@ -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

View File

@ -570,10 +570,11 @@ ETEXI
{ {
.name = "device_add", .name = "device_add",
.args_type = "config:s", .args_type = "device:O",
.params = "device", .params = "driver[,prop=value][,...]",
.help = "add device, like -device on the command line", .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 STEXI

View File

@ -27,6 +27,8 @@
#include <string.h> #include <string.h>
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu-error.h"
#include "qemu-objects.h"
#include "qemu-option.h" #include "qemu-option.h"
/* /*
@ -483,6 +485,7 @@ struct QemuOpt {
struct QemuOpts { struct QemuOpts {
char *id; char *id;
QemuOptsList *list; QemuOptsList *list;
Location loc;
QTAILQ_HEAD(QemuOptHead, QemuOpt) head; QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
QTAILQ_ENTRY(QemuOpts) next; 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->id = qemu_strdup(id);
} }
opts->list = list; opts->list = list;
loc_save(&opts->loc);
QTAILQ_INIT(&opts->head); QTAILQ_INIT(&opts->head);
QTAILQ_INSERT_TAIL(&list->head, opts, next); QTAILQ_INSERT_TAIL(&list->head, opts, next);
return opts; return opts;
@ -749,12 +753,17 @@ int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname
return 0; 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; char value[1024], *id = NULL;
const char *p; const char *p;
QemuOpts *opts; QemuOpts *opts;
assert(!permit_abbrev || list->implied_opt_name);
firstname = permit_abbrev ? list->implied_opt_name : NULL;
if (strncmp(params, "id=", 3) == 0) { if (strncmp(params, "id=", 3) == 0) {
get_opt_value(value, sizeof(value), params+3); get_opt_value(value, sizeof(value), params+3);
id = qemu_strdup(value); id = qemu_strdup(value);
@ -774,6 +783,84 @@ QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, const char *fi
return opts; 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 /* Validate parsed opts against descriptions where no
* descriptions were provided in the QemuOptsList. * 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 qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
int abort_on_failure) int abort_on_failure)
{ {
Location loc;
QemuOpts *opts; QemuOpts *opts;
int rc = 0; int rc = 0;
loc_push_none(&loc);
QTAILQ_FOREACH(opts, &list->head, next) { QTAILQ_FOREACH(opts, &list->head, next) {
loc_restore(&opts->loc);
rc |= func(opts, opaque); rc |= func(opts, opaque);
if (abort_on_failure && rc != 0) if (abort_on_failure && rc != 0)
break; break;
} }
loc_pop(&loc);
return rc; return rc;
} }

View File

@ -28,6 +28,7 @@
#include <stdint.h> #include <stdint.h>
#include "qemu-queue.h" #include "qemu-queue.h"
#include "qdict.h"
enum QEMUOptionParType { enum QEMUOptionParType {
OPT_FLAG, OPT_FLAG,
@ -96,6 +97,7 @@ typedef struct QemuOptDesc {
struct QemuOptsList { struct QemuOptsList {
const char *name; const char *name;
const char *implied_opt_name;
QTAILQ_HEAD(, QemuOpts) head; QTAILQ_HEAD(, QemuOpts) head;
QemuOptDesc desc[]; QemuOptDesc desc[];
}; };
@ -117,7 +119,9 @@ const char *qemu_opts_id(QemuOpts *opts);
void qemu_opts_del(QemuOpts *opts); void qemu_opts_del(QemuOpts *opts);
int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc); int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc);
int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname); 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); typedef int (*qemu_opts_loopfunc)(QemuOpts *opts, void *opaque);
int qemu_opts_print(QemuOpts *opts, void *dummy); int qemu_opts_print(QemuOpts *opts, void *dummy);

View File

@ -13,9 +13,9 @@
#include "qemu-common.h" #include "qemu-common.h"
#include "monitor.h" #include "monitor.h"
#include "sysemu.h"
#include "qemu-timer.h" #include "qemu-timer.h"
#include "qemu-log.h" #include "qemu-log.h"
#include "qemu-error.h"
#include <sys/time.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, ...) 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; 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; va_list args;

View File

@ -12,8 +12,8 @@
#include "qjson.h" #include "qjson.h"
#include "qerror.h" #include "qerror.h"
#include "qstring.h" #include "qstring.h"
#include "sysemu.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu-error.h"
static void qerror_destroy_obj(QObject *obj); static void qerror_destroy_obj(QObject *obj);
@ -40,49 +40,69 @@ static const QType qerror_type = {
* "running out of foo: %(foo)%%" * "running out of foo: %(foo)%%"
*/ */
static const QErrorStringTable qerror_table[] = { 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, .error_fmt = QERR_COMMAND_NOT_FOUND,
.desc = "The command %(name) has not been found", .desc = "The command %(name) has not been found",
}, },
{ {
.error_fmt = QERR_DEVICE_ENCRYPTED, .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, .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, .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, .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, .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, .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, .error_fmt = QERR_FD_NOT_SUPPLIED,
.desc = "No file descriptor supplied via SCM_RIGHTS", .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, .error_fmt = QERR_INVALID_BLOCK_FORMAT,
.desc = "Invalid block format %(name)", .desc = "Invalid block format '%(name)'",
}, },
{ {
.error_fmt = QERR_INVALID_PARAMETER, .error_fmt = QERR_INVALID_PARAMETER,
.desc = "Invalid parameter %(name)", .desc = "Invalid parameter '%(name)'",
}, },
{ {
.error_fmt = QERR_INVALID_PARAMETER_TYPE, .error_fmt = QERR_INVALID_PARAMETER_TYPE,
@ -90,7 +110,7 @@ static const QErrorStringTable qerror_table[] = {
}, },
{ {
.error_fmt = QERR_INVALID_PASSWORD, .error_fmt = QERR_INVALID_PASSWORD,
.desc = "The entered password is invalid", .desc = "Password incorrect",
}, },
{ {
.error_fmt = QERR_JSON_PARSING, .error_fmt = QERR_JSON_PARSING,
@ -102,7 +122,31 @@ static const QErrorStringTable qerror_table[] = {
}, },
{ {
.error_fmt = QERR_MISSING_PARAMETER, .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, .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; QError *qerr;
qerr = qerror_new(); qerr = qerror_new();
loc_save(&qerr->loc);
qerr->linenr = linenr; qerr->linenr = linenr;
qerr->file = file; qerr->file = file;
qerr->func = func; qerr->func = func;
@ -318,13 +363,15 @@ QString *qerror_human(const QError *qerror)
* qerror_print(): Print QError data * qerror_print(): Print QError data
* *
* This function will print the member 'desc' of the specified QError object, * 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). * place (ie. stderr or Monitor's device).
*/ */
void qerror_print(const QError *qerror) void qerror_print(QError *qerror)
{ {
QString *qstring = qerror_human(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); QDECREF(qstring);
} }

View File

@ -14,6 +14,7 @@
#include "qdict.h" #include "qdict.h"
#include "qstring.h" #include "qstring.h"
#include "qemu-error.h"
#include <stdarg.h> #include <stdarg.h>
typedef struct QErrorStringTable { typedef struct QErrorStringTable {
@ -24,6 +25,7 @@ typedef struct QErrorStringTable {
typedef struct QError { typedef struct QError {
QObject_HEAD; QObject_HEAD;
QDict *error; QDict *error;
Location loc;
int linenr; int linenr;
const char *file; const char *file;
const char *func; const char *func;
@ -34,21 +36,36 @@ QError *qerror_new(void);
QError *qerror_from_info(const char *file, int linenr, const char *func, QError *qerror_from_info(const char *file, int linenr, const char *func,
const char *fmt, va_list *va); const char *fmt, va_list *va);
QString *qerror_human(const QError *qerror); 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 *qobject_to_qerror(const QObject *obj);
/* /*
* QError class list * 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 \ #define QERR_COMMAND_NOT_FOUND \
"{ 'class': 'CommandNotFound', 'data': { 'name': %s } }" "{ 'class': 'CommandNotFound', 'data': { 'name': %s } }"
#define QERR_DEVICE_ENCRYPTED \ #define QERR_DEVICE_ENCRYPTED \
"{ 'class': 'DeviceEncrypted', 'data': { 'device': %s } }" "{ '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 } }" "{ 'class': 'DeviceLocked', 'data': { 'device': %s } }"
#define QERR_DEVICE_MULTIPLE_BUSSES \
"{ 'class': 'DeviceMultipleBusses', 'data': { 'device': %s } }"
#define QERR_DEVICE_NOT_ACTIVE \ #define QERR_DEVICE_NOT_ACTIVE \
"{ 'class': 'DeviceNotActive', 'data': { 'device': %s } }" "{ 'class': 'DeviceNotActive', 'data': { 'device': %s } }"
@ -58,15 +75,15 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_DEVICE_NOT_REMOVABLE \ #define QERR_DEVICE_NOT_REMOVABLE \
"{ 'class': 'DeviceNotRemovable', 'data': { 'device': %s } }" "{ 'class': 'DeviceNotRemovable', 'data': { 'device': %s } }"
#define QERR_DEVICE_NO_BUS \
"{ 'class': 'DeviceNoBus', 'data': { 'device': %s } }"
#define QERR_FD_NOT_FOUND \ #define QERR_FD_NOT_FOUND \
"{ 'class': 'FdNotFound', 'data': { 'name': %s } }" "{ 'class': 'FdNotFound', 'data': { 'name': %s } }"
#define QERR_FD_NOT_SUPPLIED \ #define QERR_FD_NOT_SUPPLIED \
"{ 'class': 'FdNotSupplied', 'data': {} }" "{ 'class': 'FdNotSupplied', 'data': {} }"
#define QERR_OPEN_FILE_FAILED \
"{ 'class': 'OpenFileFailed', 'data': { 'filename': %s } }"
#define QERR_INVALID_BLOCK_FORMAT \ #define QERR_INVALID_BLOCK_FORMAT \
"{ 'class': 'InvalidBlockFormat', 'data': { 'name': %s } }" "{ 'class': 'InvalidBlockFormat', 'data': { 'name': %s } }"
@ -88,18 +105,36 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_MISSING_PARAMETER \ #define QERR_MISSING_PARAMETER \
"{ 'class': 'MissingParameter', 'data': { 'name': %s } }" "{ '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 \ #define QERR_QMP_BAD_INPUT_OBJECT \
"{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }" "{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }"
#define QERR_SET_PASSWD_FAILED \ #define QERR_SET_PASSWD_FAILED \
"{ 'class': 'SetPasswdFailed', 'data': {} }" "{ 'class': 'SetPasswdFailed', 'data': {} }"
#define QERR_UNDEFINED_ERROR \
"{ 'class': 'UndefinedError', 'data': {} }"
#define QERR_TOO_MANY_FILES \ #define QERR_TOO_MANY_FILES \
"{ 'class': 'TooManyFiles', 'data': {} }" "{ 'class': 'TooManyFiles', 'data': {} }"
#define QERR_UNDEFINED_ERROR \
"{ 'class': 'UndefinedError', 'data': {} }"
#define QERR_VNC_SERVER_FAILED \ #define QERR_VNC_SERVER_FAILED \
"{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }" "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }"

View File

@ -1737,7 +1737,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
vm_start(); vm_start();
} }
int load_vmstate(Monitor *mon, const char *name) int load_vmstate(const char *name)
{ {
DriveInfo *dinfo; DriveInfo *dinfo;
BlockDriverState *bs, *bs1; BlockDriverState *bs, *bs1;
@ -1747,7 +1747,7 @@ int load_vmstate(Monitor *mon, const char *name)
bs = get_bs_snapshots(); bs = get_bs_snapshots();
if (!bs) { if (!bs) {
monitor_printf(mon, "No block device supports snapshots\n"); error_report("No block device supports snapshots");
return -EINVAL; return -EINVAL;
} }
@ -1759,22 +1759,21 @@ int load_vmstate(Monitor *mon, const char *name)
if (bdrv_has_snapshot(bs1)) { if (bdrv_has_snapshot(bs1)) {
ret = bdrv_snapshot_goto(bs1, name); ret = bdrv_snapshot_goto(bs1, name);
if (ret < 0) { if (ret < 0) {
if (bs != bs1)
monitor_printf(mon, "Warning: ");
switch(ret) { switch(ret) {
case -ENOTSUP: case -ENOTSUP:
monitor_printf(mon, error_report("%sSnapshots not supported on device '%s'",
"Snapshots not supported on device '%s'\n", bs != bs1 ? "Warning: " : "",
bdrv_get_device_name(bs1)); bdrv_get_device_name(bs1));
break; break;
case -ENOENT: case -ENOENT:
monitor_printf(mon, "Could not find snapshot '%s' on " error_report("%sCould not find snapshot '%s' on device '%s'",
"device '%s'\n", bs != bs1 ? "Warning: " : "",
name, bdrv_get_device_name(bs1)); name, bdrv_get_device_name(bs1));
break; break;
default: default:
monitor_printf(mon, "Error %d while activating snapshot on" error_report("%sError %d while activating snapshot on '%s'",
" '%s'\n", ret, bdrv_get_device_name(bs1)); bs != bs1 ? "Warning: " : "",
ret, bdrv_get_device_name(bs1));
break; break;
} }
/* fatal on snapshot block device */ /* fatal on snapshot block device */
@ -1792,13 +1791,13 @@ int load_vmstate(Monitor *mon, const char *name)
/* restore the VM state */ /* restore the VM state */
f = qemu_fopen_bdrv(bs, 0); f = qemu_fopen_bdrv(bs, 0);
if (!f) { if (!f) {
monitor_printf(mon, "Could not open VM state file\n"); error_report("Could not open VM state file");
return -EINVAL; return -EINVAL;
} }
ret = qemu_loadvm_state(f); ret = qemu_loadvm_state(f);
qemu_fclose(f); qemu_fclose(f);
if (ret < 0) { 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 ret;
} }
return 0; return 0;

View File

@ -260,7 +260,7 @@ void lprint(const char *format, ...)
va_list args; va_list args;
va_start(args, format); va_start(args, format);
monitor_vprintf(cur_mon, format, args); monitor_vprintf(default_mon, format, args);
va_end(args); va_end(args);
} }

View File

@ -54,7 +54,7 @@ extern qemu_irq qemu_system_powerdown;
void qemu_system_reset(void); void qemu_system_reset(void);
void do_savevm(Monitor *mon, const QDict *qdict); 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_delvm(Monitor *mon, const QDict *qdict);
void do_info_snapshots(Monitor *mon); 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); void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f);
int qemu_loadvm_state(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 #ifdef _WIN32
/* Polling handling */ /* Polling handling */

View File

@ -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) 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; FILE *f;
int ret = 0; int ret = 0;
char filename[PATH_MAX]; 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) { if (f) {
ret = fgets(line, line_size, f) != NULL; ret = fgets(line, line_size, f) != NULL;
fclose(f); fclose(f);
#if 0
} else {
if (mon)
monitor_printf(mon, "husb: could not open %s\n", filename);
#endif
} }
return ret; return ret;

44
vl.c
View File

@ -1813,7 +1813,7 @@ QemuOpts *drive_add(const char *file, const char *fmt, ...)
vsnprintf(optstr, sizeof(optstr), fmt, ap); vsnprintf(optstr, sizeof(optstr), fmt, ap);
va_end(ap); va_end(ap);
opts = qemu_opts_parse(&qemu_drive_opts, optstr, NULL); opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0);
if (!opts) { if (!opts) {
fprintf(stderr, "%s: huh? duplicate? (%s)\n", fprintf(stderr, "%s: huh? duplicate? (%s)\n",
__FUNCTION__, optstr); __FUNCTION__, optstr);
@ -2539,7 +2539,7 @@ void do_usb_add(Monitor *mon, const QDict *qdict)
{ {
const char *devname = qdict_get_str(qdict, "devname"); const char *devname = qdict_get_str(qdict, "devname");
if (usb_device_add(devname, 1) < 0) { 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"); const char *devname = qdict_get_str(qdict, "devname");
if (usb_device_del(devname) < 0) { 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 (!strncmp(arg, "virtio", 6)) {
if (arg[6] == ',') { if (arg[6] == ',') {
/* have params -> parse them */ /* 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) if (!opts)
return -1; return -1;
} else { } else {
@ -4796,6 +4796,7 @@ static const QEMUOption *lookup_opt(int argc, char **argv,
char *r = argv[optind]; char *r = argv[optind];
const char *optarg; const char *optarg;
loc_set_cmdline(argv, optind, 1);
optind++; optind++;
/* Treat --foo the same as -foo. */ /* Treat --foo the same as -foo. */
if (r[1] == '-') if (r[1] == '-')
@ -4803,8 +4804,7 @@ static const QEMUOption *lookup_opt(int argc, char **argv,
popt = qemu_options; popt = qemu_options;
for(;;) { for(;;) {
if (!popt->name) { if (!popt->name) {
fprintf(stderr, "%s: invalid option -- '%s'\n", error_report("invalid option");
argv[0], r);
exit(1); exit(1);
} }
if (!strcmp(popt->name, r + 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 (popt->flags & HAS_ARG) {
if (optind >= argc) { if (optind >= argc) {
fprintf(stderr, "%s: option '%s' requires an argument\n", error_report("requires an argument");
argv[0], r);
exit(1); exit(1);
} }
optarg = argv[optind++]; optarg = argv[optind++];
loc_set_cmdline(argv, optind - 2, 2);
} else { } else {
optarg = NULL; optarg = NULL;
} }
@ -4862,9 +4862,10 @@ int main(int argc, char **argv, char **envp)
int show_vnc_port = 0; int show_vnc_port = 0;
int defconfig = 1; int defconfig = 1;
error_set_progname(argv[0]);
init_clocks(); init_clocks();
qemu_errors_to_file(stderr);
qemu_cache_utils_init(envp); qemu_cache_utils_init(envp);
QLIST_INIT (&vm_change_state_head); QLIST_INIT (&vm_change_state_head);
@ -4940,18 +4941,22 @@ int main(int argc, char **argv, char **envp)
} }
if (defconfig) { if (defconfig) {
const char *fname;
FILE *fp; FILE *fp;
fp = fopen(CONFIG_QEMU_CONFDIR "/qemu.conf", "r");
fname = CONFIG_QEMU_CONFDIR "/qemu.conf";
fp = fopen(fname, "r");
if (fp) { if (fp) {
if (qemu_config_parse(fp) != 0) { if (qemu_config_parse(fp, fname) != 0) {
exit(1); exit(1);
} }
fclose(fp); 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 (fp) {
if (qemu_config_parse(fp) != 0) { if (qemu_config_parse(fp, fname) != 0) {
exit(1); exit(1);
} }
fclose(fp); fclose(fp);
@ -5360,7 +5365,7 @@ int main(int argc, char **argv, char **envp)
default_monitor = 0; default_monitor = 0;
break; break;
case QEMU_OPTION_mon: case QEMU_OPTION_mon:
opts = qemu_opts_parse(&qemu_mon_opts, optarg, "chardev"); opts = qemu_opts_parse(&qemu_mon_opts, optarg, 1);
if (!opts) { if (!opts) {
fprintf(stderr, "parse error: %s\n", optarg); fprintf(stderr, "parse error: %s\n", optarg);
exit(1); exit(1);
@ -5368,7 +5373,7 @@ int main(int argc, char **argv, char **envp)
default_monitor = 0; default_monitor = 0;
break; break;
case QEMU_OPTION_chardev: case QEMU_OPTION_chardev:
opts = qemu_opts_parse(&qemu_chardev_opts, optarg, "backend"); opts = qemu_opts_parse(&qemu_chardev_opts, optarg, 1);
if (!opts) { if (!opts) {
fprintf(stderr, "parse error: %s\n", optarg); fprintf(stderr, "parse error: %s\n", optarg);
exit(1); exit(1);
@ -5471,7 +5476,7 @@ int main(int argc, char **argv, char **envp)
add_device_config(DEV_USB, optarg); add_device_config(DEV_USB, optarg);
break; break;
case QEMU_OPTION_device: case QEMU_OPTION_device:
if (!qemu_opts_parse(&qemu_device_opts, optarg, "driver")) { if (!qemu_opts_parse(&qemu_device_opts, optarg, 1)) {
exit(1); exit(1);
} }
break; break;
@ -5580,7 +5585,7 @@ int main(int argc, char **argv, char **envp)
configure_rtc_date_offset(optarg, 1); configure_rtc_date_offset(optarg, 1);
break; break;
case QEMU_OPTION_rtc: case QEMU_OPTION_rtc:
opts = qemu_opts_parse(&qemu_rtc_opts, optarg, NULL); opts = qemu_opts_parse(&qemu_rtc_opts, optarg, 0);
if (!opts) { if (!opts) {
fprintf(stderr, "parse error: %s\n", optarg); fprintf(stderr, "parse error: %s\n", optarg);
exit(1); exit(1);
@ -5641,7 +5646,7 @@ int main(int argc, char **argv, char **envp)
fprintf(stderr, "open %s: %s\n", optarg, strerror(errno)); fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
exit(1); exit(1);
} }
if (qemu_config_parse(fp) != 0) { if (qemu_config_parse(fp, optarg) != 0) {
exit(1); exit(1);
} }
fclose(fp); 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 /* If no data_dir is specified then try to find it relative to the
executable path. */ executable path. */
@ -6081,7 +6087,7 @@ int main(int argc, char **argv, char **envp)
qemu_system_reset(); qemu_system_reset();
if (loadvm) { if (loadvm) {
if (load_vmstate(cur_mon, loadvm) < 0) { if (load_vmstate(loadvm) < 0) {
autostart = 0; autostart = 0;
} }
} }

5
vnc.c
View File

@ -1046,11 +1046,10 @@ static void audio_capture(void *opaque, void *buf, int size)
static void audio_add(VncState *vs) static void audio_add(VncState *vs)
{ {
Monitor *mon = cur_mon;
struct audio_capture_ops ops; struct audio_capture_ops ops;
if (vs->audio_cap) { if (vs->audio_cap) {
monitor_printf(mon, "audio already running\n"); monitor_printf(default_mon, "audio already running\n");
return; return;
} }
@ -1060,7 +1059,7 @@ static void audio_add(VncState *vs)
vs->audio_cap = AUD_add_capture(&vs->as, &ops, vs); vs->audio_cap = AUD_add_capture(&vs->as, &ops, vs);
if (!vs->audio_cap) { if (!vs->audio_cap) {
monitor_printf(mon, "Failed to add audio capture\n"); monitor_printf(default_mon, "Failed to add audio capture\n");
} }
} }