Annotation of qemu/qemu-config.c, revision 1.1.1.3

1.1       root        1: #include "qemu-common.h"
1.1.1.2   root        2: #include "qemu-error.h"
1.1       root        3: #include "qemu-option.h"
                      4: #include "qemu-config.h"
                      5: #include "sysemu.h"
                      6: #include "hw/qdev.h"
                      7: 
1.1.1.3 ! root        8: static QemuOptsList qemu_drive_opts = {
1.1       root        9:     .name = "drive",
                     10:     .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head),
                     11:     .desc = {
                     12:         {
                     13:             .name = "bus",
                     14:             .type = QEMU_OPT_NUMBER,
                     15:             .help = "bus number",
                     16:         },{
                     17:             .name = "unit",
                     18:             .type = QEMU_OPT_NUMBER,
                     19:             .help = "unit number (i.e. lun for scsi)",
                     20:         },{
                     21:             .name = "if",
                     22:             .type = QEMU_OPT_STRING,
                     23:             .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
                     24:         },{
                     25:             .name = "index",
                     26:             .type = QEMU_OPT_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:         },{
                     51:             .name = "file",
                     52:             .type = QEMU_OPT_STRING,
                     53:             .help = "disk image",
                     54:         },{
                     55:             .name = "cache",
                     56:             .type = QEMU_OPT_STRING,
1.1.1.2   root       57:             .help = "host cache usage (none, writeback, writethrough, unsafe)",
1.1       root       58:         },{
                     59:             .name = "aio",
                     60:             .type = QEMU_OPT_STRING,
                     61:             .help = "host AIO implementation (threads, native)",
                     62:         },{
                     63:             .name = "format",
                     64:             .type = QEMU_OPT_STRING,
                     65:             .help = "disk format (raw, qcow2, ...)",
                     66:         },{
                     67:             .name = "serial",
                     68:             .type = QEMU_OPT_STRING,
                     69:         },{
                     70:             .name = "rerror",
                     71:             .type = QEMU_OPT_STRING,
                     72:         },{
                     73:             .name = "werror",
                     74:             .type = QEMU_OPT_STRING,
                     75:         },{
                     76:             .name = "addr",
                     77:             .type = QEMU_OPT_STRING,
                     78:             .help = "pci address (virtio only)",
                     79:         },{
                     80:             .name = "readonly",
                     81:             .type = QEMU_OPT_BOOL,
                     82:         },
1.1.1.3 ! root       83:         { /* end of list */ }
1.1       root       84:     },
                     85: };
                     86: 
1.1.1.3 ! root       87: static QemuOptsList qemu_chardev_opts = {
1.1       root       88:     .name = "chardev",
1.1.1.2   root       89:     .implied_opt_name = "backend",
1.1       root       90:     .head = QTAILQ_HEAD_INITIALIZER(qemu_chardev_opts.head),
                     91:     .desc = {
                     92:         {
                     93:             .name = "backend",
                     94:             .type = QEMU_OPT_STRING,
                     95:         },{
                     96:             .name = "path",
                     97:             .type = QEMU_OPT_STRING,
                     98:         },{
                     99:             .name = "host",
                    100:             .type = QEMU_OPT_STRING,
                    101:         },{
                    102:             .name = "port",
                    103:             .type = QEMU_OPT_STRING,
                    104:         },{
                    105:             .name = "localaddr",
                    106:             .type = QEMU_OPT_STRING,
                    107:         },{
                    108:             .name = "localport",
                    109:             .type = QEMU_OPT_STRING,
                    110:         },{
                    111:             .name = "to",
                    112:             .type = QEMU_OPT_NUMBER,
                    113:         },{
                    114:             .name = "ipv4",
                    115:             .type = QEMU_OPT_BOOL,
                    116:         },{
                    117:             .name = "ipv6",
                    118:             .type = QEMU_OPT_BOOL,
                    119:         },{
                    120:             .name = "wait",
                    121:             .type = QEMU_OPT_BOOL,
                    122:         },{
                    123:             .name = "server",
                    124:             .type = QEMU_OPT_BOOL,
                    125:         },{
                    126:             .name = "delay",
                    127:             .type = QEMU_OPT_BOOL,
                    128:         },{
                    129:             .name = "telnet",
                    130:             .type = QEMU_OPT_BOOL,
                    131:         },{
                    132:             .name = "width",
                    133:             .type = QEMU_OPT_NUMBER,
                    134:         },{
                    135:             .name = "height",
                    136:             .type = QEMU_OPT_NUMBER,
                    137:         },{
                    138:             .name = "cols",
                    139:             .type = QEMU_OPT_NUMBER,
                    140:         },{
                    141:             .name = "rows",
                    142:             .type = QEMU_OPT_NUMBER,
                    143:         },{
                    144:             .name = "mux",
                    145:             .type = QEMU_OPT_BOOL,
                    146:         },{
                    147:             .name = "signal",
                    148:             .type = QEMU_OPT_BOOL,
1.1.1.3 ! root      149:         },{
        !           150:             .name = "name",
        !           151:             .type = QEMU_OPT_STRING,
        !           152:         },{
        !           153:             .name = "debug",
        !           154:             .type = QEMU_OPT_NUMBER,
1.1       root      155:         },
1.1.1.3 ! root      156:         { /* end of list */ }
1.1       root      157:     },
                    158: };
                    159: 
1.1.1.2   root      160: QemuOptsList qemu_fsdev_opts = {
                    161:     .name = "fsdev",
                    162:     .implied_opt_name = "fstype",
                    163:     .head = QTAILQ_HEAD_INITIALIZER(qemu_fsdev_opts.head),
                    164:     .desc = {
                    165:         {
                    166:             .name = "fstype",
                    167:             .type = QEMU_OPT_STRING,
                    168:         }, {
                    169:             .name = "path",
                    170:             .type = QEMU_OPT_STRING,
                    171:         }, {
                    172:             .name = "security_model",
                    173:             .type = QEMU_OPT_STRING,
                    174:         },
                    175:         { /*End of list */ }
                    176:     },
                    177: };
                    178: 
                    179: QemuOptsList qemu_virtfs_opts = {
                    180:     .name = "virtfs",
                    181:     .implied_opt_name = "fstype",
                    182:     .head = QTAILQ_HEAD_INITIALIZER(qemu_virtfs_opts.head),
                    183:     .desc = {
                    184:         {
                    185:             .name = "fstype",
                    186:             .type = QEMU_OPT_STRING,
                    187:         }, {
                    188:             .name = "path",
                    189:             .type = QEMU_OPT_STRING,
                    190:         }, {
                    191:             .name = "mount_tag",
                    192:             .type = QEMU_OPT_STRING,
                    193:         }, {
                    194:             .name = "security_model",
                    195:             .type = QEMU_OPT_STRING,
                    196:         },
                    197: 
                    198:         { /*End of list */ }
                    199:     },
                    200: };
                    201: 
1.1.1.3 ! root      202: static QemuOptsList qemu_device_opts = {
1.1       root      203:     .name = "device",
1.1.1.2   root      204:     .implied_opt_name = "driver",
1.1       root      205:     .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
                    206:     .desc = {
                    207:         /*
                    208:          * no elements => accept any
                    209:          * sanity checking will happen later
                    210:          * when setting device properties
                    211:          */
1.1.1.3 ! root      212:         { /* end of list */ }
1.1       root      213:     },
                    214: };
                    215: 
1.1.1.3 ! root      216: static QemuOptsList qemu_netdev_opts = {
1.1       root      217:     .name = "netdev",
1.1.1.2   root      218:     .implied_opt_name = "type",
1.1       root      219:     .head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head),
                    220:     .desc = {
                    221:         /*
                    222:          * no elements => accept any params
                    223:          * validation will happen later
                    224:          */
                    225:         { /* end of list */ }
                    226:     },
                    227: };
                    228: 
1.1.1.3 ! root      229: static QemuOptsList qemu_net_opts = {
1.1       root      230:     .name = "net",
1.1.1.2   root      231:     .implied_opt_name = "type",
1.1       root      232:     .head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head),
                    233:     .desc = {
                    234:         /*
                    235:          * no elements => accept any params
                    236:          * validation will happen later
                    237:          */
                    238:         { /* end of list */ }
                    239:     },
                    240: };
                    241: 
1.1.1.3 ! root      242: static QemuOptsList qemu_rtc_opts = {
1.1       root      243:     .name = "rtc",
                    244:     .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head),
                    245:     .desc = {
                    246:         {
                    247:             .name = "base",
                    248:             .type = QEMU_OPT_STRING,
                    249:         },{
                    250:             .name = "clock",
                    251:             .type = QEMU_OPT_STRING,
                    252:         },{
                    253:             .name = "driftfix",
                    254:             .type = QEMU_OPT_STRING,
                    255:         },
1.1.1.3 ! root      256:         { /* end of list */ }
1.1       root      257:     },
                    258: };
                    259: 
1.1.1.3 ! root      260: static QemuOptsList qemu_global_opts = {
1.1       root      261:     .name = "global",
                    262:     .head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
                    263:     .desc = {
                    264:         {
                    265:             .name = "driver",
                    266:             .type = QEMU_OPT_STRING,
                    267:         },{
                    268:             .name = "property",
                    269:             .type = QEMU_OPT_STRING,
                    270:         },{
                    271:             .name = "value",
                    272:             .type = QEMU_OPT_STRING,
                    273:         },
1.1.1.3 ! root      274:         { /* end of list */ }
1.1       root      275:     },
                    276: };
                    277: 
1.1.1.3 ! root      278: static QemuOptsList qemu_mon_opts = {
1.1       root      279:     .name = "mon",
1.1.1.2   root      280:     .implied_opt_name = "chardev",
1.1       root      281:     .head = QTAILQ_HEAD_INITIALIZER(qemu_mon_opts.head),
                    282:     .desc = {
                    283:         {
                    284:             .name = "mode",
                    285:             .type = QEMU_OPT_STRING,
                    286:         },{
                    287:             .name = "chardev",
                    288:             .type = QEMU_OPT_STRING,
                    289:         },{
                    290:             .name = "default",
                    291:             .type = QEMU_OPT_BOOL,
1.1.1.3 ! root      292:         },{
        !           293:             .name = "pretty",
        !           294:             .type = QEMU_OPT_BOOL,
        !           295:         },
        !           296:         { /* end of list */ }
        !           297:     },
        !           298: };
        !           299: 
        !           300: #ifdef CONFIG_SIMPLE_TRACE
        !           301: static QemuOptsList qemu_trace_opts = {
        !           302:     .name = "trace",
        !           303:     .implied_opt_name = "trace",
        !           304:     .head = QTAILQ_HEAD_INITIALIZER(qemu_trace_opts.head),
        !           305:     .desc = {
        !           306:         {
        !           307:             .name = "file",
        !           308:             .type = QEMU_OPT_STRING,
1.1       root      309:         },
                    310:         { /* end if list */ }
                    311:     },
                    312: };
1.1.1.3 ! root      313: #endif
1.1       root      314: 
1.1.1.3 ! root      315: static QemuOptsList qemu_cpudef_opts = {
1.1.1.2   root      316:     .name = "cpudef",
                    317:     .head = QTAILQ_HEAD_INITIALIZER(qemu_cpudef_opts.head),
                    318:     .desc = {
                    319:         {
                    320:             .name = "name",
                    321:             .type = QEMU_OPT_STRING,
                    322:         },{
                    323:             .name = "level",
                    324:             .type = QEMU_OPT_NUMBER,
                    325:         },{
                    326:             .name = "vendor",
                    327:             .type = QEMU_OPT_STRING,
                    328:         },{
                    329:             .name = "family",
                    330:             .type = QEMU_OPT_NUMBER,
                    331:         },{
                    332:             .name = "model",
                    333:             .type = QEMU_OPT_NUMBER,
                    334:         },{
                    335:             .name = "stepping",
                    336:             .type = QEMU_OPT_NUMBER,
                    337:         },{
                    338:             .name = "feature_edx",      /* cpuid 0000_0001.edx */
                    339:             .type = QEMU_OPT_STRING,
                    340:         },{
                    341:             .name = "feature_ecx",      /* cpuid 0000_0001.ecx */
                    342:             .type = QEMU_OPT_STRING,
                    343:         },{
                    344:             .name = "extfeature_edx",   /* cpuid 8000_0001.edx */
                    345:             .type = QEMU_OPT_STRING,
                    346:         },{
                    347:             .name = "extfeature_ecx",   /* cpuid 8000_0001.ecx */
                    348:             .type = QEMU_OPT_STRING,
                    349:         },{
                    350:             .name = "xlevel",
                    351:             .type = QEMU_OPT_NUMBER,
                    352:         },{
                    353:             .name = "model_id",
                    354:             .type = QEMU_OPT_STRING,
                    355:         },{
                    356:             .name = "vendor_override",
                    357:             .type = QEMU_OPT_NUMBER,
                    358:         },
                    359:         { /* end of list */ }
                    360:     },
                    361: };
                    362: 
1.1.1.3 ! root      363: QemuOptsList qemu_spice_opts = {
        !           364:     .name = "spice",
        !           365:     .head = QTAILQ_HEAD_INITIALIZER(qemu_spice_opts.head),
        !           366:     .desc = {
        !           367:         {
        !           368:             .name = "port",
        !           369:             .type = QEMU_OPT_NUMBER,
        !           370:         },{
        !           371:             .name = "tls-port",
        !           372:             .type = QEMU_OPT_NUMBER,
        !           373:         },{
        !           374:             .name = "addr",
        !           375:             .type = QEMU_OPT_STRING,
        !           376:         },{
        !           377:             .name = "ipv4",
        !           378:             .type = QEMU_OPT_BOOL,
        !           379:         },{
        !           380:             .name = "ipv6",
        !           381:             .type = QEMU_OPT_BOOL,
        !           382:         },{
        !           383:             .name = "password",
        !           384:             .type = QEMU_OPT_STRING,
        !           385:         },{
        !           386:             .name = "disable-ticketing",
        !           387:             .type = QEMU_OPT_BOOL,
        !           388:         },{
        !           389:             .name = "x509-dir",
        !           390:             .type = QEMU_OPT_STRING,
        !           391:         },{
        !           392:             .name = "x509-key-file",
        !           393:             .type = QEMU_OPT_STRING,
        !           394:         },{
        !           395:             .name = "x509-key-password",
        !           396:             .type = QEMU_OPT_STRING,
        !           397:         },{
        !           398:             .name = "x509-cert-file",
        !           399:             .type = QEMU_OPT_STRING,
        !           400:         },{
        !           401:             .name = "x509-cacert-file",
        !           402:             .type = QEMU_OPT_STRING,
        !           403:         },{
        !           404:             .name = "x509-dh-key-file",
        !           405:             .type = QEMU_OPT_STRING,
        !           406:         },{
        !           407:             .name = "tls-ciphers",
        !           408:             .type = QEMU_OPT_STRING,
        !           409:         },{
        !           410:             .name = "tls-channel",
        !           411:             .type = QEMU_OPT_STRING,
        !           412:         },{
        !           413:             .name = "plaintext-channel",
        !           414:             .type = QEMU_OPT_STRING,
        !           415:         },{
        !           416:             .name = "image-compression",
        !           417:             .type = QEMU_OPT_STRING,
        !           418:         },{
        !           419:             .name = "jpeg-wan-compression",
        !           420:             .type = QEMU_OPT_STRING,
        !           421:         },{
        !           422:             .name = "zlib-glz-wan-compression",
        !           423:             .type = QEMU_OPT_STRING,
        !           424:         },{
        !           425:             .name = "streaming-video",
        !           426:             .type = QEMU_OPT_STRING,
        !           427:         },{
        !           428:             .name = "agent-mouse",
        !           429:             .type = QEMU_OPT_BOOL,
        !           430:         },{
        !           431:             .name = "playback-compression",
        !           432:             .type = QEMU_OPT_BOOL,
        !           433:         },
        !           434:         { /* end if list */ }
        !           435:     },
        !           436: };
        !           437: 
        !           438: QemuOptsList qemu_option_rom_opts = {
        !           439:     .name = "option-rom",
        !           440:     .implied_opt_name = "romfile",
        !           441:     .head = QTAILQ_HEAD_INITIALIZER(qemu_option_rom_opts.head),
        !           442:     .desc = {
        !           443:         {
        !           444:             .name = "bootindex",
        !           445:             .type = QEMU_OPT_NUMBER,
        !           446:         }, {
        !           447:             .name = "romfile",
        !           448:             .type = QEMU_OPT_STRING,
        !           449:         },
        !           450:         { /* end if list */ }
        !           451:     },
        !           452: };
        !           453: 
        !           454: static QemuOptsList *vm_config_groups[32] = {
1.1       root      455:     &qemu_drive_opts,
                    456:     &qemu_chardev_opts,
                    457:     &qemu_device_opts,
                    458:     &qemu_netdev_opts,
                    459:     &qemu_net_opts,
                    460:     &qemu_rtc_opts,
                    461:     &qemu_global_opts,
                    462:     &qemu_mon_opts,
1.1.1.2   root      463:     &qemu_cpudef_opts,
1.1.1.3 ! root      464: #ifdef CONFIG_SIMPLE_TRACE
        !           465:     &qemu_trace_opts,
        !           466: #endif
        !           467:     &qemu_option_rom_opts,
1.1       root      468:     NULL,
                    469: };
                    470: 
1.1.1.2   root      471: static QemuOptsList *find_list(QemuOptsList **lists, const char *group)
1.1       root      472: {
                    473:     int i;
                    474: 
                    475:     for (i = 0; lists[i] != NULL; i++) {
                    476:         if (strcmp(lists[i]->name, group) == 0)
                    477:             break;
                    478:     }
                    479:     if (lists[i] == NULL) {
1.1.1.2   root      480:         error_report("there is no option group \"%s\"", group);
1.1       root      481:     }
                    482:     return lists[i];
                    483: }
                    484: 
1.1.1.2   root      485: QemuOptsList *qemu_find_opts(const char *group)
                    486: {
                    487:     return find_list(vm_config_groups, group);
                    488: }
                    489: 
1.1.1.3 ! root      490: void qemu_add_opts(QemuOptsList *list)
        !           491: {
        !           492:     int entries, i;
        !           493: 
        !           494:     entries = ARRAY_SIZE(vm_config_groups);
        !           495:     entries--; /* keep list NULL terminated */
        !           496:     for (i = 0; i < entries; i++) {
        !           497:         if (vm_config_groups[i] == NULL) {
        !           498:             vm_config_groups[i] = list;
        !           499:             return;
        !           500:         }
        !           501:     }
        !           502:     fprintf(stderr, "ran out of space in vm_config_groups");
        !           503:     abort();
        !           504: }
        !           505: 
1.1       root      506: int qemu_set_option(const char *str)
                    507: {
                    508:     char group[64], id[64], arg[64];
                    509:     QemuOptsList *list;
                    510:     QemuOpts *opts;
                    511:     int rc, offset;
                    512: 
                    513:     rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
                    514:     if (rc < 3 || str[offset] != '=') {
1.1.1.2   root      515:         error_report("can't parse: \"%s\"", str);
1.1       root      516:         return -1;
                    517:     }
                    518: 
1.1.1.2   root      519:     list = qemu_find_opts(group);
1.1       root      520:     if (list == NULL) {
                    521:         return -1;
                    522:     }
                    523: 
                    524:     opts = qemu_opts_find(list, id);
                    525:     if (!opts) {
1.1.1.2   root      526:         error_report("there is no %s \"%s\" defined",
                    527:                      list->name, id);
1.1       root      528:         return -1;
                    529:     }
                    530: 
                    531:     if (qemu_opt_set(opts, arg, str+offset+1) == -1) {
                    532:         return -1;
                    533:     }
                    534:     return 0;
                    535: }
                    536: 
                    537: int qemu_global_option(const char *str)
                    538: {
                    539:     char driver[64], property[64];
                    540:     QemuOpts *opts;
                    541:     int rc, offset;
                    542: 
                    543:     rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
                    544:     if (rc < 2 || str[offset] != '=') {
1.1.1.2   root      545:         error_report("can't parse: \"%s\"", str);
1.1       root      546:         return -1;
                    547:     }
                    548: 
                    549:     opts = qemu_opts_create(&qemu_global_opts, NULL, 0);
                    550:     qemu_opt_set(opts, "driver", driver);
                    551:     qemu_opt_set(opts, "property", property);
                    552:     qemu_opt_set(opts, "value", str+offset+1);
                    553:     return 0;
                    554: }
                    555: 
                    556: struct ConfigWriteData {
                    557:     QemuOptsList *list;
                    558:     FILE *fp;
                    559: };
                    560: 
                    561: static int config_write_opt(const char *name, const char *value, void *opaque)
                    562: {
                    563:     struct ConfigWriteData *data = opaque;
                    564: 
                    565:     fprintf(data->fp, "  %s = \"%s\"\n", name, value);
                    566:     return 0;
                    567: }
                    568: 
                    569: static int config_write_opts(QemuOpts *opts, void *opaque)
                    570: {
                    571:     struct ConfigWriteData *data = opaque;
                    572:     const char *id = qemu_opts_id(opts);
                    573: 
                    574:     if (id) {
                    575:         fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id);
                    576:     } else {
                    577:         fprintf(data->fp, "[%s]\n", data->list->name);
                    578:     }
                    579:     qemu_opt_foreach(opts, config_write_opt, data, 0);
                    580:     fprintf(data->fp, "\n");
                    581:     return 0;
                    582: }
                    583: 
                    584: void qemu_config_write(FILE *fp)
                    585: {
                    586:     struct ConfigWriteData data = { .fp = fp };
1.1.1.2   root      587:     QemuOptsList **lists = vm_config_groups;
1.1       root      588:     int i;
                    589: 
                    590:     fprintf(fp, "# qemu config file\n\n");
                    591:     for (i = 0; lists[i] != NULL; i++) {
                    592:         data.list = lists[i];
                    593:         qemu_opts_foreach(data.list, config_write_opts, &data, 0);
                    594:     }
                    595: }
                    596: 
1.1.1.2   root      597: int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
1.1       root      598: {
                    599:     char line[1024], group[64], id[64], arg[64], value[1024];
1.1.1.2   root      600:     Location loc;
1.1       root      601:     QemuOptsList *list = NULL;
                    602:     QemuOpts *opts = NULL;
1.1.1.2   root      603:     int res = -1, lno = 0;
1.1       root      604: 
1.1.1.2   root      605:     loc_push_none(&loc);
1.1       root      606:     while (fgets(line, sizeof(line), fp) != NULL) {
1.1.1.2   root      607:         loc_set_file(fname, ++lno);
1.1       root      608:         if (line[0] == '\n') {
                    609:             /* skip empty lines */
                    610:             continue;
                    611:         }
                    612:         if (line[0] == '#') {
                    613:             /* comment */
                    614:             continue;
                    615:         }
                    616:         if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
                    617:             /* group with id */
1.1.1.2   root      618:             list = find_list(lists, group);
1.1       root      619:             if (list == NULL)
1.1.1.2   root      620:                 goto out;
1.1       root      621:             opts = qemu_opts_create(list, id, 1);
                    622:             continue;
                    623:         }
                    624:         if (sscanf(line, "[%63[^]]]", group) == 1) {
                    625:             /* group without id */
1.1.1.2   root      626:             list = find_list(lists, group);
1.1       root      627:             if (list == NULL)
1.1.1.2   root      628:                 goto out;
1.1       root      629:             opts = qemu_opts_create(list, NULL, 0);
                    630:             continue;
                    631:         }
                    632:         if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
                    633:             /* arg = value */
                    634:             if (opts == NULL) {
1.1.1.2   root      635:                 error_report("no group defined");
                    636:                 goto out;
1.1       root      637:             }
                    638:             if (qemu_opt_set(opts, arg, value) != 0) {
1.1.1.2   root      639:                 goto out;
1.1       root      640:             }
                    641:             continue;
                    642:         }
1.1.1.2   root      643:         error_report("parse error");
                    644:         goto out;
                    645:     }
                    646:     if (ferror(fp)) {
                    647:         error_report("error reading file");
                    648:         goto out;
                    649:     }
                    650:     res = 0;
                    651: out:
                    652:     loc_pop(&loc);
                    653:     return res;
                    654: }
                    655: 
                    656: int qemu_read_config_file(const char *filename)
                    657: {
                    658:     FILE *f = fopen(filename, "r");
                    659:     int ret;
                    660: 
                    661:     if (f == NULL) {
                    662:         return -errno;
                    663:     }
                    664: 
                    665:     ret = qemu_config_parse(f, vm_config_groups, filename);
                    666:     fclose(f);
                    667: 
                    668:     if (ret == 0) {
                    669:         return 0;
                    670:     } else {
                    671:         return -EINVAL;
1.1       root      672:     }
                    673: }

unix.superglobalmegacorp.com