17282a033SGerd Hoffmann #include "qemu-common.h" 21de7afc9SPaolo Bonzini #include "qemu/error-report.h" 31de7afc9SPaolo Bonzini #include "qemu/option.h" 41de7afc9SPaolo Bonzini #include "qemu/config-file.h" 5b4a42f81SPaolo Bonzini #include "qapi/qmp/qerror.h" 6d0fef6fbSGerd Hoffmann #include "hw/qdev.h" 77b1b5d19SPaolo Bonzini #include "qapi/error.h" 81f8f987dSAmos Kong #include "qmp-commands.h" 97282a033SGerd Hoffmann 104d454574SPaolo Bonzini static QemuOptsList *vm_config_groups[32]; 11968854c8SAmos Kong static QemuOptsList *drive_config_groups[4]; 12d058fe03SGerd Hoffmann 132ac20613SLuiz Capitulino static QemuOptsList *find_list(QemuOptsList **lists, const char *group, 142ac20613SLuiz Capitulino Error **errp) 15d058fe03SGerd Hoffmann { 16ddc97855SGerd Hoffmann int i; 17d058fe03SGerd Hoffmann 18d058fe03SGerd Hoffmann for (i = 0; lists[i] != NULL; i++) { 19d058fe03SGerd Hoffmann if (strcmp(lists[i]->name, group) == 0) 20d058fe03SGerd Hoffmann break; 21d058fe03SGerd Hoffmann } 22d058fe03SGerd Hoffmann if (lists[i] == NULL) { 232ac20613SLuiz Capitulino error_set(errp, QERR_INVALID_OPTION_GROUP, group); 24ddc97855SGerd Hoffmann } 25ddc97855SGerd Hoffmann return lists[i]; 26ddc97855SGerd Hoffmann } 27ddc97855SGerd Hoffmann 28490b648eSKevin Wolf QemuOptsList *qemu_find_opts(const char *group) 29490b648eSKevin Wolf { 302ac20613SLuiz Capitulino QemuOptsList *ret; 312ac20613SLuiz Capitulino Error *local_err = NULL; 322ac20613SLuiz Capitulino 332ac20613SLuiz Capitulino ret = find_list(vm_config_groups, group, &local_err); 342ac20613SLuiz Capitulino if (error_is_set(&local_err)) { 35312fd5f2SMarkus Armbruster error_report("%s", error_get_pretty(local_err)); 362ac20613SLuiz Capitulino error_free(local_err); 372ac20613SLuiz Capitulino } 382ac20613SLuiz Capitulino 392ac20613SLuiz Capitulino return ret; 40490b648eSKevin Wolf } 41490b648eSKevin Wolf 421f8f987dSAmos Kong static CommandLineParameterInfoList *query_option_descs(const QemuOptDesc *desc) 431f8f987dSAmos Kong { 441f8f987dSAmos Kong CommandLineParameterInfoList *param_list = NULL, *entry; 451f8f987dSAmos Kong CommandLineParameterInfo *info; 461f8f987dSAmos Kong int i; 471f8f987dSAmos Kong 481f8f987dSAmos Kong for (i = 0; desc[i].name != NULL; i++) { 491f8f987dSAmos Kong info = g_malloc0(sizeof(*info)); 501f8f987dSAmos Kong info->name = g_strdup(desc[i].name); 511f8f987dSAmos Kong 521f8f987dSAmos Kong switch (desc[i].type) { 531f8f987dSAmos Kong case QEMU_OPT_STRING: 541f8f987dSAmos Kong info->type = COMMAND_LINE_PARAMETER_TYPE_STRING; 551f8f987dSAmos Kong break; 561f8f987dSAmos Kong case QEMU_OPT_BOOL: 571f8f987dSAmos Kong info->type = COMMAND_LINE_PARAMETER_TYPE_BOOLEAN; 581f8f987dSAmos Kong break; 591f8f987dSAmos Kong case QEMU_OPT_NUMBER: 601f8f987dSAmos Kong info->type = COMMAND_LINE_PARAMETER_TYPE_NUMBER; 611f8f987dSAmos Kong break; 621f8f987dSAmos Kong case QEMU_OPT_SIZE: 631f8f987dSAmos Kong info->type = COMMAND_LINE_PARAMETER_TYPE_SIZE; 641f8f987dSAmos Kong break; 651f8f987dSAmos Kong } 661f8f987dSAmos Kong 671f8f987dSAmos Kong if (desc[i].help) { 681f8f987dSAmos Kong info->has_help = true; 691f8f987dSAmos Kong info->help = g_strdup(desc[i].help); 701f8f987dSAmos Kong } 711f8f987dSAmos Kong 721f8f987dSAmos Kong entry = g_malloc0(sizeof(*entry)); 731f8f987dSAmos Kong entry->value = info; 741f8f987dSAmos Kong entry->next = param_list; 751f8f987dSAmos Kong param_list = entry; 761f8f987dSAmos Kong } 771f8f987dSAmos Kong 781f8f987dSAmos Kong return param_list; 791f8f987dSAmos Kong } 801f8f987dSAmos Kong 81968854c8SAmos Kong /* remove repeated entry from the info list */ 82968854c8SAmos Kong static void cleanup_infolist(CommandLineParameterInfoList *head) 83968854c8SAmos Kong { 84968854c8SAmos Kong CommandLineParameterInfoList *pre_entry, *cur, *del_entry; 85968854c8SAmos Kong 86968854c8SAmos Kong cur = head; 87968854c8SAmos Kong while (cur->next) { 88968854c8SAmos Kong pre_entry = head; 89968854c8SAmos Kong while (pre_entry != cur->next) { 90968854c8SAmos Kong if (!strcmp(pre_entry->value->name, cur->next->value->name)) { 91968854c8SAmos Kong del_entry = cur->next; 92968854c8SAmos Kong cur->next = cur->next->next; 93968854c8SAmos Kong g_free(del_entry); 94968854c8SAmos Kong break; 95968854c8SAmos Kong } 96968854c8SAmos Kong pre_entry = pre_entry->next; 97968854c8SAmos Kong } 98968854c8SAmos Kong cur = cur->next; 99968854c8SAmos Kong } 100968854c8SAmos Kong } 101968854c8SAmos Kong 102968854c8SAmos Kong /* merge the description items of two parameter infolists */ 103968854c8SAmos Kong static void connect_infolist(CommandLineParameterInfoList *head, 104968854c8SAmos Kong CommandLineParameterInfoList *new) 105968854c8SAmos Kong { 106968854c8SAmos Kong CommandLineParameterInfoList *cur; 107968854c8SAmos Kong 108968854c8SAmos Kong cur = head; 109968854c8SAmos Kong while (cur->next) { 110968854c8SAmos Kong cur = cur->next; 111968854c8SAmos Kong } 112968854c8SAmos Kong cur->next = new; 113968854c8SAmos Kong } 114968854c8SAmos Kong 115968854c8SAmos Kong /* access all the local QemuOptsLists for drive option */ 116968854c8SAmos Kong static CommandLineParameterInfoList *get_drive_infolist(void) 117968854c8SAmos Kong { 118968854c8SAmos Kong CommandLineParameterInfoList *head = NULL, *cur; 119968854c8SAmos Kong int i; 120968854c8SAmos Kong 121968854c8SAmos Kong for (i = 0; drive_config_groups[i] != NULL; i++) { 122968854c8SAmos Kong if (!head) { 123968854c8SAmos Kong head = query_option_descs(drive_config_groups[i]->desc); 124968854c8SAmos Kong } else { 125968854c8SAmos Kong cur = query_option_descs(drive_config_groups[i]->desc); 126968854c8SAmos Kong connect_infolist(head, cur); 127968854c8SAmos Kong } 128968854c8SAmos Kong } 129968854c8SAmos Kong cleanup_infolist(head); 130968854c8SAmos Kong 131968854c8SAmos Kong return head; 132968854c8SAmos Kong } 133968854c8SAmos Kong 1341f8f987dSAmos Kong CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option, 1351f8f987dSAmos Kong const char *option, 1361f8f987dSAmos Kong Error **errp) 1371f8f987dSAmos Kong { 1381f8f987dSAmos Kong CommandLineOptionInfoList *conf_list = NULL, *entry; 1391f8f987dSAmos Kong CommandLineOptionInfo *info; 1401f8f987dSAmos Kong int i; 1411f8f987dSAmos Kong 1421f8f987dSAmos Kong for (i = 0; vm_config_groups[i] != NULL; i++) { 1431f8f987dSAmos Kong if (!has_option || !strcmp(option, vm_config_groups[i]->name)) { 1441f8f987dSAmos Kong info = g_malloc0(sizeof(*info)); 1451f8f987dSAmos Kong info->option = g_strdup(vm_config_groups[i]->name); 146968854c8SAmos Kong if (!strcmp("drive", vm_config_groups[i]->name)) { 147968854c8SAmos Kong info->parameters = get_drive_infolist(); 148968854c8SAmos Kong } else { 149968854c8SAmos Kong info->parameters = 150968854c8SAmos Kong query_option_descs(vm_config_groups[i]->desc); 151968854c8SAmos Kong } 1521f8f987dSAmos Kong entry = g_malloc0(sizeof(*entry)); 1531f8f987dSAmos Kong entry->value = info; 1541f8f987dSAmos Kong entry->next = conf_list; 1551f8f987dSAmos Kong conf_list = entry; 1561f8f987dSAmos Kong } 1571f8f987dSAmos Kong } 1581f8f987dSAmos Kong 1591f8f987dSAmos Kong if (conf_list == NULL) { 1601f8f987dSAmos Kong error_setg(errp, "invalid option name: %s", option); 1611f8f987dSAmos Kong } 1621f8f987dSAmos Kong 1631f8f987dSAmos Kong return conf_list; 1641f8f987dSAmos Kong } 1651f8f987dSAmos Kong 16660d5666fSLuiz Capitulino QemuOptsList *qemu_find_opts_err(const char *group, Error **errp) 16760d5666fSLuiz Capitulino { 16860d5666fSLuiz Capitulino return find_list(vm_config_groups, group, errp); 16960d5666fSLuiz Capitulino } 17060d5666fSLuiz Capitulino 171968854c8SAmos Kong void qemu_add_drive_opts(QemuOptsList *list) 172968854c8SAmos Kong { 173968854c8SAmos Kong int entries, i; 174968854c8SAmos Kong 175968854c8SAmos Kong entries = ARRAY_SIZE(drive_config_groups); 176968854c8SAmos Kong entries--; /* keep list NULL terminated */ 177968854c8SAmos Kong for (i = 0; i < entries; i++) { 178968854c8SAmos Kong if (drive_config_groups[i] == NULL) { 179968854c8SAmos Kong drive_config_groups[i] = list; 180968854c8SAmos Kong return; 181968854c8SAmos Kong } 182968854c8SAmos Kong } 183968854c8SAmos Kong fprintf(stderr, "ran out of space in drive_config_groups"); 184968854c8SAmos Kong abort(); 185968854c8SAmos Kong } 186968854c8SAmos Kong 187dfe795e7SGerd Hoffmann void qemu_add_opts(QemuOptsList *list) 188dfe795e7SGerd Hoffmann { 189dfe795e7SGerd Hoffmann int entries, i; 190dfe795e7SGerd Hoffmann 191dfe795e7SGerd Hoffmann entries = ARRAY_SIZE(vm_config_groups); 192dfe795e7SGerd Hoffmann entries--; /* keep list NULL terminated */ 193dfe795e7SGerd Hoffmann for (i = 0; i < entries; i++) { 194dfe795e7SGerd Hoffmann if (vm_config_groups[i] == NULL) { 195dfe795e7SGerd Hoffmann vm_config_groups[i] = list; 196dfe795e7SGerd Hoffmann return; 197dfe795e7SGerd Hoffmann } 198dfe795e7SGerd Hoffmann } 199dfe795e7SGerd Hoffmann fprintf(stderr, "ran out of space in vm_config_groups"); 200dfe795e7SGerd Hoffmann abort(); 201dfe795e7SGerd Hoffmann } 202dfe795e7SGerd Hoffmann 203ddc97855SGerd Hoffmann int qemu_set_option(const char *str) 204ddc97855SGerd Hoffmann { 205ddc97855SGerd Hoffmann char group[64], id[64], arg[64]; 206ddc97855SGerd Hoffmann QemuOptsList *list; 207ddc97855SGerd Hoffmann QemuOpts *opts; 208ddc97855SGerd Hoffmann int rc, offset; 209ddc97855SGerd Hoffmann 210ddc97855SGerd Hoffmann rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset); 211ddc97855SGerd Hoffmann if (rc < 3 || str[offset] != '=') { 2121ecda02bSMarkus Armbruster error_report("can't parse: \"%s\"", str); 213d058fe03SGerd Hoffmann return -1; 214d058fe03SGerd Hoffmann } 215d058fe03SGerd Hoffmann 216304329eeSMarkus Armbruster list = qemu_find_opts(group); 217ddc97855SGerd Hoffmann if (list == NULL) { 218ddc97855SGerd Hoffmann return -1; 219ddc97855SGerd Hoffmann } 220ddc97855SGerd Hoffmann 221ddc97855SGerd Hoffmann opts = qemu_opts_find(list, id); 222d058fe03SGerd Hoffmann if (!opts) { 2231ecda02bSMarkus Armbruster error_report("there is no %s \"%s\" defined", 224ddc97855SGerd Hoffmann list->name, id); 225d058fe03SGerd Hoffmann return -1; 226d058fe03SGerd Hoffmann } 227d058fe03SGerd Hoffmann 2283df04ac3SMark McLoughlin if (qemu_opt_set(opts, arg, str+offset+1) == -1) { 229d058fe03SGerd Hoffmann return -1; 230d058fe03SGerd Hoffmann } 231d058fe03SGerd Hoffmann return 0; 232d058fe03SGerd Hoffmann } 233d058fe03SGerd Hoffmann 2349d993394SGerd Hoffmann struct ConfigWriteData { 2359d993394SGerd Hoffmann QemuOptsList *list; 2369d993394SGerd Hoffmann FILE *fp; 2379d993394SGerd Hoffmann }; 2389d993394SGerd Hoffmann 2399d993394SGerd Hoffmann static int config_write_opt(const char *name, const char *value, void *opaque) 2409d993394SGerd Hoffmann { 2419d993394SGerd Hoffmann struct ConfigWriteData *data = opaque; 2429d993394SGerd Hoffmann 2439d993394SGerd Hoffmann fprintf(data->fp, " %s = \"%s\"\n", name, value); 2449d993394SGerd Hoffmann return 0; 2459d993394SGerd Hoffmann } 2469d993394SGerd Hoffmann 2479d993394SGerd Hoffmann static int config_write_opts(QemuOpts *opts, void *opaque) 2489d993394SGerd Hoffmann { 2499d993394SGerd Hoffmann struct ConfigWriteData *data = opaque; 2509d993394SGerd Hoffmann const char *id = qemu_opts_id(opts); 2519d993394SGerd Hoffmann 2529d993394SGerd Hoffmann if (id) { 2539d993394SGerd Hoffmann fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id); 2549d993394SGerd Hoffmann } else { 2559d993394SGerd Hoffmann fprintf(data->fp, "[%s]\n", data->list->name); 2569d993394SGerd Hoffmann } 2579d993394SGerd Hoffmann qemu_opt_foreach(opts, config_write_opt, data, 0); 2589d993394SGerd Hoffmann fprintf(data->fp, "\n"); 2599d993394SGerd Hoffmann return 0; 2609d993394SGerd Hoffmann } 2619d993394SGerd Hoffmann 2629d993394SGerd Hoffmann void qemu_config_write(FILE *fp) 2639d993394SGerd Hoffmann { 2649d993394SGerd Hoffmann struct ConfigWriteData data = { .fp = fp }; 265490b648eSKevin Wolf QemuOptsList **lists = vm_config_groups; 2669d993394SGerd Hoffmann int i; 2679d993394SGerd Hoffmann 2689d993394SGerd Hoffmann fprintf(fp, "# qemu config file\n\n"); 2699d993394SGerd Hoffmann for (i = 0; lists[i] != NULL; i++) { 2709d993394SGerd Hoffmann data.list = lists[i]; 2719d993394SGerd Hoffmann qemu_opts_foreach(data.list, config_write_opts, &data, 0); 2729d993394SGerd Hoffmann } 2739d993394SGerd Hoffmann } 27442262ba8SGerd Hoffmann 275490b648eSKevin Wolf int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname) 27642262ba8SGerd Hoffmann { 27742262ba8SGerd Hoffmann char line[1024], group[64], id[64], arg[64], value[1024]; 278cf5a65aaSMarkus Armbruster Location loc; 27942262ba8SGerd Hoffmann QemuOptsList *list = NULL; 2802ac20613SLuiz Capitulino Error *local_err = NULL; 28142262ba8SGerd Hoffmann QemuOpts *opts = NULL; 282cf5a65aaSMarkus Armbruster int res = -1, lno = 0; 28342262ba8SGerd Hoffmann 284cf5a65aaSMarkus Armbruster loc_push_none(&loc); 28542262ba8SGerd Hoffmann while (fgets(line, sizeof(line), fp) != NULL) { 286cf5a65aaSMarkus Armbruster loc_set_file(fname, ++lno); 28742262ba8SGerd Hoffmann if (line[0] == '\n') { 28842262ba8SGerd Hoffmann /* skip empty lines */ 28942262ba8SGerd Hoffmann continue; 29042262ba8SGerd Hoffmann } 29142262ba8SGerd Hoffmann if (line[0] == '#') { 29242262ba8SGerd Hoffmann /* comment */ 29342262ba8SGerd Hoffmann continue; 29442262ba8SGerd Hoffmann } 29542262ba8SGerd Hoffmann if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) { 29642262ba8SGerd Hoffmann /* group with id */ 2972ac20613SLuiz Capitulino list = find_list(lists, group, &local_err); 2982ac20613SLuiz Capitulino if (error_is_set(&local_err)) { 299312fd5f2SMarkus Armbruster error_report("%s", error_get_pretty(local_err)); 3002ac20613SLuiz Capitulino error_free(local_err); 301cf5a65aaSMarkus Armbruster goto out; 3022ac20613SLuiz Capitulino } 3038be7e7e4SLuiz Capitulino opts = qemu_opts_create(list, id, 1, NULL); 30442262ba8SGerd Hoffmann continue; 30542262ba8SGerd Hoffmann } 30642262ba8SGerd Hoffmann if (sscanf(line, "[%63[^]]]", group) == 1) { 30742262ba8SGerd Hoffmann /* group without id */ 3082ac20613SLuiz Capitulino list = find_list(lists, group, &local_err); 3092ac20613SLuiz Capitulino if (error_is_set(&local_err)) { 310312fd5f2SMarkus Armbruster error_report("%s", error_get_pretty(local_err)); 3112ac20613SLuiz Capitulino error_free(local_err); 312cf5a65aaSMarkus Armbruster goto out; 3132ac20613SLuiz Capitulino } 31487ea75d5SPeter Crosthwaite opts = qemu_opts_create(list, NULL, 0, &error_abort); 31542262ba8SGerd Hoffmann continue; 31642262ba8SGerd Hoffmann } 31742262ba8SGerd Hoffmann if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) { 31842262ba8SGerd Hoffmann /* arg = value */ 31942262ba8SGerd Hoffmann if (opts == NULL) { 320cf5a65aaSMarkus Armbruster error_report("no group defined"); 321cf5a65aaSMarkus Armbruster goto out; 32242262ba8SGerd Hoffmann } 32342262ba8SGerd Hoffmann if (qemu_opt_set(opts, arg, value) != 0) { 324cf5a65aaSMarkus Armbruster goto out; 32542262ba8SGerd Hoffmann } 32642262ba8SGerd Hoffmann continue; 32742262ba8SGerd Hoffmann } 328cf5a65aaSMarkus Armbruster error_report("parse error"); 329cf5a65aaSMarkus Armbruster goto out; 33042262ba8SGerd Hoffmann } 331ef82516dSMarkus Armbruster if (ferror(fp)) { 332ef82516dSMarkus Armbruster error_report("error reading file"); 333ef82516dSMarkus Armbruster goto out; 334ef82516dSMarkus Armbruster } 335cf5a65aaSMarkus Armbruster res = 0; 336cf5a65aaSMarkus Armbruster out: 337cf5a65aaSMarkus Armbruster loc_pop(&loc); 338cf5a65aaSMarkus Armbruster return res; 33942262ba8SGerd Hoffmann } 340dcfb0939SKevin Wolf 341dcfb0939SKevin Wolf int qemu_read_config_file(const char *filename) 342dcfb0939SKevin Wolf { 343dcfb0939SKevin Wolf FILE *f = fopen(filename, "r"); 344019e78baSKevin Wolf int ret; 345019e78baSKevin Wolf 346dcfb0939SKevin Wolf if (f == NULL) { 347dcfb0939SKevin Wolf return -errno; 348dcfb0939SKevin Wolf } 349dcfb0939SKevin Wolf 350019e78baSKevin Wolf ret = qemu_config_parse(f, vm_config_groups, filename); 351dcfb0939SKevin Wolf fclose(f); 352dcfb0939SKevin Wolf 353019e78baSKevin Wolf if (ret == 0) { 354dcfb0939SKevin Wolf return 0; 355019e78baSKevin Wolf } else { 356019e78baSKevin Wolf return -EINVAL; 357019e78baSKevin Wolf } 358dcfb0939SKevin Wolf } 359*adf5c449SMax Reitz 360*adf5c449SMax Reitz static void config_parse_qdict_section(QDict *options, QemuOptsList *opts, 361*adf5c449SMax Reitz Error **errp) 362*adf5c449SMax Reitz { 363*adf5c449SMax Reitz QemuOpts *subopts; 364*adf5c449SMax Reitz QDict *subqdict; 365*adf5c449SMax Reitz QList *list = NULL; 366*adf5c449SMax Reitz Error *local_err = NULL; 367*adf5c449SMax Reitz size_t orig_size, enum_size; 368*adf5c449SMax Reitz char *prefix; 369*adf5c449SMax Reitz 370*adf5c449SMax Reitz prefix = g_strdup_printf("%s.", opts->name); 371*adf5c449SMax Reitz qdict_extract_subqdict(options, &subqdict, prefix); 372*adf5c449SMax Reitz g_free(prefix); 373*adf5c449SMax Reitz orig_size = qdict_size(subqdict); 374*adf5c449SMax Reitz if (!orig_size) { 375*adf5c449SMax Reitz goto out; 376*adf5c449SMax Reitz } 377*adf5c449SMax Reitz 378*adf5c449SMax Reitz subopts = qemu_opts_create(opts, NULL, 0, &local_err); 379*adf5c449SMax Reitz if (error_is_set(&local_err)) { 380*adf5c449SMax Reitz error_propagate(errp, local_err); 381*adf5c449SMax Reitz goto out; 382*adf5c449SMax Reitz } 383*adf5c449SMax Reitz 384*adf5c449SMax Reitz qemu_opts_absorb_qdict(subopts, subqdict, &local_err); 385*adf5c449SMax Reitz if (error_is_set(&local_err)) { 386*adf5c449SMax Reitz error_propagate(errp, local_err); 387*adf5c449SMax Reitz goto out; 388*adf5c449SMax Reitz } 389*adf5c449SMax Reitz 390*adf5c449SMax Reitz enum_size = qdict_size(subqdict); 391*adf5c449SMax Reitz if (enum_size < orig_size && enum_size) { 392*adf5c449SMax Reitz error_setg(errp, "Unknown option '%s' for [%s]", 393*adf5c449SMax Reitz qdict_first(subqdict)->key, opts->name); 394*adf5c449SMax Reitz goto out; 395*adf5c449SMax Reitz } 396*adf5c449SMax Reitz 397*adf5c449SMax Reitz if (enum_size) { 398*adf5c449SMax Reitz /* Multiple, enumerated sections */ 399*adf5c449SMax Reitz QListEntry *list_entry; 400*adf5c449SMax Reitz unsigned i = 0; 401*adf5c449SMax Reitz 402*adf5c449SMax Reitz /* Not required anymore */ 403*adf5c449SMax Reitz qemu_opts_del(subopts); 404*adf5c449SMax Reitz 405*adf5c449SMax Reitz qdict_array_split(subqdict, &list); 406*adf5c449SMax Reitz if (qdict_size(subqdict)) { 407*adf5c449SMax Reitz error_setg(errp, "Unused option '%s' for [%s]", 408*adf5c449SMax Reitz qdict_first(subqdict)->key, opts->name); 409*adf5c449SMax Reitz goto out; 410*adf5c449SMax Reitz } 411*adf5c449SMax Reitz 412*adf5c449SMax Reitz QLIST_FOREACH_ENTRY(list, list_entry) { 413*adf5c449SMax Reitz QDict *section = qobject_to_qdict(qlist_entry_obj(list_entry)); 414*adf5c449SMax Reitz char *opt_name; 415*adf5c449SMax Reitz 416*adf5c449SMax Reitz opt_name = g_strdup_printf("%s.%u", opts->name, i++); 417*adf5c449SMax Reitz subopts = qemu_opts_create(opts, opt_name, 1, &local_err); 418*adf5c449SMax Reitz g_free(opt_name); 419*adf5c449SMax Reitz if (error_is_set(&local_err)) { 420*adf5c449SMax Reitz error_propagate(errp, local_err); 421*adf5c449SMax Reitz goto out; 422*adf5c449SMax Reitz } 423*adf5c449SMax Reitz 424*adf5c449SMax Reitz qemu_opts_absorb_qdict(subopts, section, &local_err); 425*adf5c449SMax Reitz if (error_is_set(&local_err)) { 426*adf5c449SMax Reitz error_propagate(errp, local_err); 427*adf5c449SMax Reitz qemu_opts_del(subopts); 428*adf5c449SMax Reitz goto out; 429*adf5c449SMax Reitz } 430*adf5c449SMax Reitz 431*adf5c449SMax Reitz if (qdict_size(section)) { 432*adf5c449SMax Reitz error_setg(errp, "[%s] section doesn't support the option '%s'", 433*adf5c449SMax Reitz opts->name, qdict_first(section)->key); 434*adf5c449SMax Reitz qemu_opts_del(subopts); 435*adf5c449SMax Reitz goto out; 436*adf5c449SMax Reitz } 437*adf5c449SMax Reitz } 438*adf5c449SMax Reitz } 439*adf5c449SMax Reitz 440*adf5c449SMax Reitz out: 441*adf5c449SMax Reitz QDECREF(subqdict); 442*adf5c449SMax Reitz QDECREF(list); 443*adf5c449SMax Reitz } 444*adf5c449SMax Reitz 445*adf5c449SMax Reitz void qemu_config_parse_qdict(QDict *options, QemuOptsList **lists, 446*adf5c449SMax Reitz Error **errp) 447*adf5c449SMax Reitz { 448*adf5c449SMax Reitz int i; 449*adf5c449SMax Reitz Error *local_err = NULL; 450*adf5c449SMax Reitz 451*adf5c449SMax Reitz for (i = 0; lists[i]; i++) { 452*adf5c449SMax Reitz config_parse_qdict_section(options, lists[i], &local_err); 453*adf5c449SMax Reitz if (error_is_set(&local_err)) { 454*adf5c449SMax Reitz error_propagate(errp, local_err); 455*adf5c449SMax Reitz return; 456*adf5c449SMax Reitz } 457*adf5c449SMax Reitz } 458*adf5c449SMax Reitz } 459