1 #include "qemu-common.h" 2 #include "qemu/error-report.h" 3 #include "qemu/option.h" 4 #include "qemu/config-file.h" 5 #include "qapi/qmp/qerror.h" 6 #include "hw/qdev.h" 7 #include "qapi/error.h" 8 #include "qmp-commands.h" 9 10 static QemuOptsList *vm_config_groups[32]; 11 static QemuOptsList *drive_config_groups[4]; 12 13 static QemuOptsList *find_list(QemuOptsList **lists, const char *group, 14 Error **errp) 15 { 16 int i; 17 18 for (i = 0; lists[i] != NULL; i++) { 19 if (strcmp(lists[i]->name, group) == 0) 20 break; 21 } 22 if (lists[i] == NULL) { 23 error_setg(errp, "There is no option group '%s'", group); 24 } 25 return lists[i]; 26 } 27 28 QemuOptsList *qemu_find_opts(const char *group) 29 { 30 QemuOptsList *ret; 31 Error *local_err = NULL; 32 33 ret = find_list(vm_config_groups, group, &local_err); 34 if (local_err) { 35 error_report("%s", error_get_pretty(local_err)); 36 error_free(local_err); 37 } 38 39 return ret; 40 } 41 42 QemuOpts *qemu_find_opts_singleton(const char *group) 43 { 44 QemuOptsList *list; 45 QemuOpts *opts; 46 47 list = qemu_find_opts(group); 48 assert(list); 49 opts = qemu_opts_find(list, NULL); 50 if (!opts) { 51 opts = qemu_opts_create(list, NULL, 0, &error_abort); 52 } 53 return opts; 54 } 55 56 static CommandLineParameterInfoList *query_option_descs(const QemuOptDesc *desc) 57 { 58 CommandLineParameterInfoList *param_list = NULL, *entry; 59 CommandLineParameterInfo *info; 60 int i; 61 62 for (i = 0; desc[i].name != NULL; i++) { 63 info = g_malloc0(sizeof(*info)); 64 info->name = g_strdup(desc[i].name); 65 66 switch (desc[i].type) { 67 case QEMU_OPT_STRING: 68 info->type = COMMAND_LINE_PARAMETER_TYPE_STRING; 69 break; 70 case QEMU_OPT_BOOL: 71 info->type = COMMAND_LINE_PARAMETER_TYPE_BOOLEAN; 72 break; 73 case QEMU_OPT_NUMBER: 74 info->type = COMMAND_LINE_PARAMETER_TYPE_NUMBER; 75 break; 76 case QEMU_OPT_SIZE: 77 info->type = COMMAND_LINE_PARAMETER_TYPE_SIZE; 78 break; 79 } 80 81 if (desc[i].help) { 82 info->has_help = true; 83 info->help = g_strdup(desc[i].help); 84 } 85 if (desc[i].def_value_str) { 86 info->has_q_default = true; 87 info->q_default = g_strdup(desc[i].def_value_str); 88 } 89 90 entry = g_malloc0(sizeof(*entry)); 91 entry->value = info; 92 entry->next = param_list; 93 param_list = entry; 94 } 95 96 return param_list; 97 } 98 99 /* remove repeated entry from the info list */ 100 static void cleanup_infolist(CommandLineParameterInfoList *head) 101 { 102 CommandLineParameterInfoList *pre_entry, *cur, *del_entry; 103 104 cur = head; 105 while (cur->next) { 106 pre_entry = head; 107 while (pre_entry != cur->next) { 108 if (!strcmp(pre_entry->value->name, cur->next->value->name)) { 109 del_entry = cur->next; 110 cur->next = cur->next->next; 111 g_free(del_entry); 112 break; 113 } 114 pre_entry = pre_entry->next; 115 } 116 cur = cur->next; 117 } 118 } 119 120 /* merge the description items of two parameter infolists */ 121 static void connect_infolist(CommandLineParameterInfoList *head, 122 CommandLineParameterInfoList *new) 123 { 124 CommandLineParameterInfoList *cur; 125 126 cur = head; 127 while (cur->next) { 128 cur = cur->next; 129 } 130 cur->next = new; 131 } 132 133 /* access all the local QemuOptsLists for drive option */ 134 static CommandLineParameterInfoList *get_drive_infolist(void) 135 { 136 CommandLineParameterInfoList *head = NULL, *cur; 137 int i; 138 139 for (i = 0; drive_config_groups[i] != NULL; i++) { 140 if (!head) { 141 head = query_option_descs(drive_config_groups[i]->desc); 142 } else { 143 cur = query_option_descs(drive_config_groups[i]->desc); 144 connect_infolist(head, cur); 145 } 146 } 147 cleanup_infolist(head); 148 149 return head; 150 } 151 152 CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option, 153 const char *option, 154 Error **errp) 155 { 156 CommandLineOptionInfoList *conf_list = NULL, *entry; 157 CommandLineOptionInfo *info; 158 int i; 159 160 for (i = 0; vm_config_groups[i] != NULL; i++) { 161 if (!has_option || !strcmp(option, vm_config_groups[i]->name)) { 162 info = g_malloc0(sizeof(*info)); 163 info->option = g_strdup(vm_config_groups[i]->name); 164 if (!strcmp("drive", vm_config_groups[i]->name)) { 165 info->parameters = get_drive_infolist(); 166 } else { 167 info->parameters = 168 query_option_descs(vm_config_groups[i]->desc); 169 } 170 entry = g_malloc0(sizeof(*entry)); 171 entry->value = info; 172 entry->next = conf_list; 173 conf_list = entry; 174 } 175 } 176 177 if (conf_list == NULL) { 178 error_setg(errp, "invalid option name: %s", option); 179 } 180 181 return conf_list; 182 } 183 184 QemuOptsList *qemu_find_opts_err(const char *group, Error **errp) 185 { 186 return find_list(vm_config_groups, group, errp); 187 } 188 189 void qemu_add_drive_opts(QemuOptsList *list) 190 { 191 int entries, i; 192 193 entries = ARRAY_SIZE(drive_config_groups); 194 entries--; /* keep list NULL terminated */ 195 for (i = 0; i < entries; i++) { 196 if (drive_config_groups[i] == NULL) { 197 drive_config_groups[i] = list; 198 return; 199 } 200 } 201 fprintf(stderr, "ran out of space in drive_config_groups"); 202 abort(); 203 } 204 205 void qemu_add_opts(QemuOptsList *list) 206 { 207 int entries, i; 208 209 entries = ARRAY_SIZE(vm_config_groups); 210 entries--; /* keep list NULL terminated */ 211 for (i = 0; i < entries; i++) { 212 if (vm_config_groups[i] == NULL) { 213 vm_config_groups[i] = list; 214 return; 215 } 216 } 217 fprintf(stderr, "ran out of space in vm_config_groups"); 218 abort(); 219 } 220 221 int qemu_set_option(const char *str) 222 { 223 char group[64], id[64], arg[64]; 224 QemuOptsList *list; 225 QemuOpts *opts; 226 int rc, offset; 227 228 rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset); 229 if (rc < 3 || str[offset] != '=') { 230 error_report("can't parse: \"%s\"", str); 231 return -1; 232 } 233 234 list = qemu_find_opts(group); 235 if (list == NULL) { 236 return -1; 237 } 238 239 opts = qemu_opts_find(list, id); 240 if (!opts) { 241 error_report("there is no %s \"%s\" defined", 242 list->name, id); 243 return -1; 244 } 245 246 if (qemu_opt_set(opts, arg, str+offset+1) == -1) { 247 return -1; 248 } 249 return 0; 250 } 251 252 struct ConfigWriteData { 253 QemuOptsList *list; 254 FILE *fp; 255 }; 256 257 static int config_write_opt(const char *name, const char *value, void *opaque) 258 { 259 struct ConfigWriteData *data = opaque; 260 261 fprintf(data->fp, " %s = \"%s\"\n", name, value); 262 return 0; 263 } 264 265 static int config_write_opts(QemuOpts *opts, void *opaque) 266 { 267 struct ConfigWriteData *data = opaque; 268 const char *id = qemu_opts_id(opts); 269 270 if (id) { 271 fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id); 272 } else { 273 fprintf(data->fp, "[%s]\n", data->list->name); 274 } 275 qemu_opt_foreach(opts, config_write_opt, data, 0); 276 fprintf(data->fp, "\n"); 277 return 0; 278 } 279 280 void qemu_config_write(FILE *fp) 281 { 282 struct ConfigWriteData data = { .fp = fp }; 283 QemuOptsList **lists = vm_config_groups; 284 int i; 285 286 fprintf(fp, "# qemu config file\n\n"); 287 for (i = 0; lists[i] != NULL; i++) { 288 data.list = lists[i]; 289 qemu_opts_foreach(data.list, config_write_opts, &data, 0); 290 } 291 } 292 293 int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname) 294 { 295 char line[1024], group[64], id[64], arg[64], value[1024]; 296 Location loc; 297 QemuOptsList *list = NULL; 298 Error *local_err = NULL; 299 QemuOpts *opts = NULL; 300 int res = -1, lno = 0; 301 302 loc_push_none(&loc); 303 while (fgets(line, sizeof(line), fp) != NULL) { 304 loc_set_file(fname, ++lno); 305 if (line[0] == '\n') { 306 /* skip empty lines */ 307 continue; 308 } 309 if (line[0] == '#') { 310 /* comment */ 311 continue; 312 } 313 if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) { 314 /* group with id */ 315 list = find_list(lists, group, &local_err); 316 if (local_err) { 317 error_report("%s", error_get_pretty(local_err)); 318 error_free(local_err); 319 goto out; 320 } 321 opts = qemu_opts_create(list, id, 1, NULL); 322 continue; 323 } 324 if (sscanf(line, "[%63[^]]]", group) == 1) { 325 /* group without id */ 326 list = find_list(lists, group, &local_err); 327 if (local_err) { 328 error_report("%s", error_get_pretty(local_err)); 329 error_free(local_err); 330 goto out; 331 } 332 opts = qemu_opts_create(list, NULL, 0, &error_abort); 333 continue; 334 } 335 if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) { 336 /* arg = value */ 337 if (opts == NULL) { 338 error_report("no group defined"); 339 goto out; 340 } 341 if (qemu_opt_set(opts, arg, value) != 0) { 342 goto out; 343 } 344 continue; 345 } 346 error_report("parse error"); 347 goto out; 348 } 349 if (ferror(fp)) { 350 error_report("error reading file"); 351 goto out; 352 } 353 res = 0; 354 out: 355 loc_pop(&loc); 356 return res; 357 } 358 359 int qemu_read_config_file(const char *filename) 360 { 361 FILE *f = fopen(filename, "r"); 362 int ret; 363 364 if (f == NULL) { 365 return -errno; 366 } 367 368 ret = qemu_config_parse(f, vm_config_groups, filename); 369 fclose(f); 370 371 if (ret == 0) { 372 return 0; 373 } else { 374 return -EINVAL; 375 } 376 } 377 378 static void config_parse_qdict_section(QDict *options, QemuOptsList *opts, 379 Error **errp) 380 { 381 QemuOpts *subopts; 382 QDict *subqdict; 383 QList *list = NULL; 384 Error *local_err = NULL; 385 size_t orig_size, enum_size; 386 char *prefix; 387 388 prefix = g_strdup_printf("%s.", opts->name); 389 qdict_extract_subqdict(options, &subqdict, prefix); 390 g_free(prefix); 391 orig_size = qdict_size(subqdict); 392 if (!orig_size) { 393 goto out; 394 } 395 396 subopts = qemu_opts_create(opts, NULL, 0, &local_err); 397 if (local_err) { 398 error_propagate(errp, local_err); 399 goto out; 400 } 401 402 qemu_opts_absorb_qdict(subopts, subqdict, &local_err); 403 if (local_err) { 404 error_propagate(errp, local_err); 405 goto out; 406 } 407 408 enum_size = qdict_size(subqdict); 409 if (enum_size < orig_size && enum_size) { 410 error_setg(errp, "Unknown option '%s' for [%s]", 411 qdict_first(subqdict)->key, opts->name); 412 goto out; 413 } 414 415 if (enum_size) { 416 /* Multiple, enumerated sections */ 417 QListEntry *list_entry; 418 unsigned i = 0; 419 420 /* Not required anymore */ 421 qemu_opts_del(subopts); 422 423 qdict_array_split(subqdict, &list); 424 if (qdict_size(subqdict)) { 425 error_setg(errp, "Unused option '%s' for [%s]", 426 qdict_first(subqdict)->key, opts->name); 427 goto out; 428 } 429 430 QLIST_FOREACH_ENTRY(list, list_entry) { 431 QDict *section = qobject_to_qdict(qlist_entry_obj(list_entry)); 432 char *opt_name; 433 434 if (!section) { 435 error_setg(errp, "[%s] section (index %u) does not consist of " 436 "keys", opts->name, i); 437 goto out; 438 } 439 440 opt_name = g_strdup_printf("%s.%u", opts->name, i++); 441 subopts = qemu_opts_create(opts, opt_name, 1, &local_err); 442 g_free(opt_name); 443 if (local_err) { 444 error_propagate(errp, local_err); 445 goto out; 446 } 447 448 qemu_opts_absorb_qdict(subopts, section, &local_err); 449 if (local_err) { 450 error_propagate(errp, local_err); 451 qemu_opts_del(subopts); 452 goto out; 453 } 454 455 if (qdict_size(section)) { 456 error_setg(errp, "[%s] section doesn't support the option '%s'", 457 opts->name, qdict_first(section)->key); 458 qemu_opts_del(subopts); 459 goto out; 460 } 461 } 462 } 463 464 out: 465 QDECREF(subqdict); 466 QDECREF(list); 467 } 468 469 void qemu_config_parse_qdict(QDict *options, QemuOptsList **lists, 470 Error **errp) 471 { 472 int i; 473 Error *local_err = NULL; 474 475 for (i = 0; lists[i]; i++) { 476 config_parse_qdict_section(options, lists[i], &local_err); 477 if (local_err) { 478 error_propagate(errp, local_err); 479 return; 480 } 481 } 482 } 483