Annotation of qemu/qemu-option.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Commandline option parsing functions
                      3:  *
                      4:  * Copyright (c) 2003-2008 Fabrice Bellard
                      5:  * Copyright (c) 2009 Kevin Wolf <kwolf@redhat.com>
                      6:  *
                      7:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      8:  * of this software and associated documentation files (the "Software"), to deal
                      9:  * in the Software without restriction, including without limitation the rights
                     10:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     11:  * copies of the Software, and to permit persons to whom the Software is
                     12:  * furnished to do so, subject to the following conditions:
                     13:  *
                     14:  * The above copyright notice and this permission notice shall be included in
                     15:  * all copies or substantial portions of the Software.
                     16:  *
                     17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     18:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     19:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     20:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     21:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     22:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     23:  * THE SOFTWARE.
                     24:  */
                     25: 
                     26: #include <stdio.h>
                     27: #include <string.h>
                     28: 
                     29: #include "qemu-common.h"
                     30: #include "qemu-option.h"
                     31: 
                     32: /*
                     33:  * Extracts the name of an option from the parameter string (p points at the
                     34:  * first byte of the option name)
                     35:  *
                     36:  * The option name is delimited by delim (usually , or =) or the string end
                     37:  * and is copied into buf. If the option name is longer than buf_size, it is
                     38:  * truncated. buf is always zero terminated.
                     39:  *
                     40:  * The return value is the position of the delimiter/zero byte after the option
                     41:  * name in p.
                     42:  */
                     43: const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
                     44: {
                     45:     char *q;
                     46: 
                     47:     q = buf;
                     48:     while (*p != '\0' && *p != delim) {
                     49:         if (q && (q - buf) < buf_size - 1)
                     50:             *q++ = *p;
                     51:         p++;
                     52:     }
                     53:     if (q)
                     54:         *q = '\0';
                     55: 
                     56:     return p;
                     57: }
                     58: 
                     59: /*
                     60:  * Extracts the value of an option from the parameter string p (p points at the
                     61:  * first byte of the option value)
                     62:  *
                     63:  * This function is comparable to get_opt_name with the difference that the
                     64:  * delimiter is fixed to be comma which starts a new option. To specify an
                     65:  * option value that contains commas, double each comma.
                     66:  */
                     67: const char *get_opt_value(char *buf, int buf_size, const char *p)
                     68: {
                     69:     char *q;
                     70: 
                     71:     q = buf;
                     72:     while (*p != '\0') {
                     73:         if (*p == ',') {
                     74:             if (*(p + 1) != ',')
                     75:                 break;
                     76:             p++;
                     77:         }
                     78:         if (q && (q - buf) < buf_size - 1)
                     79:             *q++ = *p;
                     80:         p++;
                     81:     }
                     82:     if (q)
                     83:         *q = '\0';
                     84: 
                     85:     return p;
                     86: }
                     87: 
1.1.1.2 ! root       88: int get_next_param_value(char *buf, int buf_size,
        !            89:                          const char *tag, const char **pstr)
        !            90: {
        !            91:     const char *p;
        !            92:     char option[128];
        !            93: 
        !            94:     p = *pstr;
        !            95:     for(;;) {
        !            96:         p = get_opt_name(option, sizeof(option), p, '=');
        !            97:         if (*p != '=')
        !            98:             break;
        !            99:         p++;
        !           100:         if (!strcmp(tag, option)) {
        !           101:             *pstr = get_opt_value(buf, buf_size, p);
        !           102:             if (**pstr == ',') {
        !           103:                 (*pstr)++;
        !           104:             }
        !           105:             return strlen(buf);
        !           106:         } else {
        !           107:             p = get_opt_value(NULL, 0, p);
        !           108:         }
        !           109:         if (*p != ',')
        !           110:             break;
        !           111:         p++;
        !           112:     }
        !           113:     return 0;
        !           114: }
        !           115: 
        !           116: int get_param_value(char *buf, int buf_size,
        !           117:                     const char *tag, const char *str)
        !           118: {
        !           119:     return get_next_param_value(buf, buf_size, tag, &str);
        !           120: }
        !           121: 
        !           122: int check_params(char *buf, int buf_size,
        !           123:                  const char * const *params, const char *str)
        !           124: {
        !           125:     const char *p;
        !           126:     int i;
        !           127: 
        !           128:     p = str;
        !           129:     while (*p != '\0') {
        !           130:         p = get_opt_name(buf, buf_size, p, '=');
        !           131:         if (*p != '=') {
        !           132:             return -1;
        !           133:         }
        !           134:         p++;
        !           135:         for (i = 0; params[i] != NULL; i++) {
        !           136:             if (!strcmp(params[i], buf)) {
        !           137:                 break;
        !           138:             }
        !           139:         }
        !           140:         if (params[i] == NULL) {
        !           141:             return -1;
        !           142:         }
        !           143:         p = get_opt_value(NULL, 0, p);
        !           144:         if (*p != ',') {
        !           145:             break;
        !           146:         }
        !           147:         p++;
        !           148:     }
        !           149:     return 0;
        !           150: }
        !           151: 
1.1       root      152: /*
                    153:  * Searches an option list for an option with the given name
                    154:  */
                    155: QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
                    156:     const char *name)
                    157: {
                    158:     while (list && list->name) {
                    159:         if (!strcmp(list->name, name)) {
                    160:             return list;
                    161:         }
                    162:         list++;
                    163:     }
                    164: 
                    165:     return NULL;
                    166: }
                    167: 
1.1.1.2 ! root      168: static int parse_option_bool(const char *name, const char *value, int *ret)
        !           169: {
        !           170:     if (value != NULL) {
        !           171:         if (!strcmp(value, "on")) {
        !           172:             *ret = 1;
        !           173:         } else if (!strcmp(value, "off")) {
        !           174:             *ret = 0;
        !           175:         } else {
        !           176:             fprintf(stderr, "Option '%s': Use 'on' or 'off'\n", name);
        !           177:             return -1;
        !           178:         }
        !           179:     } else {
        !           180:         *ret = 1;
        !           181:     }
        !           182:     return 0;
        !           183: }
        !           184: 
        !           185: static int parse_option_number(const char *name, const char *value, uint64_t *ret)
        !           186: {
        !           187:     char *postfix;
        !           188:     uint64_t number;
        !           189: 
        !           190:     if (value != NULL) {
        !           191:         number = strtoull(value, &postfix, 0);
        !           192:         if (*postfix != '\0') {
        !           193:             fprintf(stderr, "Option '%s' needs a number as parameter\n", name);
        !           194:             return -1;
        !           195:         }
        !           196:         *ret = number;
        !           197:     } else {
        !           198:         fprintf(stderr, "Option '%s' needs a parameter\n", name);
        !           199:         return -1;
        !           200:     }
        !           201:     return 0;
        !           202: }
        !           203: 
        !           204: static int parse_option_size(const char *name, const char *value, uint64_t *ret)
        !           205: {
        !           206:     char *postfix;
        !           207:     double sizef;
        !           208: 
        !           209:     if (value != NULL) {
        !           210:         sizef = strtod(value, &postfix);
        !           211:         switch (*postfix) {
        !           212:         case 'T':
        !           213:             sizef *= 1024;
        !           214:         case 'G':
        !           215:             sizef *= 1024;
        !           216:         case 'M':
        !           217:             sizef *= 1024;
        !           218:         case 'K':
        !           219:         case 'k':
        !           220:             sizef *= 1024;
        !           221:         case 'b':
        !           222:         case '\0':
        !           223:             *ret = (uint64_t) sizef;
        !           224:             break;
        !           225:         default:
        !           226:             fprintf(stderr, "Option '%s' needs size as parameter\n", name);
        !           227:             fprintf(stderr, "You may use k, M, G or T suffixes for "
        !           228:                     "kilobytes, megabytes, gigabytes and terabytes.\n");
        !           229:             return -1;
        !           230:         }
        !           231:     } else {
        !           232:         fprintf(stderr, "Option '%s' needs a parameter\n", name);
        !           233:         return -1;
        !           234:     }
        !           235:     return 0;
        !           236: }
        !           237: 
1.1       root      238: /*
                    239:  * Sets the value of a parameter in a given option list. The parsing of the
                    240:  * value depends on the type of option:
                    241:  *
                    242:  * OPT_FLAG (uses value.n):
                    243:  *      If no value is given, the flag is set to 1.
                    244:  *      Otherwise the value must be "on" (set to 1) or "off" (set to 0)
                    245:  *
                    246:  * OPT_STRING (uses value.s):
                    247:  *      value is strdup()ed and assigned as option value
                    248:  *
                    249:  * OPT_SIZE (uses value.n):
                    250:  *      The value is converted to an integer. Suffixes for kilobytes etc. are
                    251:  *      allowed (powers of 1024).
                    252:  *
                    253:  * Returns 0 on succes, -1 in error cases
                    254:  */
                    255: int set_option_parameter(QEMUOptionParameter *list, const char *name,
                    256:     const char *value)
                    257: {
1.1.1.2 ! root      258:     int flag;
        !           259: 
1.1       root      260:     // Find a matching parameter
                    261:     list = get_option_parameter(list, name);
                    262:     if (list == NULL) {
                    263:         fprintf(stderr, "Unknown option '%s'\n", name);
                    264:         return -1;
                    265:     }
                    266: 
                    267:     // Process parameter
                    268:     switch (list->type) {
                    269:     case OPT_FLAG:
1.1.1.2 ! root      270:         if (parse_option_bool(name, value, &flag) == -1)
        !           271:             return -1;
        !           272:         list->value.n = flag;
1.1       root      273:         break;
                    274: 
                    275:     case OPT_STRING:
                    276:         if (value != NULL) {
1.1.1.2 ! root      277:             list->value.s = qemu_strdup(value);
1.1       root      278:         } else {
                    279:             fprintf(stderr, "Option '%s' needs a parameter\n", name);
                    280:             return -1;
                    281:         }
                    282:         break;
                    283: 
                    284:     case OPT_SIZE:
1.1.1.2 ! root      285:         if (parse_option_size(name, value, &list->value.n) == -1)
1.1       root      286:             return -1;
                    287:         break;
1.1.1.2 ! root      288: 
1.1       root      289:     default:
                    290:         fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
                    291:         return -1;
                    292:     }
                    293: 
                    294:     return 0;
                    295: }
                    296: 
                    297: /*
                    298:  * Sets the given parameter to an integer instead of a string.
                    299:  * This function cannot be used to set string options.
                    300:  *
                    301:  * Returns 0 on success, -1 in error cases
                    302:  */
                    303: int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
                    304:     uint64_t value)
                    305: {
                    306:     // Find a matching parameter
                    307:     list = get_option_parameter(list, name);
                    308:     if (list == NULL) {
                    309:         fprintf(stderr, "Unknown option '%s'\n", name);
                    310:         return -1;
                    311:     }
                    312: 
                    313:     // Process parameter
                    314:     switch (list->type) {
                    315:     case OPT_FLAG:
                    316:     case OPT_NUMBER:
                    317:     case OPT_SIZE:
                    318:         list->value.n = value;
                    319:         break;
                    320: 
                    321:     default:
                    322:         return -1;
                    323:     }
                    324: 
                    325:     return 0;
                    326: }
                    327: 
                    328: /*
                    329:  * Frees a option list. If it contains strings, the strings are freed as well.
                    330:  */
                    331: void free_option_parameters(QEMUOptionParameter *list)
                    332: {
                    333:     QEMUOptionParameter *cur = list;
                    334: 
                    335:     while (cur && cur->name) {
                    336:         if (cur->type == OPT_STRING) {
1.1.1.2 ! root      337:             qemu_free(cur->value.s);
1.1       root      338:         }
                    339:         cur++;
                    340:     }
                    341: 
1.1.1.2 ! root      342:     qemu_free(list);
1.1       root      343: }
                    344: 
                    345: /*
                    346:  * Parses a parameter string (param) into an option list (dest).
                    347:  *
                    348:  * list is the templace is. If dest is NULL, a new copy of list is created for
                    349:  * it. If list is NULL, this function fails.
                    350:  *
                    351:  * A parameter string consists of one or more parameters, separated by commas.
                    352:  * Each parameter consists of its name and possibly of a value. In the latter
                    353:  * case, the value is delimited by an = character. To specify a value which
                    354:  * contains commas, double each comma so it won't be recognized as the end of
                    355:  * the parameter.
                    356:  *
                    357:  * For more details of the parsing see above.
                    358:  *
                    359:  * Returns a pointer to the first element of dest (or the newly allocated copy)
                    360:  * or NULL in error cases
                    361:  */
                    362: QEMUOptionParameter *parse_option_parameters(const char *param,
                    363:     QEMUOptionParameter *list, QEMUOptionParameter *dest)
                    364: {
                    365:     QEMUOptionParameter *cur;
                    366:     QEMUOptionParameter *allocated = NULL;
                    367:     char name[256];
                    368:     char value[256];
                    369:     char *param_delim, *value_delim;
                    370:     char next_delim;
                    371:     size_t num_options;
                    372: 
                    373:     if (list == NULL) {
                    374:         return NULL;
                    375:     }
                    376: 
                    377:     if (dest == NULL) {
                    378:         // Count valid options
                    379:         num_options = 0;
                    380:         cur = list;
                    381:         while (cur->name) {
                    382:             num_options++;
                    383:             cur++;
                    384:         }
                    385: 
                    386:         // Create a copy of the option list to fill in values
                    387:         dest = qemu_mallocz((num_options + 1) * sizeof(QEMUOptionParameter));
                    388:         allocated = dest;
                    389:         memcpy(dest, list, (num_options + 1) * sizeof(QEMUOptionParameter));
                    390:     }
                    391: 
                    392:     while (*param) {
                    393: 
                    394:         // Find parameter name and value in the string
                    395:         param_delim = strchr(param, ',');
                    396:         value_delim = strchr(param, '=');
                    397: 
                    398:         if (value_delim && (value_delim < param_delim || !param_delim)) {
                    399:             next_delim = '=';
                    400:         } else {
                    401:             next_delim = ',';
                    402:             value_delim = NULL;
                    403:         }
                    404: 
                    405:         param = get_opt_name(name, sizeof(name), param, next_delim);
                    406:         if (value_delim) {
                    407:             param = get_opt_value(value, sizeof(value), param + 1);
                    408:         }
                    409:         if (*param != '\0') {
                    410:             param++;
                    411:         }
                    412: 
                    413:         // Set the parameter
                    414:         if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
                    415:             goto fail;
                    416:         }
                    417:     }
                    418: 
                    419:     return dest;
                    420: 
                    421: fail:
                    422:     // Only free the list if it was newly allocated
                    423:     free_option_parameters(allocated);
                    424:     return NULL;
                    425: }
                    426: 
                    427: /*
                    428:  * Prints all options of a list that have a value to stdout
                    429:  */
                    430: void print_option_parameters(QEMUOptionParameter *list)
                    431: {
                    432:     while (list && list->name) {
                    433:         switch (list->type) {
                    434:             case OPT_STRING:
                    435:                  if (list->value.s != NULL) {
                    436:                      printf("%s='%s' ", list->name, list->value.s);
                    437:                  }
                    438:                 break;
                    439:             case OPT_FLAG:
                    440:                 printf("%s=%s ", list->name, list->value.n ? "on" : "off");
                    441:                 break;
                    442:             case OPT_SIZE:
                    443:             case OPT_NUMBER:
                    444:                 printf("%s=%" PRId64 " ", list->name, list->value.n);
                    445:                 break;
                    446:             default:
                    447:                 printf("%s=(unkown type) ", list->name);
                    448:                 break;
                    449:         }
                    450:         list++;
                    451:     }
                    452: }
                    453: 
                    454: /*
                    455:  * Prints an overview of all available options
                    456:  */
                    457: void print_option_help(QEMUOptionParameter *list)
                    458: {
                    459:     printf("Supported options:\n");
                    460:     while (list && list->name) {
                    461:         printf("%-16s %s\n", list->name,
                    462:             list->help ? list->help : "No description available");
                    463:         list++;
                    464:     }
                    465: }
1.1.1.2 ! root      466: 
        !           467: /* ------------------------------------------------------------------ */
        !           468: 
        !           469: struct QemuOpt {
        !           470:     const char   *name;
        !           471:     const char   *str;
        !           472: 
        !           473:     QemuOptDesc  *desc;
        !           474:     union {
        !           475:         int      boolean;
        !           476:         uint64_t uint;
        !           477:     } value;
        !           478: 
        !           479:     QemuOpts     *opts;
        !           480:     QTAILQ_ENTRY(QemuOpt) next;
        !           481: };
        !           482: 
        !           483: struct QemuOpts {
        !           484:     char *id;
        !           485:     QemuOptsList *list;
        !           486:     QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
        !           487:     QTAILQ_ENTRY(QemuOpts) next;
        !           488: };
        !           489: 
        !           490: static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
        !           491: {
        !           492:     QemuOpt *opt;
        !           493: 
        !           494:     QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
        !           495:         if (strcmp(opt->name, name) != 0)
        !           496:             continue;
        !           497:         return opt;
        !           498:     }
        !           499:     return NULL;
        !           500: }
        !           501: 
        !           502: const char *qemu_opt_get(QemuOpts *opts, const char *name)
        !           503: {
        !           504:     QemuOpt *opt = qemu_opt_find(opts, name);
        !           505:     return opt ? opt->str : NULL;
        !           506: }
        !           507: 
        !           508: int qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval)
        !           509: {
        !           510:     QemuOpt *opt = qemu_opt_find(opts, name);
        !           511: 
        !           512:     if (opt == NULL)
        !           513:         return defval;
        !           514:     assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
        !           515:     return opt->value.boolean;
        !           516: }
        !           517: 
        !           518: uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
        !           519: {
        !           520:     QemuOpt *opt = qemu_opt_find(opts, name);
        !           521: 
        !           522:     if (opt == NULL)
        !           523:         return defval;
        !           524:     assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
        !           525:     return opt->value.uint;
        !           526: }
        !           527: 
        !           528: uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
        !           529: {
        !           530:     QemuOpt *opt = qemu_opt_find(opts, name);
        !           531: 
        !           532:     if (opt == NULL)
        !           533:         return defval;
        !           534:     assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
        !           535:     return opt->value.uint;
        !           536: }
        !           537: 
        !           538: static int qemu_opt_parse(QemuOpt *opt)
        !           539: {
        !           540:     if (opt->desc == NULL)
        !           541:         return 0;
        !           542:     switch (opt->desc->type) {
        !           543:     case QEMU_OPT_STRING:
        !           544:         /* nothing */
        !           545:         return 0;
        !           546:     case QEMU_OPT_BOOL:
        !           547:         return parse_option_bool(opt->name, opt->str, &opt->value.boolean);
        !           548:     case QEMU_OPT_NUMBER:
        !           549:         return parse_option_number(opt->name, opt->str, &opt->value.uint);
        !           550:     case QEMU_OPT_SIZE:
        !           551:         return parse_option_size(opt->name, opt->str, &opt->value.uint);
        !           552:     default:
        !           553:         abort();
        !           554:     }
        !           555: }
        !           556: 
        !           557: static void qemu_opt_del(QemuOpt *opt)
        !           558: {
        !           559:     QTAILQ_REMOVE(&opt->opts->head, opt, next);
        !           560:     qemu_free((/* !const */ char*)opt->name);
        !           561:     qemu_free((/* !const */ char*)opt->str);
        !           562:     qemu_free(opt);
        !           563: }
        !           564: 
        !           565: int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
        !           566: {
        !           567:     QemuOpt *opt;
        !           568:     QemuOptDesc *desc = opts->list->desc;
        !           569:     int i;
        !           570: 
        !           571:     for (i = 0; desc[i].name != NULL; i++) {
        !           572:         if (strcmp(desc[i].name, name) == 0) {
        !           573:             break;
        !           574:         }
        !           575:     }
        !           576:     if (desc[i].name == NULL) {
        !           577:         if (i == 0) {
        !           578:             /* empty list -> allow any */;
        !           579:         } else {
        !           580:             fprintf(stderr, "option \"%s\" is not valid for %s\n",
        !           581:                     name, opts->list->name);
        !           582:             return -1;
        !           583:         }
        !           584:     }
        !           585: 
        !           586:     opt = qemu_mallocz(sizeof(*opt));
        !           587:     opt->name = qemu_strdup(name);
        !           588:     opt->opts = opts;
        !           589:     QTAILQ_INSERT_TAIL(&opts->head, opt, next);
        !           590:     if (desc[i].name != NULL) {
        !           591:         opt->desc = desc+i;
        !           592:     }
        !           593:     if (value) {
        !           594:         opt->str = qemu_strdup(value);
        !           595:     }
        !           596:     if (qemu_opt_parse(opt) < 0) {
        !           597:         fprintf(stderr, "Failed to parse \"%s\" for \"%s.%s\"\n", opt->str,
        !           598:                 opts->list->name, opt->name);
        !           599:         qemu_opt_del(opt);
        !           600:         return -1;
        !           601:     }
        !           602:     return 0;
        !           603: }
        !           604: 
        !           605: int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
        !           606:                      int abort_on_failure)
        !           607: {
        !           608:     QemuOpt *opt;
        !           609:     int rc = 0;
        !           610: 
        !           611:     QTAILQ_FOREACH(opt, &opts->head, next) {
        !           612:         rc = func(opt->name, opt->str, opaque);
        !           613:         if (abort_on_failure  &&  rc != 0)
        !           614:             break;
        !           615:     }
        !           616:     return rc;
        !           617: }
        !           618: 
        !           619: QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
        !           620: {
        !           621:     QemuOpts *opts;
        !           622: 
        !           623:     QTAILQ_FOREACH(opts, &list->head, next) {
        !           624:         if (!opts->id) {
        !           625:             continue;
        !           626:         }
        !           627:         if (strcmp(opts->id, id) != 0) {
        !           628:             continue;
        !           629:         }
        !           630:         return opts;
        !           631:     }
        !           632:     return NULL;
        !           633: }
        !           634: 
        !           635: QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
        !           636: {
        !           637:     QemuOpts *opts = NULL;
        !           638: 
        !           639:     if (id) {
        !           640:         opts = qemu_opts_find(list, id);
        !           641:         if (opts != NULL) {
        !           642:             if (fail_if_exists) {
        !           643:                 fprintf(stderr, "tried to create id \"%s\" twice for \"%s\"\n",
        !           644:                         id, list->name);
        !           645:                 return NULL;
        !           646:             } else {
        !           647:                 return opts;
        !           648:             }
        !           649:         }
        !           650:     }
        !           651:     opts = qemu_mallocz(sizeof(*opts));
        !           652:     if (id) {
        !           653:         opts->id = qemu_strdup(id);
        !           654:     }
        !           655:     opts->list = list;
        !           656:     QTAILQ_INIT(&opts->head);
        !           657:     QTAILQ_INSERT_TAIL(&list->head, opts, next);
        !           658:     return opts;
        !           659: }
        !           660: 
        !           661: int qemu_opts_set(QemuOptsList *list, const char *id,
        !           662:                   const char *name, const char *value)
        !           663: {
        !           664:     QemuOpts *opts;
        !           665: 
        !           666:     opts = qemu_opts_create(list, id, 1);
        !           667:     if (opts == NULL) {
        !           668:         return -1;
        !           669:     }
        !           670:     return qemu_opt_set(opts, name, value);
        !           671: }
        !           672: 
        !           673: const char *qemu_opts_id(QemuOpts *opts)
        !           674: {
        !           675:     return opts->id;
        !           676: }
        !           677: 
        !           678: void qemu_opts_del(QemuOpts *opts)
        !           679: {
        !           680:     QemuOpt *opt;
        !           681: 
        !           682:     for (;;) {
        !           683:         opt = QTAILQ_FIRST(&opts->head);
        !           684:         if (opt == NULL)
        !           685:             break;
        !           686:         qemu_opt_del(opt);
        !           687:     }
        !           688:     QTAILQ_REMOVE(&opts->list->head, opts, next);
        !           689:     qemu_free(opts->id);
        !           690:     qemu_free(opts);
        !           691: }
        !           692: 
        !           693: int qemu_opts_print(QemuOpts *opts, void *dummy)
        !           694: {
        !           695:     QemuOpt *opt;
        !           696: 
        !           697:     fprintf(stderr, "%s: %s:", opts->list->name,
        !           698:             opts->id ? opts->id : "<noid>");
        !           699:     QTAILQ_FOREACH(opt, &opts->head, next) {
        !           700:         fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
        !           701:     }
        !           702:     fprintf(stderr, "\n");
        !           703:     return 0;
        !           704: }
        !           705: 
        !           706: int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
        !           707: {
        !           708:     char option[128], value[1024];
        !           709:     const char *p,*pe,*pc;
        !           710: 
        !           711:     for (p = params; *p != '\0'; p++) {
        !           712:         pe = strchr(p, '=');
        !           713:         pc = strchr(p, ',');
        !           714:         if (!pe || (pc && pc < pe)) {
        !           715:             /* found "foo,more" */
        !           716:             if (p == params && firstname) {
        !           717:                 /* implicitly named first option */
        !           718:                 pstrcpy(option, sizeof(option), firstname);
        !           719:                 p = get_opt_value(value, sizeof(value), p);
        !           720:             } else {
        !           721:                 /* option without value, probably a flag */
        !           722:                 p = get_opt_name(option, sizeof(option), p, ',');
        !           723:                 if (strncmp(option, "no", 2) == 0) {
        !           724:                     memmove(option, option+2, strlen(option+2)+1);
        !           725:                     pstrcpy(value, sizeof(value), "off");
        !           726:                 } else {
        !           727:                     pstrcpy(value, sizeof(value), "on");
        !           728:                 }
        !           729:             }
        !           730:         } else {
        !           731:             /* found "foo=bar,more" */
        !           732:             p = get_opt_name(option, sizeof(option), p, '=');
        !           733:             if (*p != '=') {
        !           734:                 break;
        !           735:             }
        !           736:             p++;
        !           737:             p = get_opt_value(value, sizeof(value), p);
        !           738:         }
        !           739:         if (strcmp(option, "id") != 0) {
        !           740:             /* store and parse */
        !           741:             if (qemu_opt_set(opts, option, value) == -1) {
        !           742:                 return -1;
        !           743:             }
        !           744:         }
        !           745:         if (*p != ',') {
        !           746:             break;
        !           747:         }
        !           748:     }
        !           749:     return 0;
        !           750: }
        !           751: 
        !           752: QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, const char *firstname)
        !           753: {
        !           754:     char value[1024], *id = NULL;
        !           755:     const char *p;
        !           756:     QemuOpts *opts;
        !           757: 
        !           758:     if (strncmp(params, "id=", 3) == 0) {
        !           759:         get_opt_value(value, sizeof(value), params+3);
        !           760:         id = qemu_strdup(value);
        !           761:     } else if ((p = strstr(params, ",id=")) != NULL) {
        !           762:         get_opt_value(value, sizeof(value), p+4);
        !           763:         id = qemu_strdup(value);
        !           764:     }
        !           765:     opts = qemu_opts_create(list, id, 1);
        !           766:     if (opts == NULL)
        !           767:         return NULL;
        !           768: 
        !           769:     if (qemu_opts_do_parse(opts, params, firstname) != 0) {
        !           770:         qemu_opts_del(opts);
        !           771:         return NULL;
        !           772:     }
        !           773: 
        !           774:     return opts;
        !           775: }
        !           776: 
        !           777: /* Validate parsed opts against descriptions where no
        !           778:  * descriptions were provided in the QemuOptsList.
        !           779:  */
        !           780: int qemu_opts_validate(QemuOpts *opts, QemuOptDesc *desc)
        !           781: {
        !           782:     QemuOpt *opt;
        !           783: 
        !           784:     assert(opts->list->desc[0].name == NULL);
        !           785: 
        !           786:     QTAILQ_FOREACH(opt, &opts->head, next) {
        !           787:         int i;
        !           788: 
        !           789:         for (i = 0; desc[i].name != NULL; i++) {
        !           790:             if (strcmp(desc[i].name, opt->name) == 0) {
        !           791:                 break;
        !           792:             }
        !           793:         }
        !           794:         if (desc[i].name == NULL) {
        !           795:             fprintf(stderr, "option \"%s\" is not valid for %s\n",
        !           796:                     opt->name, opts->list->name);
        !           797:             return -1;
        !           798:         }
        !           799: 
        !           800:         opt->desc = &desc[i];
        !           801: 
        !           802:         if (qemu_opt_parse(opt) < 0) {
        !           803:             return -1;
        !           804:         }
        !           805:     }
        !           806: 
        !           807:     return 0;
        !           808: }
        !           809: 
        !           810: int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
        !           811:                       int abort_on_failure)
        !           812: {
        !           813:     QemuOpts *opts;
        !           814:     int rc = 0;
        !           815: 
        !           816:     QTAILQ_FOREACH(opts, &list->head, next) {
        !           817:         rc = func(opts, opaque);
        !           818:         if (abort_on_failure  &&  rc != 0)
        !           819:             break;
        !           820:     }
        !           821:     return rc;
        !           822: }

unix.superglobalmegacorp.com