@@ -429,6 +429,7 @@ int qemu_config_parse(FILE *fp)
char line[1024], group[64], id[64], arg[64], value[1024];
QemuOptsList *list = NULL;
QemuOpts *opts = NULL;
+ char append;
while (fgets(line, sizeof(line), fp) != NULL) {
if (line[0] == '\n') {
@@ -455,13 +456,16 @@ int qemu_config_parse(FILE *fp)
opts = qemu_opts_create(list, NULL, 0);
continue;
}
- if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
- /* arg = value */
+ append = 0;
+ if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2 ||
+ (sscanf(line, " %63s += \"%1023[^\"]\"", arg, value) == 2 ?
+ append = 1 : 0)) {
+ /* arg = value, arg += value */
if (opts == NULL) {
fprintf(stderr, "no group defined\n");
return -1;
}
- if (qemu_opt_set(opts, arg, value) != 0) {
+ if (_qemu_opt_set(opts, arg, value, append) != 0) {
fprintf(stderr, "failed to set \"%s\" for %s\n",
arg, group);
return -1;
@@ -562,7 +562,11 @@ static void qemu_opt_del(QemuOpt *opt)
qemu_free(opt);
}
-int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
+/* add option *name,*value to group *opts. if append add to tail of option
+ * list, else set as sole element (overwrite any existing entries of *name).
+ */
+int _qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
+ char append)
{
QemuOpt *opt;
QemuOptDesc *desc = opts->list->desc;
@@ -582,13 +586,27 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
return -1;
}
}
-
- opt = qemu_mallocz(sizeof(*opt));
- opt->name = qemu_strdup(name);
- opt->opts = opts;
- QTAILQ_INSERT_TAIL(&opts->head, opt, next);
- if (desc[i].name != NULL) {
- opt->desc = desc+i;
+ if (append || !(opt = qemu_opt_find(opts, name))) {
+ opt = qemu_mallocz(sizeof(*opt));
+ opt->name = qemu_strdup(name);
+ opt->opts = opts;
+ QTAILQ_INSERT_TAIL(&opts->head, opt, next);
+ if (desc[i].name != NULL) {
+ opt->desc = desc+i;
+ }
+ } else if (!append) {
+ QemuOpt *p, *next;
+
+ /* assign to reclaimed *opt, remove all other *name defs */
+ QTAILQ_FOREACH_SAFE(p, &opts->head, next, next) {
+ if (p != opt && !strcmp(name, p->name)) {
+ qemu_free((char *)p->str);
+ QTAILQ_REMOVE(&opts->head, p, next);
+ qemu_free((char *)p);
+ }
+ }
+ qemu_free((char *)opt->str);
+ opt->str = NULL;
}
if (value) {
opt->str = qemu_strdup(value);
@@ -104,7 +104,14 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name);
int qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval);
uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval);
uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
-int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
+int _qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
+ char append);
+static inline int qemu_opt_set(QemuOpts *opts, const char *name,
+ const char *value)
+{
+ return (_qemu_opt_set(opts, name, value, 0));
+}
+
typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaque);
int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
int abort_on_failure);