]> Git Repo - qemu.git/blob - qemu-config.c
qcow2: Don't ignore update_refcount return value
[qemu.git] / qemu-config.c
1 #include "qemu-common.h"
2 #include "qemu-option.h"
3 #include "qemu-config.h"
4 #include "sysemu.h"
5 #include "hw/qdev.h"
6
7 QemuOptsList qemu_drive_opts = {
8     .name = "drive",
9     .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head),
10     .desc = {
11         {
12             .name = "bus",
13             .type = QEMU_OPT_NUMBER,
14             .help = "bus number",
15         },{
16             .name = "unit",
17             .type = QEMU_OPT_NUMBER,
18             .help = "unit number (i.e. lun for scsi)",
19         },{
20             .name = "if",
21             .type = QEMU_OPT_STRING,
22             .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
23         },{
24             .name = "index",
25             .type = QEMU_OPT_NUMBER,
26         },{
27             .name = "cyls",
28             .type = QEMU_OPT_NUMBER,
29             .help = "number of cylinders (ide disk geometry)",
30         },{
31             .name = "heads",
32             .type = QEMU_OPT_NUMBER,
33             .help = "number of heads (ide disk geometry)",
34         },{
35             .name = "secs",
36             .type = QEMU_OPT_NUMBER,
37             .help = "number of sectors (ide disk geometry)",
38         },{
39             .name = "trans",
40             .type = QEMU_OPT_STRING,
41             .help = "chs translation (auto, lba. none)",
42         },{
43             .name = "media",
44             .type = QEMU_OPT_STRING,
45             .help = "media type (disk, cdrom)",
46         },{
47             .name = "snapshot",
48             .type = QEMU_OPT_BOOL,
49         },{
50             .name = "file",
51             .type = QEMU_OPT_STRING,
52             .help = "disk image",
53         },{
54             .name = "cache",
55             .type = QEMU_OPT_STRING,
56             .help = "host cache usage (none, writeback, writethrough)",
57         },{
58             .name = "aio",
59             .type = QEMU_OPT_STRING,
60             .help = "host AIO implementation (threads, native)",
61         },{
62             .name = "format",
63             .type = QEMU_OPT_STRING,
64             .help = "disk format (raw, qcow2, ...)",
65         },{
66             .name = "serial",
67             .type = QEMU_OPT_STRING,
68         },{
69             .name = "rerror",
70             .type = QEMU_OPT_STRING,
71         },{
72             .name = "werror",
73             .type = QEMU_OPT_STRING,
74         },{
75             .name = "addr",
76             .type = QEMU_OPT_STRING,
77             .help = "pci address (virtio only)",
78         },{
79             .name = "readonly",
80             .type = QEMU_OPT_BOOL,
81         },
82         { /* end if list */ }
83     },
84 };
85
86 QemuOptsList qemu_chardev_opts = {
87     .name = "chardev",
88     .head = QTAILQ_HEAD_INITIALIZER(qemu_chardev_opts.head),
89     .desc = {
90         {
91             .name = "backend",
92             .type = QEMU_OPT_STRING,
93         },{
94             .name = "path",
95             .type = QEMU_OPT_STRING,
96         },{
97             .name = "host",
98             .type = QEMU_OPT_STRING,
99         },{
100             .name = "port",
101             .type = QEMU_OPT_STRING,
102         },{
103             .name = "localaddr",
104             .type = QEMU_OPT_STRING,
105         },{
106             .name = "localport",
107             .type = QEMU_OPT_STRING,
108         },{
109             .name = "to",
110             .type = QEMU_OPT_NUMBER,
111         },{
112             .name = "ipv4",
113             .type = QEMU_OPT_BOOL,
114         },{
115             .name = "ipv6",
116             .type = QEMU_OPT_BOOL,
117         },{
118             .name = "wait",
119             .type = QEMU_OPT_BOOL,
120         },{
121             .name = "server",
122             .type = QEMU_OPT_BOOL,
123         },{
124             .name = "delay",
125             .type = QEMU_OPT_BOOL,
126         },{
127             .name = "telnet",
128             .type = QEMU_OPT_BOOL,
129         },{
130             .name = "width",
131             .type = QEMU_OPT_NUMBER,
132         },{
133             .name = "height",
134             .type = QEMU_OPT_NUMBER,
135         },{
136             .name = "cols",
137             .type = QEMU_OPT_NUMBER,
138         },{
139             .name = "rows",
140             .type = QEMU_OPT_NUMBER,
141         },{
142             .name = "mux",
143             .type = QEMU_OPT_BOOL,
144         },{
145             .name = "signal",
146             .type = QEMU_OPT_BOOL,
147         },
148         { /* end if list */ }
149     },
150 };
151
152 QemuOptsList qemu_device_opts = {
153     .name = "device",
154     .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
155     .desc = {
156         /*
157          * no elements => accept any
158          * sanity checking will happen later
159          * when setting device properties
160          */
161         { /* end if list */ }
162     },
163 };
164
165 QemuOptsList qemu_netdev_opts = {
166     .name = "netdev",
167     .head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head),
168     .desc = {
169         /*
170          * no elements => accept any params
171          * validation will happen later
172          */
173         { /* end of list */ }
174     },
175 };
176
177 QemuOptsList qemu_net_opts = {
178     .name = "net",
179     .head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head),
180     .desc = {
181         /*
182          * no elements => accept any params
183          * validation will happen later
184          */
185         { /* end of list */ }
186     },
187 };
188
189 QemuOptsList qemu_rtc_opts = {
190     .name = "rtc",
191     .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head),
192     .desc = {
193         {
194             .name = "base",
195             .type = QEMU_OPT_STRING,
196         },{
197             .name = "clock",
198             .type = QEMU_OPT_STRING,
199 #ifdef TARGET_I386
200         },{
201             .name = "driftfix",
202             .type = QEMU_OPT_STRING,
203 #endif
204         },
205         { /* end if list */ }
206     },
207 };
208
209 QemuOptsList qemu_global_opts = {
210     .name = "global",
211     .head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
212     .desc = {
213         {
214             .name = "driver",
215             .type = QEMU_OPT_STRING,
216         },{
217             .name = "property",
218             .type = QEMU_OPT_STRING,
219         },{
220             .name = "value",
221             .type = QEMU_OPT_STRING,
222         },
223         { /* end if list */ }
224     },
225 };
226
227 QemuOptsList qemu_mon_opts = {
228     .name = "mon",
229     .head = QTAILQ_HEAD_INITIALIZER(qemu_mon_opts.head),
230     .desc = {
231         {
232             .name = "mode",
233             .type = QEMU_OPT_STRING,
234         },{
235             .name = "chardev",
236             .type = QEMU_OPT_STRING,
237         },{
238             .name = "default",
239             .type = QEMU_OPT_BOOL,
240         },
241         { /* end if list */ }
242     },
243 };
244
245 static QemuOptsList *lists[] = {
246     &qemu_drive_opts,
247     &qemu_chardev_opts,
248     &qemu_device_opts,
249     &qemu_netdev_opts,
250     &qemu_net_opts,
251     &qemu_rtc_opts,
252     &qemu_global_opts,
253     &qemu_mon_opts,
254     NULL,
255 };
256
257 static QemuOptsList *find_list(const char *group)
258 {
259     int i;
260
261     for (i = 0; lists[i] != NULL; i++) {
262         if (strcmp(lists[i]->name, group) == 0)
263             break;
264     }
265     if (lists[i] == NULL) {
266         qemu_error("there is no option group \"%s\"\n", group);
267     }
268     return lists[i];
269 }
270
271 int qemu_set_option(const char *str)
272 {
273     char group[64], id[64], arg[64];
274     QemuOptsList *list;
275     QemuOpts *opts;
276     int rc, offset;
277
278     rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
279     if (rc < 3 || str[offset] != '=') {
280         qemu_error("can't parse: \"%s\"\n", str);
281         return -1;
282     }
283
284     list = find_list(group);
285     if (list == NULL) {
286         return -1;
287     }
288
289     opts = qemu_opts_find(list, id);
290     if (!opts) {
291         qemu_error("there is no %s \"%s\" defined\n",
292                    list->name, id);
293         return -1;
294     }
295
296     if (qemu_opt_set(opts, arg, str+offset+1) == -1) {
297         return -1;
298     }
299     return 0;
300 }
301
302 int qemu_global_option(const char *str)
303 {
304     char driver[64], property[64];
305     QemuOpts *opts;
306     int rc, offset;
307
308     rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
309     if (rc < 2 || str[offset] != '=') {
310         qemu_error("can't parse: \"%s\"\n", str);
311         return -1;
312     }
313
314     opts = qemu_opts_create(&qemu_global_opts, NULL, 0);
315     qemu_opt_set(opts, "driver", driver);
316     qemu_opt_set(opts, "property", property);
317     qemu_opt_set(opts, "value", str+offset+1);
318     return 0;
319 }
320
321 static int qemu_add_one_global(QemuOpts *opts, void *opaque)
322 {
323     GlobalProperty *g;
324
325     g = qemu_mallocz(sizeof(*g));
326     g->driver   = qemu_opt_get(opts, "driver");
327     g->property = qemu_opt_get(opts, "property");
328     g->value    = qemu_opt_get(opts, "value");
329     qdev_prop_register_global(g);
330     return 0;
331 }
332
333 void qemu_add_globals(void)
334 {
335     qemu_opts_foreach(&qemu_global_opts, qemu_add_one_global, NULL, 0);
336 }
337
338 struct ConfigWriteData {
339     QemuOptsList *list;
340     FILE *fp;
341 };
342
343 static int config_write_opt(const char *name, const char *value, void *opaque)
344 {
345     struct ConfigWriteData *data = opaque;
346
347     fprintf(data->fp, "  %s = \"%s\"\n", name, value);
348     return 0;
349 }
350
351 static int config_write_opts(QemuOpts *opts, void *opaque)
352 {
353     struct ConfigWriteData *data = opaque;
354     const char *id = qemu_opts_id(opts);
355
356     if (id) {
357         fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id);
358     } else {
359         fprintf(data->fp, "[%s]\n", data->list->name);
360     }
361     qemu_opt_foreach(opts, config_write_opt, data, 0);
362     fprintf(data->fp, "\n");
363     return 0;
364 }
365
366 void qemu_config_write(FILE *fp)
367 {
368     struct ConfigWriteData data = { .fp = fp };
369     int i;
370
371     fprintf(fp, "# qemu config file\n\n");
372     for (i = 0; lists[i] != NULL; i++) {
373         data.list = lists[i];
374         qemu_opts_foreach(data.list, config_write_opts, &data, 0);
375     }
376 }
377
378 int qemu_config_parse(FILE *fp)
379 {
380     char line[1024], group[64], id[64], arg[64], value[1024];
381     QemuOptsList *list = NULL;
382     QemuOpts *opts = NULL;
383
384     while (fgets(line, sizeof(line), fp) != NULL) {
385         if (line[0] == '\n') {
386             /* skip empty lines */
387             continue;
388         }
389         if (line[0] == '#') {
390             /* comment */
391             continue;
392         }
393         if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
394             /* group with id */
395             list = find_list(group);
396             if (list == NULL)
397                 return -1;
398             opts = qemu_opts_create(list, id, 1);
399             continue;
400         }
401         if (sscanf(line, "[%63[^]]]", group) == 1) {
402             /* group without id */
403             list = find_list(group);
404             if (list == NULL)
405                 return -1;
406             opts = qemu_opts_create(list, NULL, 0);
407             continue;
408         }
409         if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
410             /* arg = value */
411             if (opts == NULL) {
412                 fprintf(stderr, "no group defined\n");
413                 return -1;
414             }
415             if (qemu_opt_set(opts, arg, value) != 0) {
416                 fprintf(stderr, "failed to set \"%s\" for %s\n",
417                         arg, group);
418                 return -1;
419             }
420             continue;
421         }
422         fprintf(stderr, "parse error: %s\n", line);
423         return -1;
424     }
425     return 0;
426 }
This page took 0.046921 seconds and 4 git commands to generate.