]> Git Repo - qemu.git/blob - qemu-config.c
sun4u: initialize OBIO interrupt mappings
[qemu.git] / qemu-config.c
1 #include "qemu-common.h"
2 #include "qemu-error.h"
3 #include "qemu-option.h"
4 #include "qemu-config.h"
5 #include "hw/qdev.h"
6
7 static 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             .help = "index number",
27         },{
28             .name = "cyls",
29             .type = QEMU_OPT_NUMBER,
30             .help = "number of cylinders (ide disk geometry)",
31         },{
32             .name = "heads",
33             .type = QEMU_OPT_NUMBER,
34             .help = "number of heads (ide disk geometry)",
35         },{
36             .name = "secs",
37             .type = QEMU_OPT_NUMBER,
38             .help = "number of sectors (ide disk geometry)",
39         },{
40             .name = "trans",
41             .type = QEMU_OPT_STRING,
42             .help = "chs translation (auto, lba. none)",
43         },{
44             .name = "media",
45             .type = QEMU_OPT_STRING,
46             .help = "media type (disk, cdrom)",
47         },{
48             .name = "snapshot",
49             .type = QEMU_OPT_BOOL,
50             .help = "enable/disable snapshot mode",
51         },{
52             .name = "file",
53             .type = QEMU_OPT_STRING,
54             .help = "disk image",
55         },{
56             .name = "cache",
57             .type = QEMU_OPT_STRING,
58             .help = "host cache usage (none, writeback, writethrough, "
59                     "directsync, unsafe)",
60         },{
61             .name = "aio",
62             .type = QEMU_OPT_STRING,
63             .help = "host AIO implementation (threads, native)",
64         },{
65             .name = "format",
66             .type = QEMU_OPT_STRING,
67             .help = "disk format (raw, qcow2, ...)",
68         },{
69             .name = "serial",
70             .type = QEMU_OPT_STRING,
71             .help = "disk serial number",
72         },{
73             .name = "rerror",
74             .type = QEMU_OPT_STRING,
75             .help = "read error action",
76         },{
77             .name = "werror",
78             .type = QEMU_OPT_STRING,
79             .help = "write error action",
80         },{
81             .name = "addr",
82             .type = QEMU_OPT_STRING,
83             .help = "pci address (virtio only)",
84         },{
85             .name = "readonly",
86             .type = QEMU_OPT_BOOL,
87             .help = "open drive file as read-only",
88         },{
89             .name = "iops",
90             .type = QEMU_OPT_NUMBER,
91             .help = "limit total I/O operations per second",
92         },{
93             .name = "iops_rd",
94             .type = QEMU_OPT_NUMBER,
95             .help = "limit read operations per second",
96         },{
97             .name = "iops_wr",
98             .type = QEMU_OPT_NUMBER,
99             .help = "limit write operations per second",
100         },{
101             .name = "bps",
102             .type = QEMU_OPT_NUMBER,
103             .help = "limit total bytes per second",
104         },{
105             .name = "bps_rd",
106             .type = QEMU_OPT_NUMBER,
107             .help = "limit read bytes per second",
108         },{
109             .name = "bps_wr",
110             .type = QEMU_OPT_NUMBER,
111             .help = "limit write bytes per second",
112         },{
113             .name = "copy-on-read",
114             .type = QEMU_OPT_BOOL,
115             .help = "copy read data from backing file into image file",
116         },
117         { /* end of list */ }
118     },
119 };
120
121 static QemuOptsList qemu_iscsi_opts = {
122     .name = "iscsi",
123     .head = QTAILQ_HEAD_INITIALIZER(qemu_iscsi_opts.head),
124     .desc = {
125         {
126             .name = "user",
127             .type = QEMU_OPT_STRING,
128             .help = "username for CHAP authentication to target",
129         },{
130             .name = "password",
131             .type = QEMU_OPT_STRING,
132             .help = "password for CHAP authentication to target",
133         },{
134             .name = "header-digest",
135             .type = QEMU_OPT_STRING,
136             .help = "HeaderDigest setting. "
137                     "{CRC32C|CRC32C-NONE|NONE-CRC32C|NONE}",
138         },{
139             .name = "initiator-name",
140             .type = QEMU_OPT_STRING,
141             .help = "Initiator iqn name to use when connecting",
142         },
143         { /* end of list */ }
144     },
145 };
146
147 static QemuOptsList qemu_chardev_opts = {
148     .name = "chardev",
149     .implied_opt_name = "backend",
150     .head = QTAILQ_HEAD_INITIALIZER(qemu_chardev_opts.head),
151     .desc = {
152         {
153             .name = "backend",
154             .type = QEMU_OPT_STRING,
155         },{
156             .name = "path",
157             .type = QEMU_OPT_STRING,
158         },{
159             .name = "host",
160             .type = QEMU_OPT_STRING,
161         },{
162             .name = "port",
163             .type = QEMU_OPT_STRING,
164         },{
165             .name = "localaddr",
166             .type = QEMU_OPT_STRING,
167         },{
168             .name = "localport",
169             .type = QEMU_OPT_STRING,
170         },{
171             .name = "to",
172             .type = QEMU_OPT_NUMBER,
173         },{
174             .name = "ipv4",
175             .type = QEMU_OPT_BOOL,
176         },{
177             .name = "ipv6",
178             .type = QEMU_OPT_BOOL,
179         },{
180             .name = "wait",
181             .type = QEMU_OPT_BOOL,
182         },{
183             .name = "server",
184             .type = QEMU_OPT_BOOL,
185         },{
186             .name = "delay",
187             .type = QEMU_OPT_BOOL,
188         },{
189             .name = "telnet",
190             .type = QEMU_OPT_BOOL,
191         },{
192             .name = "width",
193             .type = QEMU_OPT_NUMBER,
194         },{
195             .name = "height",
196             .type = QEMU_OPT_NUMBER,
197         },{
198             .name = "cols",
199             .type = QEMU_OPT_NUMBER,
200         },{
201             .name = "rows",
202             .type = QEMU_OPT_NUMBER,
203         },{
204             .name = "mux",
205             .type = QEMU_OPT_BOOL,
206         },{
207             .name = "signal",
208             .type = QEMU_OPT_BOOL,
209         },{
210             .name = "name",
211             .type = QEMU_OPT_STRING,
212         },{
213             .name = "debug",
214             .type = QEMU_OPT_NUMBER,
215         },
216         { /* end of list */ }
217     },
218 };
219
220 QemuOptsList qemu_fsdev_opts = {
221     .name = "fsdev",
222     .implied_opt_name = "fsdriver",
223     .head = QTAILQ_HEAD_INITIALIZER(qemu_fsdev_opts.head),
224     .desc = {
225         {
226             .name = "fsdriver",
227             .type = QEMU_OPT_STRING,
228         }, {
229             .name = "path",
230             .type = QEMU_OPT_STRING,
231         }, {
232             .name = "security_model",
233             .type = QEMU_OPT_STRING,
234         }, {
235             .name = "writeout",
236             .type = QEMU_OPT_STRING,
237         }, {
238             .name = "readonly",
239             .type = QEMU_OPT_BOOL,
240
241         }, {
242             .name = "socket",
243             .type = QEMU_OPT_STRING,
244         }, {
245             .name = "sock_fd",
246             .type = QEMU_OPT_NUMBER,
247         },
248
249         { /*End of list */ }
250     },
251 };
252
253 QemuOptsList qemu_virtfs_opts = {
254     .name = "virtfs",
255     .implied_opt_name = "fsdriver",
256     .head = QTAILQ_HEAD_INITIALIZER(qemu_virtfs_opts.head),
257     .desc = {
258         {
259             .name = "fsdriver",
260             .type = QEMU_OPT_STRING,
261         }, {
262             .name = "path",
263             .type = QEMU_OPT_STRING,
264         }, {
265             .name = "mount_tag",
266             .type = QEMU_OPT_STRING,
267         }, {
268             .name = "security_model",
269             .type = QEMU_OPT_STRING,
270         }, {
271             .name = "writeout",
272             .type = QEMU_OPT_STRING,
273         }, {
274             .name = "readonly",
275             .type = QEMU_OPT_BOOL,
276         }, {
277             .name = "socket",
278             .type = QEMU_OPT_STRING,
279         }, {
280             .name = "sock_fd",
281             .type = QEMU_OPT_NUMBER,
282         },
283
284         { /*End of list */ }
285     },
286 };
287
288 static QemuOptsList qemu_device_opts = {
289     .name = "device",
290     .implied_opt_name = "driver",
291     .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
292     .desc = {
293         /*
294          * no elements => accept any
295          * sanity checking will happen later
296          * when setting device properties
297          */
298         { /* end of list */ }
299     },
300 };
301
302 static QemuOptsList qemu_netdev_opts = {
303     .name = "netdev",
304     .implied_opt_name = "type",
305     .head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head),
306     .desc = {
307         /*
308          * no elements => accept any params
309          * validation will happen later
310          */
311         { /* end of list */ }
312     },
313 };
314
315 static QemuOptsList qemu_net_opts = {
316     .name = "net",
317     .implied_opt_name = "type",
318     .head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head),
319     .desc = {
320         /*
321          * no elements => accept any params
322          * validation will happen later
323          */
324         { /* end of list */ }
325     },
326 };
327
328 static QemuOptsList qemu_rtc_opts = {
329     .name = "rtc",
330     .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head),
331     .desc = {
332         {
333             .name = "base",
334             .type = QEMU_OPT_STRING,
335         },{
336             .name = "clock",
337             .type = QEMU_OPT_STRING,
338         },{
339             .name = "driftfix",
340             .type = QEMU_OPT_STRING,
341         },
342         { /* end of list */ }
343     },
344 };
345
346 static QemuOptsList qemu_global_opts = {
347     .name = "global",
348     .head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
349     .desc = {
350         {
351             .name = "driver",
352             .type = QEMU_OPT_STRING,
353         },{
354             .name = "property",
355             .type = QEMU_OPT_STRING,
356         },{
357             .name = "value",
358             .type = QEMU_OPT_STRING,
359         },
360         { /* end of list */ }
361     },
362 };
363
364 static QemuOptsList qemu_mon_opts = {
365     .name = "mon",
366     .implied_opt_name = "chardev",
367     .head = QTAILQ_HEAD_INITIALIZER(qemu_mon_opts.head),
368     .desc = {
369         {
370             .name = "mode",
371             .type = QEMU_OPT_STRING,
372         },{
373             .name = "chardev",
374             .type = QEMU_OPT_STRING,
375         },{
376             .name = "default",
377             .type = QEMU_OPT_BOOL,
378         },{
379             .name = "pretty",
380             .type = QEMU_OPT_BOOL,
381         },
382         { /* end of list */ }
383     },
384 };
385
386 static QemuOptsList qemu_trace_opts = {
387     .name = "trace",
388     .implied_opt_name = "trace",
389     .head = QTAILQ_HEAD_INITIALIZER(qemu_trace_opts.head),
390     .desc = {
391         {
392             .name = "events",
393             .type = QEMU_OPT_STRING,
394         },{
395             .name = "file",
396             .type = QEMU_OPT_STRING,
397         },
398         { /* end of list */ }
399     },
400 };
401
402 static QemuOptsList qemu_cpudef_opts = {
403     .name = "cpudef",
404     .head = QTAILQ_HEAD_INITIALIZER(qemu_cpudef_opts.head),
405     .desc = {
406         {
407             .name = "name",
408             .type = QEMU_OPT_STRING,
409         },{
410             .name = "level",
411             .type = QEMU_OPT_NUMBER,
412         },{
413             .name = "vendor",
414             .type = QEMU_OPT_STRING,
415         },{
416             .name = "family",
417             .type = QEMU_OPT_NUMBER,
418         },{
419             .name = "model",
420             .type = QEMU_OPT_NUMBER,
421         },{
422             .name = "stepping",
423             .type = QEMU_OPT_NUMBER,
424         },{
425             .name = "feature_edx",      /* cpuid 0000_0001.edx */
426             .type = QEMU_OPT_STRING,
427         },{
428             .name = "feature_ecx",      /* cpuid 0000_0001.ecx */
429             .type = QEMU_OPT_STRING,
430         },{
431             .name = "extfeature_edx",   /* cpuid 8000_0001.edx */
432             .type = QEMU_OPT_STRING,
433         },{
434             .name = "extfeature_ecx",   /* cpuid 8000_0001.ecx */
435             .type = QEMU_OPT_STRING,
436         },{
437             .name = "xlevel",
438             .type = QEMU_OPT_NUMBER,
439         },{
440             .name = "model_id",
441             .type = QEMU_OPT_STRING,
442         },{
443             .name = "vendor_override",
444             .type = QEMU_OPT_NUMBER,
445         },
446         { /* end of list */ }
447     },
448 };
449
450 QemuOptsList qemu_spice_opts = {
451     .name = "spice",
452     .head = QTAILQ_HEAD_INITIALIZER(qemu_spice_opts.head),
453     .desc = {
454         {
455             .name = "port",
456             .type = QEMU_OPT_NUMBER,
457         },{
458             .name = "tls-port",
459             .type = QEMU_OPT_NUMBER,
460         },{
461             .name = "addr",
462             .type = QEMU_OPT_STRING,
463         },{
464             .name = "ipv4",
465             .type = QEMU_OPT_BOOL,
466         },{
467             .name = "ipv6",
468             .type = QEMU_OPT_BOOL,
469         },{
470             .name = "password",
471             .type = QEMU_OPT_STRING,
472         },{
473             .name = "disable-ticketing",
474             .type = QEMU_OPT_BOOL,
475         },{
476             .name = "disable-copy-paste",
477             .type = QEMU_OPT_BOOL,
478         },{
479             .name = "sasl",
480             .type = QEMU_OPT_BOOL,
481         },{
482             .name = "x509-dir",
483             .type = QEMU_OPT_STRING,
484         },{
485             .name = "x509-key-file",
486             .type = QEMU_OPT_STRING,
487         },{
488             .name = "x509-key-password",
489             .type = QEMU_OPT_STRING,
490         },{
491             .name = "x509-cert-file",
492             .type = QEMU_OPT_STRING,
493         },{
494             .name = "x509-cacert-file",
495             .type = QEMU_OPT_STRING,
496         },{
497             .name = "x509-dh-key-file",
498             .type = QEMU_OPT_STRING,
499         },{
500             .name = "tls-ciphers",
501             .type = QEMU_OPT_STRING,
502         },{
503             .name = "tls-channel",
504             .type = QEMU_OPT_STRING,
505         },{
506             .name = "plaintext-channel",
507             .type = QEMU_OPT_STRING,
508         },{
509             .name = "image-compression",
510             .type = QEMU_OPT_STRING,
511         },{
512             .name = "jpeg-wan-compression",
513             .type = QEMU_OPT_STRING,
514         },{
515             .name = "zlib-glz-wan-compression",
516             .type = QEMU_OPT_STRING,
517         },{
518             .name = "streaming-video",
519             .type = QEMU_OPT_STRING,
520         },{
521             .name = "agent-mouse",
522             .type = QEMU_OPT_BOOL,
523         },{
524             .name = "playback-compression",
525             .type = QEMU_OPT_BOOL,
526         },
527         { /* end of list */ }
528     },
529 };
530
531 QemuOptsList qemu_option_rom_opts = {
532     .name = "option-rom",
533     .implied_opt_name = "romfile",
534     .head = QTAILQ_HEAD_INITIALIZER(qemu_option_rom_opts.head),
535     .desc = {
536         {
537             .name = "bootindex",
538             .type = QEMU_OPT_NUMBER,
539         }, {
540             .name = "romfile",
541             .type = QEMU_OPT_STRING,
542         },
543         { /* end of list */ }
544     },
545 };
546
547 static QemuOptsList qemu_machine_opts = {
548     .name = "machine",
549     .implied_opt_name = "type",
550     .merge_lists = true,
551     .head = QTAILQ_HEAD_INITIALIZER(qemu_machine_opts.head),
552     .desc = {
553         {
554             .name = "type",
555             .type = QEMU_OPT_STRING,
556             .help = "emulated machine"
557         }, {
558             .name = "accel",
559             .type = QEMU_OPT_STRING,
560             .help = "accelerator list",
561         }, {
562             .name = "kernel_irqchip",
563             .type = QEMU_OPT_BOOL,
564             .help = "use KVM in-kernel irqchip",
565         }, {
566             .name = "kvm_shadow_mem",
567             .type = QEMU_OPT_SIZE,
568             .help = "KVM shadow MMU size",
569         }, {
570             .name = "kernel",
571             .type = QEMU_OPT_STRING,
572             .help = "Linux kernel image file",
573         }, {
574             .name = "initrd",
575             .type = QEMU_OPT_STRING,
576             .help = "Linux initial ramdisk file",
577         }, {
578             .name = "append",
579             .type = QEMU_OPT_STRING,
580             .help = "Linux kernel command line",
581         }, {
582             .name = "dtb",
583             .type = QEMU_OPT_STRING,
584             .help = "Linux kernel device tree file",
585         },
586         { /* End of list */ }
587     },
588 };
589
590 QemuOptsList qemu_boot_opts = {
591     .name = "boot-opts",
592     .head = QTAILQ_HEAD_INITIALIZER(qemu_boot_opts.head),
593     .desc = {
594         /* the three names below are not used now */
595         {
596             .name = "order",
597             .type = QEMU_OPT_STRING,
598         }, {
599             .name = "once",
600             .type = QEMU_OPT_STRING,
601         }, {
602             .name = "menu",
603             .type = QEMU_OPT_STRING,
604         /* following are really used */
605         }, {
606             .name = "splash",
607             .type = QEMU_OPT_STRING,
608         }, {
609             .name = "splash-time",
610             .type = QEMU_OPT_STRING,
611         },
612         { /*End of list */ }
613     },
614 };
615
616 static QemuOptsList *vm_config_groups[32] = {
617     &qemu_drive_opts,
618     &qemu_chardev_opts,
619     &qemu_device_opts,
620     &qemu_netdev_opts,
621     &qemu_net_opts,
622     &qemu_rtc_opts,
623     &qemu_global_opts,
624     &qemu_mon_opts,
625     &qemu_cpudef_opts,
626     &qemu_trace_opts,
627     &qemu_option_rom_opts,
628     &qemu_machine_opts,
629     &qemu_boot_opts,
630     &qemu_iscsi_opts,
631     NULL,
632 };
633
634 static QemuOptsList *find_list(QemuOptsList **lists, const char *group)
635 {
636     int i;
637
638     for (i = 0; lists[i] != NULL; i++) {
639         if (strcmp(lists[i]->name, group) == 0)
640             break;
641     }
642     if (lists[i] == NULL) {
643         error_report("there is no option group \"%s\"", group);
644     }
645     return lists[i];
646 }
647
648 QemuOptsList *qemu_find_opts(const char *group)
649 {
650     return find_list(vm_config_groups, group);
651 }
652
653 void qemu_add_opts(QemuOptsList *list)
654 {
655     int entries, i;
656
657     entries = ARRAY_SIZE(vm_config_groups);
658     entries--; /* keep list NULL terminated */
659     for (i = 0; i < entries; i++) {
660         if (vm_config_groups[i] == NULL) {
661             vm_config_groups[i] = list;
662             return;
663         }
664     }
665     fprintf(stderr, "ran out of space in vm_config_groups");
666     abort();
667 }
668
669 int qemu_set_option(const char *str)
670 {
671     char group[64], id[64], arg[64];
672     QemuOptsList *list;
673     QemuOpts *opts;
674     int rc, offset;
675
676     rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
677     if (rc < 3 || str[offset] != '=') {
678         error_report("can't parse: \"%s\"", str);
679         return -1;
680     }
681
682     list = qemu_find_opts(group);
683     if (list == NULL) {
684         return -1;
685     }
686
687     opts = qemu_opts_find(list, id);
688     if (!opts) {
689         error_report("there is no %s \"%s\" defined",
690                      list->name, id);
691         return -1;
692     }
693
694     if (qemu_opt_set(opts, arg, str+offset+1) == -1) {
695         return -1;
696     }
697     return 0;
698 }
699
700 int qemu_global_option(const char *str)
701 {
702     char driver[64], property[64];
703     QemuOpts *opts;
704     int rc, offset;
705
706     rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
707     if (rc < 2 || str[offset] != '=') {
708         error_report("can't parse: \"%s\"", str);
709         return -1;
710     }
711
712     opts = qemu_opts_create(&qemu_global_opts, NULL, 0);
713     qemu_opt_set(opts, "driver", driver);
714     qemu_opt_set(opts, "property", property);
715     qemu_opt_set(opts, "value", str+offset+1);
716     return 0;
717 }
718
719 struct ConfigWriteData {
720     QemuOptsList *list;
721     FILE *fp;
722 };
723
724 static int config_write_opt(const char *name, const char *value, void *opaque)
725 {
726     struct ConfigWriteData *data = opaque;
727
728     fprintf(data->fp, "  %s = \"%s\"\n", name, value);
729     return 0;
730 }
731
732 static int config_write_opts(QemuOpts *opts, void *opaque)
733 {
734     struct ConfigWriteData *data = opaque;
735     const char *id = qemu_opts_id(opts);
736
737     if (id) {
738         fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id);
739     } else {
740         fprintf(data->fp, "[%s]\n", data->list->name);
741     }
742     qemu_opt_foreach(opts, config_write_opt, data, 0);
743     fprintf(data->fp, "\n");
744     return 0;
745 }
746
747 void qemu_config_write(FILE *fp)
748 {
749     struct ConfigWriteData data = { .fp = fp };
750     QemuOptsList **lists = vm_config_groups;
751     int i;
752
753     fprintf(fp, "# qemu config file\n\n");
754     for (i = 0; lists[i] != NULL; i++) {
755         data.list = lists[i];
756         qemu_opts_foreach(data.list, config_write_opts, &data, 0);
757     }
758 }
759
760 int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
761 {
762     char line[1024], group[64], id[64], arg[64], value[1024];
763     Location loc;
764     QemuOptsList *list = NULL;
765     QemuOpts *opts = NULL;
766     int res = -1, lno = 0;
767
768     loc_push_none(&loc);
769     while (fgets(line, sizeof(line), fp) != NULL) {
770         loc_set_file(fname, ++lno);
771         if (line[0] == '\n') {
772             /* skip empty lines */
773             continue;
774         }
775         if (line[0] == '#') {
776             /* comment */
777             continue;
778         }
779         if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
780             /* group with id */
781             list = find_list(lists, group);
782             if (list == NULL)
783                 goto out;
784             opts = qemu_opts_create(list, id, 1);
785             continue;
786         }
787         if (sscanf(line, "[%63[^]]]", group) == 1) {
788             /* group without id */
789             list = find_list(lists, group);
790             if (list == NULL)
791                 goto out;
792             opts = qemu_opts_create(list, NULL, 0);
793             continue;
794         }
795         if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
796             /* arg = value */
797             if (opts == NULL) {
798                 error_report("no group defined");
799                 goto out;
800             }
801             if (qemu_opt_set(opts, arg, value) != 0) {
802                 goto out;
803             }
804             continue;
805         }
806         error_report("parse error");
807         goto out;
808     }
809     if (ferror(fp)) {
810         error_report("error reading file");
811         goto out;
812     }
813     res = 0;
814 out:
815     loc_pop(&loc);
816     return res;
817 }
818
819 int qemu_read_config_file(const char *filename)
820 {
821     FILE *f = fopen(filename, "r");
822     int ret;
823
824     if (f == NULL) {
825         return -errno;
826     }
827
828     ret = qemu_config_parse(f, vm_config_groups, filename);
829     fclose(f);
830
831     if (ret == 0) {
832         return 0;
833     } else {
834         return -EINVAL;
835     }
836 }
This page took 0.07059 seconds and 4 git commands to generate.