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 12 static QemuOptsList *find_list(QemuOptsList **lists, const char *group, 13 Error **errp) 14 { 15 int i; 16 17 for (i = 0; lists[i] != NULL; i++) { 18 if (strcmp(lists[i]->name, group) == 0) 19 break; 20 } 21 if (lists[i] == NULL) { 22 error_set(errp, QERR_INVALID_OPTION_GROUP, group); 23 } 24 return lists[i]; 25 } 26 27 QemuOptsList *qemu_find_opts(const char *group) 28 { 29 QemuOptsList *ret; 30 Error *local_err = NULL; 31 32 ret = find_list(vm_config_groups, group, &local_err); 33 if (error_is_set(&local_err)) { 34 error_report("%s", error_get_pretty(local_err)); 35 error_free(local_err); 36 } 37 38 return ret; 39 } 40 41 static CommandLineParameterInfoList *query_option_descs(const QemuOptDesc *desc) 42 { 43 CommandLineParameterInfoList *param_list = NULL, *entry; 44 CommandLineParameterInfo *info; 45 int i; 46 47 for (i = 0; desc[i].name != NULL; i++) { 48 info = g_malloc0(sizeof(*info)); 49 info->name = g_strdup(desc[i].name); 50 51 switch (desc[i].type) { 52 case QEMU_OPT_STRING: 53 info->type = COMMAND_LINE_PARAMETER_TYPE_STRING; 54 break; 55 case QEMU_OPT_BOOL: 56 info->type = COMMAND_LINE_PARAMETER_TYPE_BOOLEAN; 57 break; 58 case QEMU_OPT_NUMBER: 59 info->type = COMMAND_LINE_PARAMETER_TYPE_NUMBER; 60 break; 61 case QEMU_OPT_SIZE: 62 info->type = COMMAND_LINE_PARAMETER_TYPE_SIZE; 63 break; 64 } 65 66 if (desc[i].help) { 67 info->has_help = true; 68 info->help = g_strdup(desc[i].help); 69 } 70 71 entry = g_malloc0(sizeof(*entry)); 72 entry->value = info; 73 entry->next = param_list; 74 param_list = entry; 75 } 76 77 return param_list; 78 } 79 80 CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option, 81 const char *option, 82 Error **errp) 83 { 84 CommandLineOptionInfoList *conf_list = NULL, *entry; 85 CommandLineOptionInfo *info; 86 int i; 87 88 for (i = 0; vm_config_groups[i] != NULL; i++) { 89 if (!has_option || !strcmp(option, vm_config_groups[i]->name)) { 90 info = g_malloc0(sizeof(*info)); 91 info->option = g_strdup(vm_config_groups[i]->name); 92 info->parameters = query_option_descs(vm_config_groups[i]->desc); 93 entry = g_malloc0(sizeof(*entry)); 94 entry->value = info; 95 entry->next = conf_list; 96 conf_list = entry; 97 } 98 } 99 100 if (conf_list == NULL) { 101 error_setg(errp, "invalid option name: %s", option); 102 } 103 104 return conf_list; 105 } 106 107 QemuOptsList *qemu_find_opts_err(const char *group, Error **errp) 108 { 109 return find_list(vm_config_groups, group, errp); 110 } 111 112 void qemu_add_opts(QemuOptsList *list) 113 { 114 int entries, i; 115 116 entries = ARRAY_SIZE(vm_config_groups); 117 entries--; /* keep list NULL terminated */ 118 for (i = 0; i < entries; i++) { 119 if (vm_config_groups[i] == NULL) { 120 vm_config_groups[i] = list; 121 return; 122 } 123 } 124 fprintf(stderr, "ran out of space in vm_config_groups"); 125 abort(); 126 } 127 128 int qemu_set_option(const char *str) 129 { 130 char group[64], id[64], arg[64]; 131 QemuOptsList *list; 132 QemuOpts *opts; 133 int rc, offset; 134 135 rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset); 136 if (rc < 3 || str[offset] != '=') { 137 error_report("can't parse: \"%s\"", str); 138 return -1; 139 } 140 141 list = qemu_find_opts(group); 142 if (list == NULL) { 143 return -1; 144 } 145 146 opts = qemu_opts_find(list, id); 147 if (!opts) { 148 error_report("there is no %s \"%s\" defined", 149 list->name, id); 150 return -1; 151 } 152 153 if (qemu_opt_set(opts, arg, str+offset+1) == -1) { 154 return -1; 155 } 156 return 0; 157 } 158 159 struct ConfigWriteData { 160 QemuOptsList *list; 161 FILE *fp; 162 }; 163 164 static int config_write_opt(const char *name, const char *value, void *opaque) 165 { 166 struct ConfigWriteData *data = opaque; 167 168 fprintf(data->fp, " %s = \"%s\"\n", name, value); 169 return 0; 170 } 171 172 static int config_write_opts(QemuOpts *opts, void *opaque) 173 { 174 struct ConfigWriteData *data = opaque; 175 const char *id = qemu_opts_id(opts); 176 177 if (id) { 178 fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id); 179 } else { 180 fprintf(data->fp, "[%s]\n", data->list->name); 181 } 182 qemu_opt_foreach(opts, config_write_opt, data, 0); 183 fprintf(data->fp, "\n"); 184 return 0; 185 } 186 187 void qemu_config_write(FILE *fp) 188 { 189 struct ConfigWriteData data = { .fp = fp }; 190 QemuOptsList **lists = vm_config_groups; 191 int i; 192 193 fprintf(fp, "# qemu config file\n\n"); 194 for (i = 0; lists[i] != NULL; i++) { 195 data.list = lists[i]; 196 qemu_opts_foreach(data.list, config_write_opts, &data, 0); 197 } 198 } 199 200 int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname) 201 { 202 char line[1024], group[64], id[64], arg[64], value[1024]; 203 Location loc; 204 QemuOptsList *list = NULL; 205 Error *local_err = NULL; 206 QemuOpts *opts = NULL; 207 int res = -1, lno = 0; 208 209 loc_push_none(&loc); 210 while (fgets(line, sizeof(line), fp) != NULL) { 211 loc_set_file(fname, ++lno); 212 if (line[0] == '\n') { 213 /* skip empty lines */ 214 continue; 215 } 216 if (line[0] == '#') { 217 /* comment */ 218 continue; 219 } 220 if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) { 221 /* group with id */ 222 list = find_list(lists, group, &local_err); 223 if (error_is_set(&local_err)) { 224 error_report("%s", error_get_pretty(local_err)); 225 error_free(local_err); 226 goto out; 227 } 228 opts = qemu_opts_create(list, id, 1, NULL); 229 continue; 230 } 231 if (sscanf(line, "[%63[^]]]", group) == 1) { 232 /* group without id */ 233 list = find_list(lists, group, &local_err); 234 if (error_is_set(&local_err)) { 235 error_report("%s", error_get_pretty(local_err)); 236 error_free(local_err); 237 goto out; 238 } 239 opts = qemu_opts_create_nofail(list); 240 continue; 241 } 242 if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) { 243 /* arg = value */ 244 if (opts == NULL) { 245 error_report("no group defined"); 246 goto out; 247 } 248 if (qemu_opt_set(opts, arg, value) != 0) { 249 goto out; 250 } 251 continue; 252 } 253 error_report("parse error"); 254 goto out; 255 } 256 if (ferror(fp)) { 257 error_report("error reading file"); 258 goto out; 259 } 260 res = 0; 261 out: 262 loc_pop(&loc); 263 return res; 264 } 265 266 int qemu_read_config_file(const char *filename) 267 { 268 FILE *f = fopen(filename, "r"); 269 int ret; 270 271 if (f == NULL) { 272 return -errno; 273 } 274 275 ret = qemu_config_parse(f, vm_config_groups, filename); 276 fclose(f); 277 278 if (ret == 0) { 279 return 0; 280 } else { 281 return -EINVAL; 282 } 283 } 284