File:  [Qemu by Fabrice Bellard] / qemu / qemu-option.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:33:36 2018 UTC (2 years, 2 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0125, qemu0124, qemu0123, qemu0122, qemu0121, qemu0120, HEAD
qemu 0.12.0

    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: 
   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: 
  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: 
  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: 
  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: {
  258:     int flag;
  259: 
  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:
  270:         if (parse_option_bool(name, value, &flag) == -1)
  271:             return -1;
  272:         list->value.n = flag;
  273:         break;
  274: 
  275:     case OPT_STRING:
  276:         if (value != NULL) {
  277:             list->value.s = qemu_strdup(value);
  278:         } else {
  279:             fprintf(stderr, "Option '%s' needs a parameter\n", name);
  280:             return -1;
  281:         }
  282:         break;
  283: 
  284:     case OPT_SIZE:
  285:         if (parse_option_size(name, value, &list->value.n) == -1)
  286:             return -1;
  287:         break;
  288: 
  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) {
  337:             qemu_free(cur->value.s);
  338:         }
  339:         cur++;
  340:     }
  341: 
  342:     qemu_free(list);
  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: }
  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