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) { 23f231b88dSCole Robinson error_setg(errp, "There is no option group '%s'", 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); 3484d18f06SMarkus Armbruster if (local_err) { 35565f65d2SMarkus Armbruster error_report_err(local_err); 362ac20613SLuiz Capitulino } 372ac20613SLuiz Capitulino 382ac20613SLuiz Capitulino return ret; 39490b648eSKevin Wolf } 40490b648eSKevin Wolf 41e96e5ae8SPaolo Bonzini QemuOpts *qemu_find_opts_singleton(const char *group) 42e96e5ae8SPaolo Bonzini { 43e96e5ae8SPaolo Bonzini QemuOptsList *list; 44e96e5ae8SPaolo Bonzini QemuOpts *opts; 45e96e5ae8SPaolo Bonzini 46e96e5ae8SPaolo Bonzini list = qemu_find_opts(group); 47e96e5ae8SPaolo Bonzini assert(list); 48e96e5ae8SPaolo Bonzini opts = qemu_opts_find(list, NULL); 49e96e5ae8SPaolo Bonzini if (!opts) { 50e96e5ae8SPaolo Bonzini opts = qemu_opts_create(list, NULL, 0, &error_abort); 51e96e5ae8SPaolo Bonzini } 52e96e5ae8SPaolo Bonzini return opts; 53e96e5ae8SPaolo Bonzini } 54e96e5ae8SPaolo Bonzini 551f8f987dSAmos Kong static CommandLineParameterInfoList *query_option_descs(const QemuOptDesc *desc) 561f8f987dSAmos Kong { 571f8f987dSAmos Kong CommandLineParameterInfoList *param_list = NULL, *entry; 581f8f987dSAmos Kong CommandLineParameterInfo *info; 591f8f987dSAmos Kong int i; 601f8f987dSAmos Kong 611f8f987dSAmos Kong for (i = 0; desc[i].name != NULL; i++) { 621f8f987dSAmos Kong info = g_malloc0(sizeof(*info)); 631f8f987dSAmos Kong info->name = g_strdup(desc[i].name); 641f8f987dSAmos Kong 651f8f987dSAmos Kong switch (desc[i].type) { 661f8f987dSAmos Kong case QEMU_OPT_STRING: 671f8f987dSAmos Kong info->type = COMMAND_LINE_PARAMETER_TYPE_STRING; 681f8f987dSAmos Kong break; 691f8f987dSAmos Kong case QEMU_OPT_BOOL: 701f8f987dSAmos Kong info->type = COMMAND_LINE_PARAMETER_TYPE_BOOLEAN; 711f8f987dSAmos Kong break; 721f8f987dSAmos Kong case QEMU_OPT_NUMBER: 731f8f987dSAmos Kong info->type = COMMAND_LINE_PARAMETER_TYPE_NUMBER; 741f8f987dSAmos Kong break; 751f8f987dSAmos Kong case QEMU_OPT_SIZE: 761f8f987dSAmos Kong info->type = COMMAND_LINE_PARAMETER_TYPE_SIZE; 771f8f987dSAmos Kong break; 781f8f987dSAmos Kong } 791f8f987dSAmos Kong 801f8f987dSAmos Kong if (desc[i].help) { 811f8f987dSAmos Kong info->has_help = true; 821f8f987dSAmos Kong info->help = g_strdup(desc[i].help); 831f8f987dSAmos Kong } 84e36af94fSChunyan Liu if (desc[i].def_value_str) { 85e36af94fSChunyan Liu info->has_q_default = true; 86e36af94fSChunyan Liu info->q_default = g_strdup(desc[i].def_value_str); 87e36af94fSChunyan Liu } 881f8f987dSAmos Kong 891f8f987dSAmos Kong entry = g_malloc0(sizeof(*entry)); 901f8f987dSAmos Kong entry->value = info; 911f8f987dSAmos Kong entry->next = param_list; 921f8f987dSAmos Kong param_list = entry; 931f8f987dSAmos Kong } 941f8f987dSAmos Kong 951f8f987dSAmos Kong return param_list; 961f8f987dSAmos Kong } 971f8f987dSAmos Kong 98968854c8SAmos Kong /* remove repeated entry from the info list */ 99968854c8SAmos Kong static void cleanup_infolist(CommandLineParameterInfoList *head) 100968854c8SAmos Kong { 101968854c8SAmos Kong CommandLineParameterInfoList *pre_entry, *cur, *del_entry; 102968854c8SAmos Kong 103968854c8SAmos Kong cur = head; 104968854c8SAmos Kong while (cur->next) { 105968854c8SAmos Kong pre_entry = head; 106968854c8SAmos Kong while (pre_entry != cur->next) { 107968854c8SAmos Kong if (!strcmp(pre_entry->value->name, cur->next->value->name)) { 108968854c8SAmos Kong del_entry = cur->next; 109968854c8SAmos Kong cur->next = cur->next->next; 110968854c8SAmos Kong g_free(del_entry); 111968854c8SAmos Kong break; 112968854c8SAmos Kong } 113968854c8SAmos Kong pre_entry = pre_entry->next; 114968854c8SAmos Kong } 115968854c8SAmos Kong cur = cur->next; 116968854c8SAmos Kong } 117968854c8SAmos Kong } 118968854c8SAmos Kong 119968854c8SAmos Kong /* merge the description items of two parameter infolists */ 120968854c8SAmos Kong static void connect_infolist(CommandLineParameterInfoList *head, 121968854c8SAmos Kong CommandLineParameterInfoList *new) 122968854c8SAmos Kong { 123968854c8SAmos Kong CommandLineParameterInfoList *cur; 124968854c8SAmos Kong 125968854c8SAmos Kong cur = head; 126968854c8SAmos Kong while (cur->next) { 127968854c8SAmos Kong cur = cur->next; 128968854c8SAmos Kong } 129968854c8SAmos Kong cur->next = new; 130968854c8SAmos Kong } 131968854c8SAmos Kong 132968854c8SAmos Kong /* access all the local QemuOptsLists for drive option */ 133968854c8SAmos Kong static CommandLineParameterInfoList *get_drive_infolist(void) 134968854c8SAmos Kong { 135968854c8SAmos Kong CommandLineParameterInfoList *head = NULL, *cur; 136968854c8SAmos Kong int i; 137968854c8SAmos Kong 138968854c8SAmos Kong for (i = 0; drive_config_groups[i] != NULL; i++) { 139968854c8SAmos Kong if (!head) { 140968854c8SAmos Kong head = query_option_descs(drive_config_groups[i]->desc); 141968854c8SAmos Kong } else { 142968854c8SAmos Kong cur = query_option_descs(drive_config_groups[i]->desc); 143968854c8SAmos Kong connect_infolist(head, cur); 144968854c8SAmos Kong } 145968854c8SAmos Kong } 146968854c8SAmos Kong cleanup_infolist(head); 147968854c8SAmos Kong 148968854c8SAmos Kong return head; 149968854c8SAmos Kong } 150968854c8SAmos Kong 1511f8f987dSAmos Kong CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option, 1521f8f987dSAmos Kong const char *option, 1531f8f987dSAmos Kong Error **errp) 1541f8f987dSAmos Kong { 1551f8f987dSAmos Kong CommandLineOptionInfoList *conf_list = NULL, *entry; 1561f8f987dSAmos Kong CommandLineOptionInfo *info; 1571f8f987dSAmos Kong int i; 1581f8f987dSAmos Kong 1591f8f987dSAmos Kong for (i = 0; vm_config_groups[i] != NULL; i++) { 1601f8f987dSAmos Kong if (!has_option || !strcmp(option, vm_config_groups[i]->name)) { 1611f8f987dSAmos Kong info = g_malloc0(sizeof(*info)); 1621f8f987dSAmos Kong info->option = g_strdup(vm_config_groups[i]->name); 163968854c8SAmos Kong if (!strcmp("drive", vm_config_groups[i]->name)) { 164968854c8SAmos Kong info->parameters = get_drive_infolist(); 165968854c8SAmos Kong } else { 166968854c8SAmos Kong info->parameters = 167968854c8SAmos Kong query_option_descs(vm_config_groups[i]->desc); 168968854c8SAmos Kong } 1691f8f987dSAmos Kong entry = g_malloc0(sizeof(*entry)); 1701f8f987dSAmos Kong entry->value = info; 1711f8f987dSAmos Kong entry->next = conf_list; 1721f8f987dSAmos Kong conf_list = entry; 1731f8f987dSAmos Kong } 1741f8f987dSAmos Kong } 1751f8f987dSAmos Kong 1761f8f987dSAmos Kong if (conf_list == NULL) { 1771f8f987dSAmos Kong error_setg(errp, "invalid option name: %s", option); 1781f8f987dSAmos Kong } 1791f8f987dSAmos Kong 1801f8f987dSAmos Kong return conf_list; 1811f8f987dSAmos Kong } 1821f8f987dSAmos Kong 18360d5666fSLuiz Capitulino QemuOptsList *qemu_find_opts_err(const char *group, Error **errp) 18460d5666fSLuiz Capitulino { 18560d5666fSLuiz Capitulino return find_list(vm_config_groups, group, errp); 18660d5666fSLuiz Capitulino } 18760d5666fSLuiz Capitulino 188968854c8SAmos Kong void qemu_add_drive_opts(QemuOptsList *list) 189968854c8SAmos Kong { 190968854c8SAmos Kong int entries, i; 191968854c8SAmos Kong 192968854c8SAmos Kong entries = ARRAY_SIZE(drive_config_groups); 193968854c8SAmos Kong entries--; /* keep list NULL terminated */ 194968854c8SAmos Kong for (i = 0; i < entries; i++) { 195968854c8SAmos Kong if (drive_config_groups[i] == NULL) { 196968854c8SAmos Kong drive_config_groups[i] = list; 197968854c8SAmos Kong return; 198968854c8SAmos Kong } 199968854c8SAmos Kong } 200968854c8SAmos Kong fprintf(stderr, "ran out of space in drive_config_groups"); 201968854c8SAmos Kong abort(); 202968854c8SAmos Kong } 203968854c8SAmos Kong 204dfe795e7SGerd Hoffmann void qemu_add_opts(QemuOptsList *list) 205dfe795e7SGerd Hoffmann { 206dfe795e7SGerd Hoffmann int entries, i; 207dfe795e7SGerd Hoffmann 208dfe795e7SGerd Hoffmann entries = ARRAY_SIZE(vm_config_groups); 209dfe795e7SGerd Hoffmann entries--; /* keep list NULL terminated */ 210dfe795e7SGerd Hoffmann for (i = 0; i < entries; i++) { 211dfe795e7SGerd Hoffmann if (vm_config_groups[i] == NULL) { 212dfe795e7SGerd Hoffmann vm_config_groups[i] = list; 213dfe795e7SGerd Hoffmann return; 214dfe795e7SGerd Hoffmann } 215dfe795e7SGerd Hoffmann } 216dfe795e7SGerd Hoffmann fprintf(stderr, "ran out of space in vm_config_groups"); 217dfe795e7SGerd Hoffmann abort(); 218dfe795e7SGerd Hoffmann } 219dfe795e7SGerd Hoffmann 220ddc97855SGerd Hoffmann int qemu_set_option(const char *str) 221ddc97855SGerd Hoffmann { 222*f43e47dbSMarkus Armbruster Error *local_err = NULL; 223ddc97855SGerd Hoffmann char group[64], id[64], arg[64]; 224ddc97855SGerd Hoffmann QemuOptsList *list; 225ddc97855SGerd Hoffmann QemuOpts *opts; 226ddc97855SGerd Hoffmann int rc, offset; 227ddc97855SGerd Hoffmann 228ddc97855SGerd Hoffmann rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset); 229ddc97855SGerd Hoffmann if (rc < 3 || str[offset] != '=') { 2301ecda02bSMarkus Armbruster error_report("can't parse: \"%s\"", str); 231d058fe03SGerd Hoffmann return -1; 232d058fe03SGerd Hoffmann } 233d058fe03SGerd Hoffmann 234304329eeSMarkus Armbruster list = qemu_find_opts(group); 235ddc97855SGerd Hoffmann if (list == NULL) { 236ddc97855SGerd Hoffmann return -1; 237ddc97855SGerd Hoffmann } 238ddc97855SGerd Hoffmann 239ddc97855SGerd Hoffmann opts = qemu_opts_find(list, id); 240d058fe03SGerd Hoffmann if (!opts) { 2411ecda02bSMarkus Armbruster error_report("there is no %s \"%s\" defined", 242ddc97855SGerd Hoffmann list->name, id); 243d058fe03SGerd Hoffmann return -1; 244d058fe03SGerd Hoffmann } 245d058fe03SGerd Hoffmann 246*f43e47dbSMarkus Armbruster qemu_opt_set(opts, arg, str + offset + 1, &local_err); 247*f43e47dbSMarkus Armbruster if (local_err) { 248*f43e47dbSMarkus Armbruster error_report_err(local_err); 249d058fe03SGerd Hoffmann return -1; 250d058fe03SGerd Hoffmann } 251d058fe03SGerd Hoffmann return 0; 252d058fe03SGerd Hoffmann } 253d058fe03SGerd Hoffmann 2549d993394SGerd Hoffmann struct ConfigWriteData { 2559d993394SGerd Hoffmann QemuOptsList *list; 2569d993394SGerd Hoffmann FILE *fp; 2579d993394SGerd Hoffmann }; 2589d993394SGerd Hoffmann 2599d993394SGerd Hoffmann static int config_write_opt(const char *name, const char *value, void *opaque) 2609d993394SGerd Hoffmann { 2619d993394SGerd Hoffmann struct ConfigWriteData *data = opaque; 2629d993394SGerd Hoffmann 2639d993394SGerd Hoffmann fprintf(data->fp, " %s = \"%s\"\n", name, value); 2649d993394SGerd Hoffmann return 0; 2659d993394SGerd Hoffmann } 2669d993394SGerd Hoffmann 2679d993394SGerd Hoffmann static int config_write_opts(QemuOpts *opts, void *opaque) 2689d993394SGerd Hoffmann { 2699d993394SGerd Hoffmann struct ConfigWriteData *data = opaque; 2709d993394SGerd Hoffmann const char *id = qemu_opts_id(opts); 2719d993394SGerd Hoffmann 2729d993394SGerd Hoffmann if (id) { 2739d993394SGerd Hoffmann fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id); 2749d993394SGerd Hoffmann } else { 2759d993394SGerd Hoffmann fprintf(data->fp, "[%s]\n", data->list->name); 2769d993394SGerd Hoffmann } 2779d993394SGerd Hoffmann qemu_opt_foreach(opts, config_write_opt, data, 0); 2789d993394SGerd Hoffmann fprintf(data->fp, "\n"); 2799d993394SGerd Hoffmann return 0; 2809d993394SGerd Hoffmann } 2819d993394SGerd Hoffmann 2829d993394SGerd Hoffmann void qemu_config_write(FILE *fp) 2839d993394SGerd Hoffmann { 2849d993394SGerd Hoffmann struct ConfigWriteData data = { .fp = fp }; 285490b648eSKevin Wolf QemuOptsList **lists = vm_config_groups; 2869d993394SGerd Hoffmann int i; 2879d993394SGerd Hoffmann 2889d993394SGerd Hoffmann fprintf(fp, "# qemu config file\n\n"); 2899d993394SGerd Hoffmann for (i = 0; lists[i] != NULL; i++) { 2909d993394SGerd Hoffmann data.list = lists[i]; 2919d993394SGerd Hoffmann qemu_opts_foreach(data.list, config_write_opts, &data, 0); 2929d993394SGerd Hoffmann } 2939d993394SGerd Hoffmann } 29442262ba8SGerd Hoffmann 295490b648eSKevin Wolf int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname) 29642262ba8SGerd Hoffmann { 29742262ba8SGerd Hoffmann char line[1024], group[64], id[64], arg[64], value[1024]; 298cf5a65aaSMarkus Armbruster Location loc; 29942262ba8SGerd Hoffmann QemuOptsList *list = NULL; 3002ac20613SLuiz Capitulino Error *local_err = NULL; 30142262ba8SGerd Hoffmann QemuOpts *opts = NULL; 302cf5a65aaSMarkus Armbruster int res = -1, lno = 0; 30342262ba8SGerd Hoffmann 304cf5a65aaSMarkus Armbruster loc_push_none(&loc); 30542262ba8SGerd Hoffmann while (fgets(line, sizeof(line), fp) != NULL) { 306cf5a65aaSMarkus Armbruster loc_set_file(fname, ++lno); 30742262ba8SGerd Hoffmann if (line[0] == '\n') { 30842262ba8SGerd Hoffmann /* skip empty lines */ 30942262ba8SGerd Hoffmann continue; 31042262ba8SGerd Hoffmann } 31142262ba8SGerd Hoffmann if (line[0] == '#') { 31242262ba8SGerd Hoffmann /* comment */ 31342262ba8SGerd Hoffmann continue; 31442262ba8SGerd Hoffmann } 31542262ba8SGerd Hoffmann if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) { 31642262ba8SGerd Hoffmann /* group with id */ 3172ac20613SLuiz Capitulino list = find_list(lists, group, &local_err); 31884d18f06SMarkus Armbruster if (local_err) { 319565f65d2SMarkus Armbruster error_report_err(local_err); 320cf5a65aaSMarkus Armbruster goto out; 3212ac20613SLuiz Capitulino } 3228be7e7e4SLuiz Capitulino opts = qemu_opts_create(list, id, 1, NULL); 32342262ba8SGerd Hoffmann continue; 32442262ba8SGerd Hoffmann } 32542262ba8SGerd Hoffmann if (sscanf(line, "[%63[^]]]", group) == 1) { 32642262ba8SGerd Hoffmann /* group without id */ 3272ac20613SLuiz Capitulino list = find_list(lists, group, &local_err); 32884d18f06SMarkus Armbruster if (local_err) { 329565f65d2SMarkus Armbruster error_report_err(local_err); 330cf5a65aaSMarkus Armbruster goto out; 3312ac20613SLuiz Capitulino } 33287ea75d5SPeter Crosthwaite opts = qemu_opts_create(list, NULL, 0, &error_abort); 33342262ba8SGerd Hoffmann continue; 33442262ba8SGerd Hoffmann } 33542262ba8SGerd Hoffmann if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) { 33642262ba8SGerd Hoffmann /* arg = value */ 33742262ba8SGerd Hoffmann if (opts == NULL) { 338cf5a65aaSMarkus Armbruster error_report("no group defined"); 339cf5a65aaSMarkus Armbruster goto out; 34042262ba8SGerd Hoffmann } 341*f43e47dbSMarkus Armbruster qemu_opt_set(opts, arg, value, &local_err); 342*f43e47dbSMarkus Armbruster if (local_err) { 343*f43e47dbSMarkus Armbruster error_report_err(local_err); 344cf5a65aaSMarkus Armbruster goto out; 34542262ba8SGerd Hoffmann } 34642262ba8SGerd Hoffmann continue; 34742262ba8SGerd Hoffmann } 348cf5a65aaSMarkus Armbruster error_report("parse error"); 349cf5a65aaSMarkus Armbruster goto out; 35042262ba8SGerd Hoffmann } 351ef82516dSMarkus Armbruster if (ferror(fp)) { 352ef82516dSMarkus Armbruster error_report("error reading file"); 353ef82516dSMarkus Armbruster goto out; 354ef82516dSMarkus Armbruster } 355cf5a65aaSMarkus Armbruster res = 0; 356cf5a65aaSMarkus Armbruster out: 357cf5a65aaSMarkus Armbruster loc_pop(&loc); 358cf5a65aaSMarkus Armbruster return res; 35942262ba8SGerd Hoffmann } 360dcfb0939SKevin Wolf 361dcfb0939SKevin Wolf int qemu_read_config_file(const char *filename) 362dcfb0939SKevin Wolf { 363dcfb0939SKevin Wolf FILE *f = fopen(filename, "r"); 364019e78baSKevin Wolf int ret; 365019e78baSKevin Wolf 366dcfb0939SKevin Wolf if (f == NULL) { 367dcfb0939SKevin Wolf return -errno; 368dcfb0939SKevin Wolf } 369dcfb0939SKevin Wolf 370019e78baSKevin Wolf ret = qemu_config_parse(f, vm_config_groups, filename); 371dcfb0939SKevin Wolf fclose(f); 372dcfb0939SKevin Wolf 373019e78baSKevin Wolf if (ret == 0) { 374dcfb0939SKevin Wolf return 0; 375019e78baSKevin Wolf } else { 376019e78baSKevin Wolf return -EINVAL; 377019e78baSKevin Wolf } 378dcfb0939SKevin Wolf } 379adf5c449SMax Reitz 380adf5c449SMax Reitz static void config_parse_qdict_section(QDict *options, QemuOptsList *opts, 381adf5c449SMax Reitz Error **errp) 382adf5c449SMax Reitz { 383adf5c449SMax Reitz QemuOpts *subopts; 384adf5c449SMax Reitz QDict *subqdict; 385adf5c449SMax Reitz QList *list = NULL; 386adf5c449SMax Reitz Error *local_err = NULL; 387adf5c449SMax Reitz size_t orig_size, enum_size; 388adf5c449SMax Reitz char *prefix; 389adf5c449SMax Reitz 390adf5c449SMax Reitz prefix = g_strdup_printf("%s.", opts->name); 391adf5c449SMax Reitz qdict_extract_subqdict(options, &subqdict, prefix); 392adf5c449SMax Reitz g_free(prefix); 393adf5c449SMax Reitz orig_size = qdict_size(subqdict); 394adf5c449SMax Reitz if (!orig_size) { 395adf5c449SMax Reitz goto out; 396adf5c449SMax Reitz } 397adf5c449SMax Reitz 398adf5c449SMax Reitz subopts = qemu_opts_create(opts, NULL, 0, &local_err); 39984d18f06SMarkus Armbruster if (local_err) { 400adf5c449SMax Reitz error_propagate(errp, local_err); 401adf5c449SMax Reitz goto out; 402adf5c449SMax Reitz } 403adf5c449SMax Reitz 404adf5c449SMax Reitz qemu_opts_absorb_qdict(subopts, subqdict, &local_err); 40584d18f06SMarkus Armbruster if (local_err) { 406adf5c449SMax Reitz error_propagate(errp, local_err); 407adf5c449SMax Reitz goto out; 408adf5c449SMax Reitz } 409adf5c449SMax Reitz 410adf5c449SMax Reitz enum_size = qdict_size(subqdict); 411adf5c449SMax Reitz if (enum_size < orig_size && enum_size) { 412adf5c449SMax Reitz error_setg(errp, "Unknown option '%s' for [%s]", 413adf5c449SMax Reitz qdict_first(subqdict)->key, opts->name); 414adf5c449SMax Reitz goto out; 415adf5c449SMax Reitz } 416adf5c449SMax Reitz 417adf5c449SMax Reitz if (enum_size) { 418adf5c449SMax Reitz /* Multiple, enumerated sections */ 419adf5c449SMax Reitz QListEntry *list_entry; 420adf5c449SMax Reitz unsigned i = 0; 421adf5c449SMax Reitz 422adf5c449SMax Reitz /* Not required anymore */ 423adf5c449SMax Reitz qemu_opts_del(subopts); 424adf5c449SMax Reitz 425adf5c449SMax Reitz qdict_array_split(subqdict, &list); 426adf5c449SMax Reitz if (qdict_size(subqdict)) { 427adf5c449SMax Reitz error_setg(errp, "Unused option '%s' for [%s]", 428adf5c449SMax Reitz qdict_first(subqdict)->key, opts->name); 429adf5c449SMax Reitz goto out; 430adf5c449SMax Reitz } 431adf5c449SMax Reitz 432adf5c449SMax Reitz QLIST_FOREACH_ENTRY(list, list_entry) { 433adf5c449SMax Reitz QDict *section = qobject_to_qdict(qlist_entry_obj(list_entry)); 434adf5c449SMax Reitz char *opt_name; 435adf5c449SMax Reitz 436ae39c4b2SMax Reitz if (!section) { 437ae39c4b2SMax Reitz error_setg(errp, "[%s] section (index %u) does not consist of " 438ae39c4b2SMax Reitz "keys", opts->name, i); 439ae39c4b2SMax Reitz goto out; 440ae39c4b2SMax Reitz } 441ae39c4b2SMax Reitz 442adf5c449SMax Reitz opt_name = g_strdup_printf("%s.%u", opts->name, i++); 443adf5c449SMax Reitz subopts = qemu_opts_create(opts, opt_name, 1, &local_err); 444adf5c449SMax Reitz g_free(opt_name); 44584d18f06SMarkus Armbruster if (local_err) { 446adf5c449SMax Reitz error_propagate(errp, local_err); 447adf5c449SMax Reitz goto out; 448adf5c449SMax Reitz } 449adf5c449SMax Reitz 450adf5c449SMax Reitz qemu_opts_absorb_qdict(subopts, section, &local_err); 45184d18f06SMarkus Armbruster if (local_err) { 452adf5c449SMax Reitz error_propagate(errp, local_err); 453adf5c449SMax Reitz qemu_opts_del(subopts); 454adf5c449SMax Reitz goto out; 455adf5c449SMax Reitz } 456adf5c449SMax Reitz 457adf5c449SMax Reitz if (qdict_size(section)) { 458adf5c449SMax Reitz error_setg(errp, "[%s] section doesn't support the option '%s'", 459adf5c449SMax Reitz opts->name, qdict_first(section)->key); 460adf5c449SMax Reitz qemu_opts_del(subopts); 461adf5c449SMax Reitz goto out; 462adf5c449SMax Reitz } 463adf5c449SMax Reitz } 464adf5c449SMax Reitz } 465adf5c449SMax Reitz 466adf5c449SMax Reitz out: 467adf5c449SMax Reitz QDECREF(subqdict); 468adf5c449SMax Reitz QDECREF(list); 469adf5c449SMax Reitz } 470adf5c449SMax Reitz 471adf5c449SMax Reitz void qemu_config_parse_qdict(QDict *options, QemuOptsList **lists, 472adf5c449SMax Reitz Error **errp) 473adf5c449SMax Reitz { 474adf5c449SMax Reitz int i; 475adf5c449SMax Reitz Error *local_err = NULL; 476adf5c449SMax Reitz 477adf5c449SMax Reitz for (i = 0; lists[i]; i++) { 478adf5c449SMax Reitz config_parse_qdict_section(options, lists[i], &local_err); 47984d18f06SMarkus Armbruster if (local_err) { 480adf5c449SMax Reitz error_propagate(errp, local_err); 481adf5c449SMax Reitz return; 482adf5c449SMax Reitz } 483adf5c449SMax Reitz } 484adf5c449SMax Reitz } 485