qemu: delete rule target on error
[qemu/mdroth.git] / qemu-config.c
blob92b5363ecfb84db4463c63dad175479fcf452e18
1 #include "qemu-common.h"
2 #include "qemu-option.h"
3 #include "qemu-config.h"
4 #include "sysemu.h"
6 QemuOptsList qemu_drive_opts = {
7 .name = "drive",
8 .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head),
9 .desc = {
11 .name = "bus",
12 .type = QEMU_OPT_NUMBER,
13 .help = "bus number",
14 },{
15 .name = "unit",
16 .type = QEMU_OPT_NUMBER,
17 .help = "unit number (i.e. lun for scsi)",
18 },{
19 .name = "if",
20 .type = QEMU_OPT_STRING,
21 .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
22 },{
23 .name = "index",
24 .type = QEMU_OPT_NUMBER,
25 },{
26 .name = "cyls",
27 .type = QEMU_OPT_NUMBER,
28 .help = "number of cylinders (ide disk geometry)",
29 },{
30 .name = "heads",
31 .type = QEMU_OPT_NUMBER,
32 .help = "number of heads (ide disk geometry)",
33 },{
34 .name = "secs",
35 .type = QEMU_OPT_NUMBER,
36 .help = "number of sectors (ide disk geometry)",
37 },{
38 .name = "trans",
39 .type = QEMU_OPT_STRING,
40 .help = "chs translation (auto, lba. none)",
41 },{
42 .name = "media",
43 .type = QEMU_OPT_STRING,
44 .help = "media type (disk, cdrom)",
45 },{
46 .name = "snapshot",
47 .type = QEMU_OPT_BOOL,
48 },{
49 .name = "file",
50 .type = QEMU_OPT_STRING,
51 .help = "disk image",
52 },{
53 .name = "cache",
54 .type = QEMU_OPT_STRING,
55 .help = "host cache usage (none, writeback, writethrough)",
56 },{
57 .name = "aio",
58 .type = QEMU_OPT_STRING,
59 .help = "host AIO implementation (threads, native)",
60 },{
61 .name = "format",
62 .type = QEMU_OPT_STRING,
63 .help = "disk format (raw, qcow2, ...)",
64 },{
65 .name = "serial",
66 .type = QEMU_OPT_STRING,
67 },{
68 .name = "rerror",
69 .type = QEMU_OPT_STRING,
70 },{
71 .name = "werror",
72 .type = QEMU_OPT_STRING,
73 },{
74 .name = "addr",
75 .type = QEMU_OPT_STRING,
76 .help = "pci address (virtio only)",
77 },{
78 .name = "readonly",
79 .type = QEMU_OPT_BOOL,
81 { /* end if list */ }
85 QemuOptsList qemu_chardev_opts = {
86 .name = "chardev",
87 .head = QTAILQ_HEAD_INITIALIZER(qemu_chardev_opts.head),
88 .desc = {
90 .name = "backend",
91 .type = QEMU_OPT_STRING,
92 },{
93 .name = "path",
94 .type = QEMU_OPT_STRING,
95 },{
96 .name = "host",
97 .type = QEMU_OPT_STRING,
98 },{
99 .name = "port",
100 .type = QEMU_OPT_STRING,
102 .name = "localaddr",
103 .type = QEMU_OPT_STRING,
105 .name = "localport",
106 .type = QEMU_OPT_STRING,
108 .name = "to",
109 .type = QEMU_OPT_NUMBER,
111 .name = "ipv4",
112 .type = QEMU_OPT_BOOL,
114 .name = "ipv6",
115 .type = QEMU_OPT_BOOL,
117 .name = "wait",
118 .type = QEMU_OPT_BOOL,
120 .name = "server",
121 .type = QEMU_OPT_BOOL,
123 .name = "delay",
124 .type = QEMU_OPT_BOOL,
126 .name = "telnet",
127 .type = QEMU_OPT_BOOL,
129 .name = "width",
130 .type = QEMU_OPT_NUMBER,
132 .name = "height",
133 .type = QEMU_OPT_NUMBER,
135 .name = "cols",
136 .type = QEMU_OPT_NUMBER,
138 .name = "rows",
139 .type = QEMU_OPT_NUMBER,
141 .name = "mux",
142 .type = QEMU_OPT_BOOL,
144 .name = "signal",
145 .type = QEMU_OPT_BOOL,
147 { /* end if list */ }
151 QemuOptsList qemu_device_opts = {
152 .name = "device",
153 .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
154 .desc = {
156 * no elements => accept any
157 * sanity checking will happen later
158 * when setting device properties
160 { /* end if list */ }
164 QemuOptsList qemu_netdev_opts = {
165 .name = "netdev",
166 .head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head),
167 .desc = {
169 * no elements => accept any params
170 * validation will happen later
172 { /* end of list */ }
176 QemuOptsList qemu_net_opts = {
177 .name = "net",
178 .head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head),
179 .desc = {
181 * no elements => accept any params
182 * validation will happen later
184 { /* end of list */ }
188 QemuOptsList qemu_rtc_opts = {
189 .name = "rtc",
190 .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head),
191 .desc = {
193 .name = "base",
194 .type = QEMU_OPT_STRING,
196 .name = "clock",
197 .type = QEMU_OPT_STRING,
198 #ifdef TARGET_I386
200 .name = "driftfix",
201 .type = QEMU_OPT_STRING,
202 #endif
204 { /* end if list */ }
208 static QemuOptsList *lists[] = {
209 &qemu_drive_opts,
210 &qemu_chardev_opts,
211 &qemu_device_opts,
212 &qemu_netdev_opts,
213 &qemu_net_opts,
214 &qemu_rtc_opts,
215 NULL,
218 static QemuOptsList *find_list(const char *group)
220 int i;
222 for (i = 0; lists[i] != NULL; i++) {
223 if (strcmp(lists[i]->name, group) == 0)
224 break;
226 if (lists[i] == NULL) {
227 qemu_error("there is no option group \"%s\"\n", group);
229 return lists[i];
232 int qemu_set_option(const char *str)
234 char group[64], id[64], arg[64];
235 QemuOptsList *list;
236 QemuOpts *opts;
237 int rc, offset;
239 rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
240 if (rc < 3 || str[offset] != '=') {
241 qemu_error("can't parse: \"%s\"\n", str);
242 return -1;
245 list = find_list(group);
246 if (list == NULL) {
247 return -1;
250 opts = qemu_opts_find(list, id);
251 if (!opts) {
252 qemu_error("there is no %s \"%s\" defined\n",
253 list->name, id);
254 return -1;
257 if (qemu_opt_set(opts, arg, str+offset+1) == -1) {
258 return -1;
260 return 0;
263 struct ConfigWriteData {
264 QemuOptsList *list;
265 FILE *fp;
268 static int config_write_opt(const char *name, const char *value, void *opaque)
270 struct ConfigWriteData *data = opaque;
272 fprintf(data->fp, " %s = \"%s\"\n", name, value);
273 return 0;
276 static int config_write_opts(QemuOpts *opts, void *opaque)
278 struct ConfigWriteData *data = opaque;
279 const char *id = qemu_opts_id(opts);
281 if (id) {
282 fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id);
283 } else {
284 fprintf(data->fp, "[%s]\n", data->list->name);
286 qemu_opt_foreach(opts, config_write_opt, data, 0);
287 fprintf(data->fp, "\n");
288 return 0;
291 void qemu_config_write(FILE *fp)
293 struct ConfigWriteData data = { .fp = fp };
294 int i;
296 fprintf(fp, "# qemu config file\n\n");
297 for (i = 0; lists[i] != NULL; i++) {
298 data.list = lists[i];
299 qemu_opts_foreach(data.list, config_write_opts, &data, 0);
303 int qemu_config_parse(FILE *fp)
305 char line[1024], group[64], id[64], arg[64], value[1024];
306 QemuOptsList *list = NULL;
307 QemuOpts *opts = NULL;
309 while (fgets(line, sizeof(line), fp) != NULL) {
310 if (line[0] == '\n') {
311 /* skip empty lines */
312 continue;
314 if (line[0] == '#') {
315 /* comment */
316 continue;
318 if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
319 /* group with id */
320 list = find_list(group);
321 if (list == NULL)
322 return -1;
323 opts = qemu_opts_create(list, id, 1);
324 continue;
326 if (sscanf(line, "[%63[^]]]", group) == 1) {
327 /* group without id */
328 list = find_list(group);
329 if (list == NULL)
330 return -1;
331 opts = qemu_opts_create(list, NULL, 0);
332 continue;
334 if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
335 /* arg = value */
336 if (opts == NULL) {
337 fprintf(stderr, "no group defined\n");
338 return -1;
340 if (qemu_opt_set(opts, arg, value) != 0) {
341 fprintf(stderr, "failed to set \"%s\" for %s\n",
342 arg, group);
343 return -1;
345 continue;
347 fprintf(stderr, "parse error: %s\n", line);
348 return -1;
350 return 0;