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

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"
1.1.1.3 ! root       30: #include "qemu-error.h"
        !            31: #include "qemu-objects.h"
1.1       root       32: #include "qemu-option.h"
1.1.1.3 ! root       33: #include "qerror.h"
1.1       root       34: 
                     35: /*
                     36:  * Extracts the name of an option from the parameter string (p points at the
                     37:  * first byte of the option name)
                     38:  *
                     39:  * The option name is delimited by delim (usually , or =) or the string end
                     40:  * and is copied into buf. If the option name is longer than buf_size, it is
                     41:  * truncated. buf is always zero terminated.
                     42:  *
                     43:  * The return value is the position of the delimiter/zero byte after the option
                     44:  * name in p.
                     45:  */
                     46: const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
                     47: {
                     48:     char *q;
                     49: 
                     50:     q = buf;
                     51:     while (*p != '\0' && *p != delim) {
                     52:         if (q && (q - buf) < buf_size - 1)
                     53:             *q++ = *p;
                     54:         p++;
                     55:     }
                     56:     if (q)
                     57:         *q = '\0';
                     58: 
                     59:     return p;
                     60: }
                     61: 
                     62: /*
                     63:  * Extracts the value of an option from the parameter string p (p points at the
                     64:  * first byte of the option value)
                     65:  *
                     66:  * This function is comparable to get_opt_name with the difference that the
                     67:  * delimiter is fixed to be comma which starts a new option. To specify an
                     68:  * option value that contains commas, double each comma.
                     69:  */
                     70: const char *get_opt_value(char *buf, int buf_size, const char *p)
                     71: {
                     72:     char *q;
                     73: 
                     74:     q = buf;
                     75:     while (*p != '\0') {
                     76:         if (*p == ',') {
                     77:             if (*(p + 1) != ',')
                     78:                 break;
                     79:             p++;
                     80:         }
                     81:         if (q && (q - buf) < buf_size - 1)
                     82:             *q++ = *p;
                     83:         p++;
                     84:     }
                     85:     if (q)
                     86:         *q = '\0';
                     87: 
                     88:     return p;
                     89: }
                     90: 
1.1.1.2   root       91: int get_next_param_value(char *buf, int buf_size,
                     92:                          const char *tag, const char **pstr)
                     93: {
                     94:     const char *p;
                     95:     char option[128];
                     96: 
                     97:     p = *pstr;
                     98:     for(;;) {
                     99:         p = get_opt_name(option, sizeof(option), p, '=');
                    100:         if (*p != '=')
                    101:             break;
                    102:         p++;
                    103:         if (!strcmp(tag, option)) {
                    104:             *pstr = get_opt_value(buf, buf_size, p);
                    105:             if (**pstr == ',') {
                    106:                 (*pstr)++;
                    107:             }
                    108:             return strlen(buf);
                    109:         } else {
                    110:             p = get_opt_value(NULL, 0, p);
                    111:         }
                    112:         if (*p != ',')
                    113:             break;
                    114:         p++;
                    115:     }
                    116:     return 0;
                    117: }
                    118: 
                    119: int get_param_value(char *buf, int buf_size,
                    120:                     const char *tag, const char *str)
                    121: {
                    122:     return get_next_param_value(buf, buf_size, tag, &str);
                    123: }
                    124: 
                    125: int check_params(char *buf, int buf_size,
                    126:                  const char * const *params, const char *str)
                    127: {
                    128:     const char *p;
                    129:     int i;
                    130: 
                    131:     p = str;
                    132:     while (*p != '\0') {
                    133:         p = get_opt_name(buf, buf_size, p, '=');
                    134:         if (*p != '=') {
                    135:             return -1;
                    136:         }
                    137:         p++;
                    138:         for (i = 0; params[i] != NULL; i++) {
                    139:             if (!strcmp(params[i], buf)) {
                    140:                 break;
                    141:             }
                    142:         }
                    143:         if (params[i] == NULL) {
                    144:             return -1;
                    145:         }
                    146:         p = get_opt_value(NULL, 0, p);
                    147:         if (*p != ',') {
                    148:             break;
                    149:         }
                    150:         p++;
                    151:     }
                    152:     return 0;
                    153: }
                    154: 
1.1       root      155: /*
                    156:  * Searches an option list for an option with the given name
                    157:  */
                    158: QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
                    159:     const char *name)
                    160: {
                    161:     while (list && list->name) {
                    162:         if (!strcmp(list->name, name)) {
                    163:             return list;
                    164:         }
                    165:         list++;
                    166:     }
                    167: 
                    168:     return NULL;
                    169: }
                    170: 
1.1.1.2   root      171: static int parse_option_bool(const char *name, const char *value, int *ret)
                    172: {
                    173:     if (value != NULL) {
                    174:         if (!strcmp(value, "on")) {
                    175:             *ret = 1;
                    176:         } else if (!strcmp(value, "off")) {
                    177:             *ret = 0;
                    178:         } else {
1.1.1.3 ! root      179:             qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'");
1.1.1.2   root      180:             return -1;
                    181:         }
                    182:     } else {
                    183:         *ret = 1;
                    184:     }
                    185:     return 0;
                    186: }
                    187: 
                    188: static int parse_option_number(const char *name, const char *value, uint64_t *ret)
                    189: {
                    190:     char *postfix;
                    191:     uint64_t number;
                    192: 
                    193:     if (value != NULL) {
                    194:         number = strtoull(value, &postfix, 0);
                    195:         if (*postfix != '\0') {
1.1.1.3 ! root      196:             qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
1.1.1.2   root      197:             return -1;
                    198:         }
                    199:         *ret = number;
                    200:     } else {
1.1.1.3 ! root      201:         qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
1.1.1.2   root      202:         return -1;
                    203:     }
                    204:     return 0;
                    205: }
                    206: 
                    207: static int parse_option_size(const char *name, const char *value, uint64_t *ret)
                    208: {
                    209:     char *postfix;
                    210:     double sizef;
                    211: 
                    212:     if (value != NULL) {
                    213:         sizef = strtod(value, &postfix);
                    214:         switch (*postfix) {
                    215:         case 'T':
                    216:             sizef *= 1024;
                    217:         case 'G':
                    218:             sizef *= 1024;
                    219:         case 'M':
                    220:             sizef *= 1024;
                    221:         case 'K':
                    222:         case 'k':
                    223:             sizef *= 1024;
                    224:         case 'b':
                    225:         case '\0':
                    226:             *ret = (uint64_t) sizef;
                    227:             break;
                    228:         default:
1.1.1.3 ! root      229:             qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
        !           230:             error_printf_unless_qmp("You may use k, M, G or T suffixes for "
1.1.1.2   root      231:                     "kilobytes, megabytes, gigabytes and terabytes.\n");
                    232:             return -1;
                    233:         }
                    234:     } else {
1.1.1.3 ! root      235:         qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
1.1.1.2   root      236:         return -1;
                    237:     }
                    238:     return 0;
                    239: }
                    240: 
1.1       root      241: /*
                    242:  * Sets the value of a parameter in a given option list. The parsing of the
                    243:  * value depends on the type of option:
                    244:  *
                    245:  * OPT_FLAG (uses value.n):
                    246:  *      If no value is given, the flag is set to 1.
                    247:  *      Otherwise the value must be "on" (set to 1) or "off" (set to 0)
                    248:  *
                    249:  * OPT_STRING (uses value.s):
                    250:  *      value is strdup()ed and assigned as option value
                    251:  *
                    252:  * OPT_SIZE (uses value.n):
                    253:  *      The value is converted to an integer. Suffixes for kilobytes etc. are
                    254:  *      allowed (powers of 1024).
                    255:  *
                    256:  * Returns 0 on succes, -1 in error cases
                    257:  */
                    258: int set_option_parameter(QEMUOptionParameter *list, const char *name,
                    259:     const char *value)
                    260: {
1.1.1.2   root      261:     int flag;
                    262: 
1.1       root      263:     // Find a matching parameter
                    264:     list = get_option_parameter(list, name);
                    265:     if (list == NULL) {
                    266:         fprintf(stderr, "Unknown option '%s'\n", name);
                    267:         return -1;
                    268:     }
                    269: 
                    270:     // Process parameter
                    271:     switch (list->type) {
                    272:     case OPT_FLAG:
1.1.1.2   root      273:         if (parse_option_bool(name, value, &flag) == -1)
                    274:             return -1;
                    275:         list->value.n = flag;
1.1       root      276:         break;
                    277: 
                    278:     case OPT_STRING:
                    279:         if (value != NULL) {
1.1.1.2   root      280:             list->value.s = qemu_strdup(value);
1.1       root      281:         } else {
                    282:             fprintf(stderr, "Option '%s' needs a parameter\n", name);
                    283:             return -1;
                    284:         }
                    285:         break;
                    286: 
                    287:     case OPT_SIZE:
1.1.1.2   root      288:         if (parse_option_size(name, value, &list->value.n) == -1)
1.1       root      289:             return -1;
                    290:         break;
1.1.1.2   root      291: 
1.1       root      292:     default:
                    293:         fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
                    294:         return -1;
                    295:     }
                    296: 
                    297:     return 0;
                    298: }
                    299: 
                    300: /*
                    301:  * Sets the given parameter to an integer instead of a string.
                    302:  * This function cannot be used to set string options.
                    303:  *
                    304:  * Returns 0 on success, -1 in error cases
                    305:  */
                    306: int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
                    307:     uint64_t value)
                    308: {
                    309:     // Find a matching parameter
                    310:     list = get_option_parameter(list, name);
                    311:     if (list == NULL) {
                    312:         fprintf(stderr, "Unknown option '%s'\n", name);
                    313:         return -1;
                    314:     }
                    315: 
                    316:     // Process parameter
                    317:     switch (list->type) {
                    318:     case OPT_FLAG:
                    319:     case OPT_NUMBER:
                    320:     case OPT_SIZE:
                    321:         list->value.n = value;
                    322:         break;
                    323: 
                    324:     default:
                    325:         return -1;
                    326:     }
                    327: 
                    328:     return 0;
                    329: }
                    330: 
                    331: /*
                    332:  * Frees a option list. If it contains strings, the strings are freed as well.
                    333:  */
                    334: void free_option_parameters(QEMUOptionParameter *list)
                    335: {
                    336:     QEMUOptionParameter *cur = list;
                    337: 
                    338:     while (cur && cur->name) {
                    339:         if (cur->type == OPT_STRING) {
1.1.1.2   root      340:             qemu_free(cur->value.s);
1.1       root      341:         }
                    342:         cur++;
                    343:     }
                    344: 
1.1.1.2   root      345:     qemu_free(list);
1.1       root      346: }
                    347: 
                    348: /*
1.1.1.3 ! root      349:  * Count valid options in list
        !           350:  */
        !           351: static size_t count_option_parameters(QEMUOptionParameter *list)
        !           352: {
        !           353:     size_t num_options = 0;
        !           354: 
        !           355:     while (list && list->name) {
        !           356:         num_options++;
        !           357:         list++;
        !           358:     }
        !           359: 
        !           360:     return num_options;
        !           361: }
        !           362: 
        !           363: /*
        !           364:  * Append an option list (list) to an option list (dest).
        !           365:  *
        !           366:  * If dest is NULL, a new copy of list is created.
        !           367:  *
        !           368:  * Returns a pointer to the first element of dest (or the newly allocated copy)
        !           369:  */
        !           370: QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
        !           371:     QEMUOptionParameter *list)
        !           372: {
        !           373:     size_t num_options, num_dest_options;
        !           374: 
        !           375:     num_options = count_option_parameters(dest);
        !           376:     num_dest_options = num_options;
        !           377: 
        !           378:     num_options += count_option_parameters(list);
        !           379: 
        !           380:     dest = qemu_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
        !           381:     dest[num_dest_options].name = NULL;
        !           382: 
        !           383:     while (list && list->name) {
        !           384:         if (get_option_parameter(dest, list->name) == NULL) {
        !           385:             dest[num_dest_options++] = *list;
        !           386:             dest[num_dest_options].name = NULL;
        !           387:         }
        !           388:         list++;
        !           389:     }
        !           390: 
        !           391:     return dest;
        !           392: }
        !           393: 
        !           394: /*
1.1       root      395:  * Parses a parameter string (param) into an option list (dest).
                    396:  *
                    397:  * list is the templace is. If dest is NULL, a new copy of list is created for
                    398:  * it. If list is NULL, this function fails.
                    399:  *
                    400:  * A parameter string consists of one or more parameters, separated by commas.
                    401:  * Each parameter consists of its name and possibly of a value. In the latter
                    402:  * case, the value is delimited by an = character. To specify a value which
                    403:  * contains commas, double each comma so it won't be recognized as the end of
                    404:  * the parameter.
                    405:  *
                    406:  * For more details of the parsing see above.
                    407:  *
                    408:  * Returns a pointer to the first element of dest (or the newly allocated copy)
                    409:  * or NULL in error cases
                    410:  */
                    411: QEMUOptionParameter *parse_option_parameters(const char *param,
                    412:     QEMUOptionParameter *list, QEMUOptionParameter *dest)
                    413: {
                    414:     QEMUOptionParameter *allocated = NULL;
                    415:     char name[256];
                    416:     char value[256];
                    417:     char *param_delim, *value_delim;
                    418:     char next_delim;
                    419:     size_t num_options;
                    420: 
                    421:     if (list == NULL) {
                    422:         return NULL;
                    423:     }
                    424: 
                    425:     if (dest == NULL) {
                    426:         // Count valid options
1.1.1.3 ! root      427:         num_options = count_option_parameters(list);
1.1       root      428: 
                    429:         // Create a copy of the option list to fill in values
                    430:         dest = qemu_mallocz((num_options + 1) * sizeof(QEMUOptionParameter));
                    431:         allocated = dest;
                    432:         memcpy(dest, list, (num_options + 1) * sizeof(QEMUOptionParameter));
                    433:     }
                    434: 
                    435:     while (*param) {
                    436: 
                    437:         // Find parameter name and value in the string
                    438:         param_delim = strchr(param, ',');
                    439:         value_delim = strchr(param, '=');
                    440: 
                    441:         if (value_delim && (value_delim < param_delim || !param_delim)) {
                    442:             next_delim = '=';
                    443:         } else {
                    444:             next_delim = ',';
                    445:             value_delim = NULL;
                    446:         }
                    447: 
                    448:         param = get_opt_name(name, sizeof(name), param, next_delim);
                    449:         if (value_delim) {
                    450:             param = get_opt_value(value, sizeof(value), param + 1);
                    451:         }
                    452:         if (*param != '\0') {
                    453:             param++;
                    454:         }
                    455: 
                    456:         // Set the parameter
                    457:         if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
                    458:             goto fail;
                    459:         }
                    460:     }
                    461: 
                    462:     return dest;
                    463: 
                    464: fail:
                    465:     // Only free the list if it was newly allocated
                    466:     free_option_parameters(allocated);
                    467:     return NULL;
                    468: }
                    469: 
                    470: /*
                    471:  * Prints all options of a list that have a value to stdout
                    472:  */
                    473: void print_option_parameters(QEMUOptionParameter *list)
                    474: {
                    475:     while (list && list->name) {
                    476:         switch (list->type) {
                    477:             case OPT_STRING:
                    478:                  if (list->value.s != NULL) {
                    479:                      printf("%s='%s' ", list->name, list->value.s);
                    480:                  }
                    481:                 break;
                    482:             case OPT_FLAG:
                    483:                 printf("%s=%s ", list->name, list->value.n ? "on" : "off");
                    484:                 break;
                    485:             case OPT_SIZE:
                    486:             case OPT_NUMBER:
                    487:                 printf("%s=%" PRId64 " ", list->name, list->value.n);
                    488:                 break;
                    489:             default:
                    490:                 printf("%s=(unkown type) ", list->name);
                    491:                 break;
                    492:         }
                    493:         list++;
                    494:     }
                    495: }
                    496: 
                    497: /*
                    498:  * Prints an overview of all available options
                    499:  */
                    500: void print_option_help(QEMUOptionParameter *list)
                    501: {
                    502:     printf("Supported options:\n");
                    503:     while (list && list->name) {
                    504:         printf("%-16s %s\n", list->name,
                    505:             list->help ? list->help : "No description available");
                    506:         list++;
                    507:     }
                    508: }
1.1.1.2   root      509: 
                    510: /* ------------------------------------------------------------------ */
                    511: 
                    512: struct QemuOpt {
                    513:     const char   *name;
                    514:     const char   *str;
                    515: 
1.1.1.3 ! root      516:     const QemuOptDesc *desc;
1.1.1.2   root      517:     union {
                    518:         int      boolean;
                    519:         uint64_t uint;
                    520:     } value;
                    521: 
                    522:     QemuOpts     *opts;
                    523:     QTAILQ_ENTRY(QemuOpt) next;
                    524: };
                    525: 
                    526: struct QemuOpts {
                    527:     char *id;
                    528:     QemuOptsList *list;
1.1.1.3 ! root      529:     Location loc;
1.1.1.2   root      530:     QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
                    531:     QTAILQ_ENTRY(QemuOpts) next;
                    532: };
                    533: 
                    534: static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
                    535: {
                    536:     QemuOpt *opt;
                    537: 
                    538:     QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
                    539:         if (strcmp(opt->name, name) != 0)
                    540:             continue;
                    541:         return opt;
                    542:     }
                    543:     return NULL;
                    544: }
                    545: 
                    546: const char *qemu_opt_get(QemuOpts *opts, const char *name)
                    547: {
                    548:     QemuOpt *opt = qemu_opt_find(opts, name);
                    549:     return opt ? opt->str : NULL;
                    550: }
                    551: 
                    552: int qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval)
                    553: {
                    554:     QemuOpt *opt = qemu_opt_find(opts, name);
                    555: 
                    556:     if (opt == NULL)
                    557:         return defval;
                    558:     assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
                    559:     return opt->value.boolean;
                    560: }
                    561: 
                    562: uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
                    563: {
                    564:     QemuOpt *opt = qemu_opt_find(opts, name);
                    565: 
                    566:     if (opt == NULL)
                    567:         return defval;
                    568:     assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
                    569:     return opt->value.uint;
                    570: }
                    571: 
                    572: uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
                    573: {
                    574:     QemuOpt *opt = qemu_opt_find(opts, name);
                    575: 
                    576:     if (opt == NULL)
                    577:         return defval;
                    578:     assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
                    579:     return opt->value.uint;
                    580: }
                    581: 
                    582: static int qemu_opt_parse(QemuOpt *opt)
                    583: {
                    584:     if (opt->desc == NULL)
                    585:         return 0;
                    586:     switch (opt->desc->type) {
                    587:     case QEMU_OPT_STRING:
                    588:         /* nothing */
                    589:         return 0;
                    590:     case QEMU_OPT_BOOL:
                    591:         return parse_option_bool(opt->name, opt->str, &opt->value.boolean);
                    592:     case QEMU_OPT_NUMBER:
                    593:         return parse_option_number(opt->name, opt->str, &opt->value.uint);
                    594:     case QEMU_OPT_SIZE:
                    595:         return parse_option_size(opt->name, opt->str, &opt->value.uint);
                    596:     default:
                    597:         abort();
                    598:     }
                    599: }
                    600: 
                    601: static void qemu_opt_del(QemuOpt *opt)
                    602: {
                    603:     QTAILQ_REMOVE(&opt->opts->head, opt, next);
                    604:     qemu_free((/* !const */ char*)opt->name);
                    605:     qemu_free((/* !const */ char*)opt->str);
                    606:     qemu_free(opt);
                    607: }
                    608: 
                    609: int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
                    610: {
                    611:     QemuOpt *opt;
1.1.1.3 ! root      612:     const QemuOptDesc *desc = opts->list->desc;
1.1.1.2   root      613:     int i;
                    614: 
                    615:     for (i = 0; desc[i].name != NULL; i++) {
                    616:         if (strcmp(desc[i].name, name) == 0) {
                    617:             break;
                    618:         }
                    619:     }
                    620:     if (desc[i].name == NULL) {
                    621:         if (i == 0) {
                    622:             /* empty list -> allow any */;
                    623:         } else {
1.1.1.3 ! root      624:             qerror_report(QERR_INVALID_PARAMETER, name);
1.1.1.2   root      625:             return -1;
                    626:         }
                    627:     }
                    628: 
                    629:     opt = qemu_mallocz(sizeof(*opt));
                    630:     opt->name = qemu_strdup(name);
                    631:     opt->opts = opts;
                    632:     QTAILQ_INSERT_TAIL(&opts->head, opt, next);
                    633:     if (desc[i].name != NULL) {
                    634:         opt->desc = desc+i;
                    635:     }
                    636:     if (value) {
                    637:         opt->str = qemu_strdup(value);
                    638:     }
                    639:     if (qemu_opt_parse(opt) < 0) {
                    640:         qemu_opt_del(opt);
                    641:         return -1;
                    642:     }
                    643:     return 0;
                    644: }
                    645: 
                    646: int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
                    647:                      int abort_on_failure)
                    648: {
                    649:     QemuOpt *opt;
                    650:     int rc = 0;
                    651: 
                    652:     QTAILQ_FOREACH(opt, &opts->head, next) {
                    653:         rc = func(opt->name, opt->str, opaque);
                    654:         if (abort_on_failure  &&  rc != 0)
                    655:             break;
                    656:     }
                    657:     return rc;
                    658: }
                    659: 
                    660: QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
                    661: {
                    662:     QemuOpts *opts;
                    663: 
                    664:     QTAILQ_FOREACH(opts, &list->head, next) {
                    665:         if (!opts->id) {
                    666:             continue;
                    667:         }
                    668:         if (strcmp(opts->id, id) != 0) {
                    669:             continue;
                    670:         }
                    671:         return opts;
                    672:     }
                    673:     return NULL;
                    674: }
                    675: 
1.1.1.3 ! root      676: static int id_wellformed(const char *id)
        !           677: {
        !           678:     int i;
        !           679: 
        !           680:     if (!qemu_isalpha(id[0])) {
        !           681:         return 0;
        !           682:     }
        !           683:     for (i = 1; id[i]; i++) {
        !           684:         if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) {
        !           685:             return 0;
        !           686:         }
        !           687:     }
        !           688:     return 1;
        !           689: }
        !           690: 
1.1.1.2   root      691: QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
                    692: {
                    693:     QemuOpts *opts = NULL;
                    694: 
                    695:     if (id) {
1.1.1.3 ! root      696:         if (!id_wellformed(id)) {
        !           697:             qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
        !           698:             error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
        !           699:             return NULL;
        !           700:         }
1.1.1.2   root      701:         opts = qemu_opts_find(list, id);
                    702:         if (opts != NULL) {
                    703:             if (fail_if_exists) {
1.1.1.3 ! root      704:                 qerror_report(QERR_DUPLICATE_ID, id, list->name);
1.1.1.2   root      705:                 return NULL;
                    706:             } else {
                    707:                 return opts;
                    708:             }
                    709:         }
                    710:     }
                    711:     opts = qemu_mallocz(sizeof(*opts));
                    712:     if (id) {
                    713:         opts->id = qemu_strdup(id);
                    714:     }
                    715:     opts->list = list;
1.1.1.3 ! root      716:     loc_save(&opts->loc);
1.1.1.2   root      717:     QTAILQ_INIT(&opts->head);
                    718:     QTAILQ_INSERT_TAIL(&list->head, opts, next);
                    719:     return opts;
                    720: }
                    721: 
1.1.1.3 ! root      722: void qemu_opts_reset(QemuOptsList *list)
        !           723: {
        !           724:     QemuOpts *opts, *next_opts;
        !           725: 
        !           726:     QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) {
        !           727:         qemu_opts_del(opts);
        !           728:     }
        !           729: }
        !           730: 
        !           731: void qemu_opts_loc_restore(QemuOpts *opts)
        !           732: {
        !           733:     loc_restore(&opts->loc);
        !           734: }
        !           735: 
1.1.1.2   root      736: int qemu_opts_set(QemuOptsList *list, const char *id,
                    737:                   const char *name, const char *value)
                    738: {
                    739:     QemuOpts *opts;
                    740: 
                    741:     opts = qemu_opts_create(list, id, 1);
                    742:     if (opts == NULL) {
                    743:         return -1;
                    744:     }
                    745:     return qemu_opt_set(opts, name, value);
                    746: }
                    747: 
                    748: const char *qemu_opts_id(QemuOpts *opts)
                    749: {
                    750:     return opts->id;
                    751: }
                    752: 
                    753: void qemu_opts_del(QemuOpts *opts)
                    754: {
                    755:     QemuOpt *opt;
                    756: 
                    757:     for (;;) {
                    758:         opt = QTAILQ_FIRST(&opts->head);
                    759:         if (opt == NULL)
                    760:             break;
                    761:         qemu_opt_del(opt);
                    762:     }
                    763:     QTAILQ_REMOVE(&opts->list->head, opts, next);
                    764:     qemu_free(opts->id);
                    765:     qemu_free(opts);
                    766: }
                    767: 
                    768: int qemu_opts_print(QemuOpts *opts, void *dummy)
                    769: {
                    770:     QemuOpt *opt;
                    771: 
                    772:     fprintf(stderr, "%s: %s:", opts->list->name,
                    773:             opts->id ? opts->id : "<noid>");
                    774:     QTAILQ_FOREACH(opt, &opts->head, next) {
                    775:         fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
                    776:     }
                    777:     fprintf(stderr, "\n");
                    778:     return 0;
                    779: }
                    780: 
                    781: int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
                    782: {
                    783:     char option[128], value[1024];
                    784:     const char *p,*pe,*pc;
                    785: 
                    786:     for (p = params; *p != '\0'; p++) {
                    787:         pe = strchr(p, '=');
                    788:         pc = strchr(p, ',');
                    789:         if (!pe || (pc && pc < pe)) {
                    790:             /* found "foo,more" */
                    791:             if (p == params && firstname) {
                    792:                 /* implicitly named first option */
                    793:                 pstrcpy(option, sizeof(option), firstname);
                    794:                 p = get_opt_value(value, sizeof(value), p);
                    795:             } else {
                    796:                 /* option without value, probably a flag */
                    797:                 p = get_opt_name(option, sizeof(option), p, ',');
                    798:                 if (strncmp(option, "no", 2) == 0) {
                    799:                     memmove(option, option+2, strlen(option+2)+1);
                    800:                     pstrcpy(value, sizeof(value), "off");
                    801:                 } else {
                    802:                     pstrcpy(value, sizeof(value), "on");
                    803:                 }
                    804:             }
                    805:         } else {
                    806:             /* found "foo=bar,more" */
                    807:             p = get_opt_name(option, sizeof(option), p, '=');
                    808:             if (*p != '=') {
                    809:                 break;
                    810:             }
                    811:             p++;
                    812:             p = get_opt_value(value, sizeof(value), p);
                    813:         }
                    814:         if (strcmp(option, "id") != 0) {
                    815:             /* store and parse */
                    816:             if (qemu_opt_set(opts, option, value) == -1) {
                    817:                 return -1;
                    818:             }
                    819:         }
                    820:         if (*p != ',') {
                    821:             break;
                    822:         }
                    823:     }
                    824:     return 0;
                    825: }
                    826: 
1.1.1.3 ! root      827: QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
        !           828:                           int permit_abbrev)
1.1.1.2   root      829: {
1.1.1.3 ! root      830:     const char *firstname;
1.1.1.2   root      831:     char value[1024], *id = NULL;
                    832:     const char *p;
                    833:     QemuOpts *opts;
                    834: 
1.1.1.3 ! root      835:     assert(!permit_abbrev || list->implied_opt_name);
        !           836:     firstname = permit_abbrev ? list->implied_opt_name : NULL;
        !           837: 
1.1.1.2   root      838:     if (strncmp(params, "id=", 3) == 0) {
                    839:         get_opt_value(value, sizeof(value), params+3);
1.1.1.3 ! root      840:         id = value;
1.1.1.2   root      841:     } else if ((p = strstr(params, ",id=")) != NULL) {
                    842:         get_opt_value(value, sizeof(value), p+4);
1.1.1.3 ! root      843:         id = value;
1.1.1.2   root      844:     }
                    845:     opts = qemu_opts_create(list, id, 1);
                    846:     if (opts == NULL)
                    847:         return NULL;
                    848: 
                    849:     if (qemu_opts_do_parse(opts, params, firstname) != 0) {
                    850:         qemu_opts_del(opts);
                    851:         return NULL;
                    852:     }
                    853: 
                    854:     return opts;
                    855: }
                    856: 
1.1.1.3 ! root      857: static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
        !           858: {
        !           859:     char buf[32];
        !           860:     const char *value;
        !           861:     int n;
        !           862: 
        !           863:     if (!strcmp(key, "id")) {
        !           864:         return;
        !           865:     }
        !           866: 
        !           867:     switch (qobject_type(obj)) {
        !           868:     case QTYPE_QSTRING:
        !           869:         value = qstring_get_str(qobject_to_qstring(obj));
        !           870:         break;
        !           871:     case QTYPE_QINT:
        !           872:         n = snprintf(buf, sizeof(buf), "%" PRId64,
        !           873:                      qint_get_int(qobject_to_qint(obj)));
        !           874:         assert(n < sizeof(buf));
        !           875:         value = buf;
        !           876:         break;
        !           877:     case QTYPE_QFLOAT:
        !           878:         n = snprintf(buf, sizeof(buf), "%.17g",
        !           879:                      qfloat_get_double(qobject_to_qfloat(obj)));
        !           880:         assert(n < sizeof(buf));
        !           881:         value = buf;
        !           882:         break;
        !           883:     case QTYPE_QBOOL:
        !           884:         pstrcpy(buf, sizeof(buf),
        !           885:                 qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off");
        !           886:         value = buf;
        !           887:         break;
        !           888:     default:
        !           889:         return;
        !           890:     }
        !           891:     qemu_opt_set(opaque, key, value);
        !           892: }
        !           893: 
        !           894: /*
        !           895:  * Create QemuOpts from a QDict.
        !           896:  * Use value of key "id" as ID if it exists and is a QString.
        !           897:  * Only QStrings, QInts, QFloats and QBools are copied.  Entries with
        !           898:  * other types are silently ignored.
        !           899:  */
        !           900: QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
        !           901: {
        !           902:     QemuOpts *opts;
        !           903: 
        !           904:     opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1);
        !           905:     if (opts == NULL)
        !           906:         return NULL;
        !           907: 
        !           908:     qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
        !           909:     return opts;
        !           910: }
        !           911: 
        !           912: /*
        !           913:  * Convert from QemuOpts to QDict.
        !           914:  * The QDict values are of type QString.
        !           915:  * TODO We'll want to use types appropriate for opt->desc->type, but
        !           916:  * this is enough for now.
        !           917:  */
        !           918: QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
        !           919: {
        !           920:     QemuOpt *opt;
        !           921:     QObject *val;
        !           922: 
        !           923:     if (!qdict) {
        !           924:         qdict = qdict_new();
        !           925:     }
        !           926:     if (opts->id) {
        !           927:         qdict_put(qdict, "id", qstring_from_str(opts->id));
        !           928:     }
        !           929:     QTAILQ_FOREACH(opt, &opts->head, next) {
        !           930:         val = QOBJECT(qstring_from_str(opt->str));
        !           931:         qdict_put_obj(qdict, opt->name, val);
        !           932:     }
        !           933:     return qdict;
        !           934: }
        !           935: 
1.1.1.2   root      936: /* Validate parsed opts against descriptions where no
                    937:  * descriptions were provided in the QemuOptsList.
                    938:  */
1.1.1.3 ! root      939: int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
1.1.1.2   root      940: {
                    941:     QemuOpt *opt;
                    942: 
                    943:     assert(opts->list->desc[0].name == NULL);
                    944: 
                    945:     QTAILQ_FOREACH(opt, &opts->head, next) {
                    946:         int i;
                    947: 
                    948:         for (i = 0; desc[i].name != NULL; i++) {
                    949:             if (strcmp(desc[i].name, opt->name) == 0) {
                    950:                 break;
                    951:             }
                    952:         }
                    953:         if (desc[i].name == NULL) {
1.1.1.3 ! root      954:             qerror_report(QERR_INVALID_PARAMETER, opt->name);
1.1.1.2   root      955:             return -1;
                    956:         }
                    957: 
                    958:         opt->desc = &desc[i];
                    959: 
                    960:         if (qemu_opt_parse(opt) < 0) {
                    961:             return -1;
                    962:         }
                    963:     }
                    964: 
                    965:     return 0;
                    966: }
                    967: 
                    968: int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
                    969:                       int abort_on_failure)
                    970: {
1.1.1.3 ! root      971:     Location loc;
1.1.1.2   root      972:     QemuOpts *opts;
                    973:     int rc = 0;
                    974: 
1.1.1.3 ! root      975:     loc_push_none(&loc);
1.1.1.2   root      976:     QTAILQ_FOREACH(opts, &list->head, next) {
1.1.1.3 ! root      977:         loc_restore(&opts->loc);
        !           978:         rc |= func(opts, opaque);
1.1.1.2   root      979:         if (abort_on_failure  &&  rc != 0)
                    980:             break;
                    981:     }
1.1.1.3 ! root      982:     loc_pop(&loc);
1.1.1.2   root      983:     return rc;
                    984: }

unix.superglobalmegacorp.com