diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index e23b322937383b9b59e1eb4aa647fb4ea709e2eb..1a8b4aabb254e77b0549c77a5e20b1619fdacf1f 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -4771,11 +4771,11 @@ static const char *qemuFindEnv(const char **progenv, * the "=value" part is optional and if a key with no value is found, * NULL is be placed into corresponding place in retvalues. */ -static int -qemuParseCommandLineKeywords(const char *str, - char ***retkeywords, - char ***retvalues, - int allowEmptyValue) +int +qemuParseKeywords(const char *str, + char ***retkeywords, + char ***retvalues, + int allowEmptyValue) { int keywordCount = 0; int keywordAlloc = 0; @@ -4874,9 +4874,9 @@ qemuParseCommandLineDisk(const char *val, int busid = -1; int unitid = -1; - if ((nkeywords = qemuParseCommandLineKeywords(val, - &keywords, - &values, 0)) < 0) + if ((nkeywords = qemuParseKeywords(val, + &keywords, + &values, 0)) < 0) return NULL; if (VIR_ALLOC(def) < 0) { @@ -5114,9 +5114,9 @@ qemuParseCommandLineNet(virCapsPtr caps, tmp = strchr(val, ','); if (tmp) { - if ((nkeywords = qemuParseCommandLineKeywords(tmp+1, - &keywords, - &values, 0)) < 0) + if ((nkeywords = qemuParseKeywords(tmp+1, + &keywords, + &values, 0)) < 0) return NULL; } else { nkeywords = 0; @@ -5186,9 +5186,9 @@ qemuParseCommandLineNet(virCapsPtr caps, VIR_FREE(values); if (STRPREFIX(nic, "nic,")) { - if ((nkeywords = qemuParseCommandLineKeywords(nic + strlen("nic,"), - &keywords, - &values, 0)) < 0) { + if ((nkeywords = qemuParseKeywords(nic + strlen("nic,"), + &keywords, + &values, 0)) < 0) { virDomainNetDefFree(def); def = NULL; goto cleanup; @@ -5596,7 +5596,7 @@ qemuParseCommandLineSmp(virDomainDefPtr dom, char *end; int ret; - nkws = qemuParseCommandLineKeywords(val, &kws, &vals, 1); + nkws = qemuParseKeywords(val, &kws, &vals, 1); if (nkws < 0) return -1; diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index e0666cb313f92116904ce423ddd725db063e0822..574709eb07a7ec97824463054244359835bc6f93 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -311,5 +311,11 @@ int qemuAssignDeviceDiskAlias(virDomainDiskDefPtr def, unsigned long long qemuCm int qemuAssignDeviceHostdevAlias(virDomainDefPtr def, virDomainHostdevDefPtr net, int idx); int qemuAssignDeviceControllerAlias(virDomainControllerDefPtr controller); +int +qemuParseKeywords(const char *str, + char ***retkeywords, + char ***retvalues, + int allowEmptyValue); + #endif /* __QEMUD_CONF_H */ diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index f5c73f724ec36faeaaa3d39d1aa030c1add2103d..de59b2b9ee636166bda4baad4e67046595cf2ad7 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -1961,24 +1961,94 @@ int qemuMonitorJSONDelDevice(qemuMonitorPtr mon, } +static void +qemuFreeKeywords(int nkeywords, char **keywords, char **values) +{ + int i; + for (i = 0 ; i < nkeywords ; i++) { + VIR_FREE(keywords[i]); + VIR_FREE(values[i]); + } + VIR_FREE(keywords); + VIR_FREE(values); +} + +static virJSONValuePtr +qemuMonitorJSONKeywordStringToJSON(const char *str, const char *firstkeyword) +{ + virJSONValuePtr ret = NULL; + char **keywords = NULL; + char **values = NULL; + int nkeywords = 0; + int i; + + if (!(ret = virJSONValueNewObject())) + goto no_memory; + + nkeywords = qemuParseKeywords(str, &keywords, &values, 1); + + if (nkeywords < 0) + goto error; + + for (i = 0 ; i < nkeywords ; i++) { + if (values[i] == NULL) { + if (i != 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected empty keyword in %s"), str); + goto error; + } else { + /* This 3rd arg isn't a typo - the way the parser works is + * that the value ended up in the keyword field */ + if (virJSONValueObjectAppendString(ret, firstkeyword, keywords[i]) < 0) + goto no_memory; + } + } else { + if (virJSONValueObjectAppendString(ret, keywords[i], values[i]) < 0) + goto no_memory; + } + } + + qemuFreeKeywords(nkeywords, keywords, values); + return ret; + +no_memory: + virReportOOMError(); +error: + qemuFreeKeywords(nkeywords, keywords, values); + virJSONValueFree(ret); + return NULL; +} + + int qemuMonitorJSONAddDevice(qemuMonitorPtr mon, const char *devicestr) { - int ret; + int ret = -1; virJSONValuePtr cmd; virJSONValuePtr reply = NULL; + virJSONValuePtr args; - cmd = qemuMonitorJSONMakeCommand("device_add", - "s:config", devicestr, - NULL); + cmd = qemuMonitorJSONMakeCommand("device_add", NULL); if (!cmd) return -1; + args = qemuMonitorJSONKeywordStringToJSON(devicestr, "driver"); + if (!args) + goto cleanup; + + if (virJSONValueObjectAppend(cmd, "arguments", args) < 0) { + virReportOOMError(); + goto cleanup; + } + args = NULL; /* obj owns reference to args now */ + ret = qemuMonitorJSONCommand(mon, cmd, &reply); if (ret == 0) ret = qemuMonitorJSONCheckError(cmd, reply); +cleanup: + virJSONValueFree(args); virJSONValueFree(cmd); virJSONValueFree(reply); return ret;