Merge tag 'pull-request-2024-06-12' of https://gitlab.com/thuth/qemu into staging
[qemu/kevin.git] / util / qemu-config.c
bloba90c18dad25a9e8c07fa77a6561ade0b26b1c204
1 #include "qemu/osdep.h"
2 #include "block/qdict.h" /* for qdict_extract_subqdict() */
3 #include "qapi/error.h"
4 #include "qapi/qmp/qdict.h"
5 #include "qapi/qmp/qlist.h"
6 #include "qemu/error-report.h"
7 #include "qemu/option.h"
8 #include "qemu/config-file.h"
10 QemuOptsList *vm_config_groups[48];
11 QemuOptsList *drive_config_groups[5];
13 static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
14 Error **errp)
16 int i;
18 qemu_load_module_for_opts(group);
19 for (i = 0; lists[i] != NULL; i++) {
20 if (strcmp(lists[i]->name, group) == 0)
21 break;
23 if (lists[i] == NULL) {
24 error_setg(errp, "There is no option group '%s'", group);
26 return lists[i];
29 QemuOptsList *qemu_find_opts(const char *group)
31 QemuOptsList *ret;
32 Error *local_err = NULL;
34 ret = find_list(vm_config_groups, group, &local_err);
35 if (local_err) {
36 error_report_err(local_err);
39 return ret;
42 QemuOpts *qemu_find_opts_singleton(const char *group)
44 QemuOptsList *list;
45 QemuOpts *opts;
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);
53 return opts;
56 QemuOptsList *qemu_find_opts_err(const char *group, Error **errp)
58 return find_list(vm_config_groups, group, errp);
61 void qemu_add_drive_opts(QemuOptsList *list)
63 int entries, i;
65 entries = ARRAY_SIZE(drive_config_groups);
66 entries--; /* keep list NULL terminated */
67 for (i = 0; i < entries; i++) {
68 if (drive_config_groups[i] == NULL) {
69 drive_config_groups[i] = list;
70 return;
73 fprintf(stderr, "ran out of space in drive_config_groups");
74 abort();
77 void qemu_add_opts(QemuOptsList *list)
79 int entries, i;
81 entries = ARRAY_SIZE(vm_config_groups);
82 entries--; /* keep list NULL terminated */
83 for (i = 0; i < entries; i++) {
84 if (vm_config_groups[i] == NULL) {
85 vm_config_groups[i] = list;
86 return;
89 fprintf(stderr, "ran out of space in vm_config_groups");
90 abort();
93 /* Returns number of config groups on success, -errno on error */
94 static int qemu_config_foreach(FILE *fp, QEMUConfigCB *cb, void *opaque,
95 const char *fname, Error **errp)
97 ERRP_GUARD();
98 char line[1024], prev_group[64], group[64], arg[64], value[1024];
99 Location loc;
100 QDict *qdict = NULL;
101 int res = -EINVAL, lno = 0;
102 int count = 0;
104 loc_push_none(&loc);
105 while (fgets(line, sizeof(line), fp) != NULL) {
106 ++lno;
107 if (line[0] == '\n') {
108 /* skip empty lines */
109 continue;
111 if (line[0] == '#') {
112 /* comment */
113 continue;
115 if (line[0] == '[') {
116 QDict *prev = qdict;
117 if (sscanf(line, "[%63s \"%63[^\"]\"]", group, value) == 2) {
118 qdict = qdict_new();
119 qdict_put_str(qdict, "id", value);
120 count++;
121 } else if (sscanf(line, "[%63[^]]]", group) == 1) {
122 qdict = qdict_new();
123 count++;
125 if (qdict != prev) {
126 if (prev) {
127 cb(prev_group, prev, opaque, errp);
128 qobject_unref(prev);
129 if (*errp) {
130 goto out;
133 strcpy(prev_group, group);
134 continue;
137 loc_set_file(fname, lno);
138 value[0] = '\0';
139 if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2 ||
140 sscanf(line, " %63s = \"\"", arg) == 1) {
141 /* arg = value */
142 if (qdict == NULL) {
143 error_setg(errp, "no group defined");
144 goto out;
146 qdict_put_str(qdict, arg, value);
147 continue;
149 error_setg(errp, "parse error");
150 goto out;
152 if (ferror(fp)) {
153 loc_pop(&loc);
154 error_setg_errno(errp, errno, "Cannot read config file");
155 goto out_no_loc;
157 res = count;
158 if (qdict) {
159 cb(group, qdict, opaque, errp);
161 out:
162 loc_pop(&loc);
163 out_no_loc:
164 qobject_unref(qdict);
165 return res;
168 void qemu_config_do_parse(const char *group, QDict *qdict, void *opaque, Error **errp)
170 QemuOptsList **lists = opaque;
171 QemuOptsList *list;
173 list = find_list(lists, group, errp);
174 if (!list) {
175 return;
178 qemu_opts_from_qdict(list, qdict, errp);
181 int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp)
183 return qemu_config_foreach(fp, qemu_config_do_parse, lists, fname, errp);
186 int qemu_read_config_file(const char *filename, QEMUConfigCB *cb, Error **errp)
188 FILE *f = fopen(filename, "r");
189 int ret;
191 if (f == NULL) {
192 error_setg_file_open(errp, errno, filename);
193 return -errno;
196 ret = qemu_config_foreach(f, cb, vm_config_groups, filename, errp);
197 fclose(f);
198 return ret;
201 static bool config_parse_qdict_section(QDict *options, QemuOptsList *opts,
202 Error **errp)
204 QemuOpts *subopts;
205 g_autoptr(QDict) subqdict = NULL;
206 g_autoptr(QList) list = NULL;
207 size_t orig_size, enum_size;
208 char *prefix;
210 prefix = g_strdup_printf("%s.", opts->name);
211 qdict_extract_subqdict(options, &subqdict, prefix);
212 g_free(prefix);
213 orig_size = qdict_size(subqdict);
214 if (!orig_size) {
215 return true;
218 subopts = qemu_opts_create(opts, NULL, 0, errp);
219 if (!subopts) {
220 return false;
223 if (!qemu_opts_absorb_qdict(subopts, subqdict, errp)) {
224 return false;
227 enum_size = qdict_size(subqdict);
228 if (enum_size < orig_size && enum_size) {
229 error_setg(errp, "Unknown option '%s' for [%s]",
230 qdict_first(subqdict)->key, opts->name);
231 return false;
234 if (enum_size) {
235 /* Multiple, enumerated sections */
236 QListEntry *list_entry;
237 unsigned i = 0;
239 /* Not required anymore */
240 qemu_opts_del(subopts);
242 qdict_array_split(subqdict, &list);
243 if (qdict_size(subqdict)) {
244 error_setg(errp, "Unused option '%s' for [%s]",
245 qdict_first(subqdict)->key, opts->name);
246 return false;
249 QLIST_FOREACH_ENTRY(list, list_entry) {
250 QDict *section = qobject_to(QDict, qlist_entry_obj(list_entry));
251 char *opt_name;
253 if (!section) {
254 error_setg(errp, "[%s] section (index %u) does not consist of "
255 "keys", opts->name, i);
256 return false;
259 opt_name = g_strdup_printf("%s.%u", opts->name, i++);
260 subopts = qemu_opts_create(opts, opt_name, 1, errp);
261 g_free(opt_name);
262 if (!subopts) {
263 return false;
266 if (!qemu_opts_absorb_qdict(subopts, section, errp)) {
267 qemu_opts_del(subopts);
268 return false;
271 if (qdict_size(section)) {
272 error_setg(errp, "[%s] section doesn't support the option '%s'",
273 opts->name, qdict_first(section)->key);
274 qemu_opts_del(subopts);
275 return false;
280 return true;
283 bool qemu_config_parse_qdict(QDict *options, QemuOptsList **lists,
284 Error **errp)
286 int i;
288 for (i = 0; lists[i]; i++) {
289 if (!config_parse_qdict_section(options, lists[i], errp)) {
290 return false;
294 return true;