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

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.5   root      171: static int parse_option_bool(const char *name, const char *value, bool *ret)
1.1.1.2   root      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;
1.1.1.6 ! root      217:             /* fall through */
1.1.1.2   root      218:         case 'G':
                    219:             sizef *= 1024;
1.1.1.6 ! root      220:             /* fall through */
1.1.1.2   root      221:         case 'M':
                    222:             sizef *= 1024;
1.1.1.6 ! root      223:             /* fall through */
1.1.1.2   root      224:         case 'K':
                    225:         case 'k':
                    226:             sizef *= 1024;
1.1.1.6 ! root      227:             /* fall through */
1.1.1.2   root      228:         case 'b':
                    229:         case '\0':
                    230:             *ret = (uint64_t) sizef;
                    231:             break;
                    232:         default:
1.1.1.3   root      233:             qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
                    234:             error_printf_unless_qmp("You may use k, M, G or T suffixes for "
1.1.1.2   root      235:                     "kilobytes, megabytes, gigabytes and terabytes.\n");
                    236:             return -1;
                    237:         }
                    238:     } else {
1.1.1.3   root      239:         qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
1.1.1.2   root      240:         return -1;
                    241:     }
                    242:     return 0;
                    243: }
                    244: 
1.1       root      245: /*
                    246:  * Sets the value of a parameter in a given option list. The parsing of the
                    247:  * value depends on the type of option:
                    248:  *
                    249:  * OPT_FLAG (uses value.n):
                    250:  *      If no value is given, the flag is set to 1.
                    251:  *      Otherwise the value must be "on" (set to 1) or "off" (set to 0)
                    252:  *
                    253:  * OPT_STRING (uses value.s):
                    254:  *      value is strdup()ed and assigned as option value
                    255:  *
                    256:  * OPT_SIZE (uses value.n):
                    257:  *      The value is converted to an integer. Suffixes for kilobytes etc. are
                    258:  *      allowed (powers of 1024).
                    259:  *
                    260:  * Returns 0 on succes, -1 in error cases
                    261:  */
                    262: int set_option_parameter(QEMUOptionParameter *list, const char *name,
                    263:     const char *value)
                    264: {
1.1.1.5   root      265:     bool flag;
1.1.1.2   root      266: 
1.1       root      267:     // Find a matching parameter
                    268:     list = get_option_parameter(list, name);
                    269:     if (list == NULL) {
                    270:         fprintf(stderr, "Unknown option '%s'\n", name);
                    271:         return -1;
                    272:     }
                    273: 
                    274:     // Process parameter
                    275:     switch (list->type) {
                    276:     case OPT_FLAG:
1.1.1.2   root      277:         if (parse_option_bool(name, value, &flag) == -1)
                    278:             return -1;
                    279:         list->value.n = flag;
1.1       root      280:         break;
                    281: 
                    282:     case OPT_STRING:
                    283:         if (value != NULL) {
1.1.1.5   root      284:             list->value.s = g_strdup(value);
1.1       root      285:         } else {
                    286:             fprintf(stderr, "Option '%s' needs a parameter\n", name);
                    287:             return -1;
                    288:         }
                    289:         break;
                    290: 
                    291:     case OPT_SIZE:
1.1.1.2   root      292:         if (parse_option_size(name, value, &list->value.n) == -1)
1.1       root      293:             return -1;
                    294:         break;
1.1.1.2   root      295: 
1.1       root      296:     default:
                    297:         fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
                    298:         return -1;
                    299:     }
                    300: 
                    301:     return 0;
                    302: }
                    303: 
                    304: /*
                    305:  * Sets the given parameter to an integer instead of a string.
                    306:  * This function cannot be used to set string options.
                    307:  *
                    308:  * Returns 0 on success, -1 in error cases
                    309:  */
                    310: int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
                    311:     uint64_t value)
                    312: {
                    313:     // Find a matching parameter
                    314:     list = get_option_parameter(list, name);
                    315:     if (list == NULL) {
                    316:         fprintf(stderr, "Unknown option '%s'\n", name);
                    317:         return -1;
                    318:     }
                    319: 
                    320:     // Process parameter
                    321:     switch (list->type) {
                    322:     case OPT_FLAG:
                    323:     case OPT_NUMBER:
                    324:     case OPT_SIZE:
                    325:         list->value.n = value;
                    326:         break;
                    327: 
                    328:     default:
                    329:         return -1;
                    330:     }
                    331: 
                    332:     return 0;
                    333: }
                    334: 
                    335: /*
                    336:  * Frees a option list. If it contains strings, the strings are freed as well.
                    337:  */
                    338: void free_option_parameters(QEMUOptionParameter *list)
                    339: {
                    340:     QEMUOptionParameter *cur = list;
                    341: 
                    342:     while (cur && cur->name) {
                    343:         if (cur->type == OPT_STRING) {
1.1.1.5   root      344:             g_free(cur->value.s);
1.1       root      345:         }
                    346:         cur++;
                    347:     }
                    348: 
1.1.1.5   root      349:     g_free(list);
1.1       root      350: }
                    351: 
                    352: /*
1.1.1.3   root      353:  * Count valid options in list
                    354:  */
                    355: static size_t count_option_parameters(QEMUOptionParameter *list)
                    356: {
                    357:     size_t num_options = 0;
                    358: 
                    359:     while (list && list->name) {
                    360:         num_options++;
                    361:         list++;
                    362:     }
                    363: 
                    364:     return num_options;
                    365: }
                    366: 
                    367: /*
                    368:  * Append an option list (list) to an option list (dest).
                    369:  *
                    370:  * If dest is NULL, a new copy of list is created.
                    371:  *
                    372:  * Returns a pointer to the first element of dest (or the newly allocated copy)
                    373:  */
                    374: QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
                    375:     QEMUOptionParameter *list)
                    376: {
                    377:     size_t num_options, num_dest_options;
                    378: 
                    379:     num_options = count_option_parameters(dest);
                    380:     num_dest_options = num_options;
                    381: 
                    382:     num_options += count_option_parameters(list);
                    383: 
1.1.1.5   root      384:     dest = g_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
1.1.1.3   root      385:     dest[num_dest_options].name = NULL;
                    386: 
                    387:     while (list && list->name) {
                    388:         if (get_option_parameter(dest, list->name) == NULL) {
                    389:             dest[num_dest_options++] = *list;
                    390:             dest[num_dest_options].name = NULL;
                    391:         }
                    392:         list++;
                    393:     }
                    394: 
                    395:     return dest;
                    396: }
                    397: 
                    398: /*
1.1       root      399:  * Parses a parameter string (param) into an option list (dest).
                    400:  *
1.1.1.4   root      401:  * list is the template option list. If dest is NULL, a new copy of list is
                    402:  * created. If list is NULL, this function fails.
1.1       root      403:  *
                    404:  * A parameter string consists of one or more parameters, separated by commas.
                    405:  * Each parameter consists of its name and possibly of a value. In the latter
                    406:  * case, the value is delimited by an = character. To specify a value which
                    407:  * contains commas, double each comma so it won't be recognized as the end of
                    408:  * the parameter.
                    409:  *
                    410:  * For more details of the parsing see above.
                    411:  *
                    412:  * Returns a pointer to the first element of dest (or the newly allocated copy)
                    413:  * or NULL in error cases
                    414:  */
                    415: QEMUOptionParameter *parse_option_parameters(const char *param,
                    416:     QEMUOptionParameter *list, QEMUOptionParameter *dest)
                    417: {
                    418:     QEMUOptionParameter *allocated = NULL;
                    419:     char name[256];
                    420:     char value[256];
                    421:     char *param_delim, *value_delim;
                    422:     char next_delim;
                    423: 
                    424:     if (list == NULL) {
                    425:         return NULL;
                    426:     }
                    427: 
                    428:     if (dest == NULL) {
1.1.1.4   root      429:         dest = allocated = append_option_parameters(NULL, list);
1.1       root      430:     }
                    431: 
                    432:     while (*param) {
                    433: 
                    434:         // Find parameter name and value in the string
                    435:         param_delim = strchr(param, ',');
                    436:         value_delim = strchr(param, '=');
                    437: 
                    438:         if (value_delim && (value_delim < param_delim || !param_delim)) {
                    439:             next_delim = '=';
                    440:         } else {
                    441:             next_delim = ',';
                    442:             value_delim = NULL;
                    443:         }
                    444: 
                    445:         param = get_opt_name(name, sizeof(name), param, next_delim);
                    446:         if (value_delim) {
                    447:             param = get_opt_value(value, sizeof(value), param + 1);
                    448:         }
                    449:         if (*param != '\0') {
                    450:             param++;
                    451:         }
                    452: 
                    453:         // Set the parameter
                    454:         if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
                    455:             goto fail;
                    456:         }
                    457:     }
                    458: 
                    459:     return dest;
                    460: 
                    461: fail:
                    462:     // Only free the list if it was newly allocated
                    463:     free_option_parameters(allocated);
                    464:     return NULL;
                    465: }
                    466: 
                    467: /*
                    468:  * Prints all options of a list that have a value to stdout
                    469:  */
                    470: void print_option_parameters(QEMUOptionParameter *list)
                    471: {
                    472:     while (list && list->name) {
                    473:         switch (list->type) {
                    474:             case OPT_STRING:
                    475:                  if (list->value.s != NULL) {
                    476:                      printf("%s='%s' ", list->name, list->value.s);
                    477:                  }
                    478:                 break;
                    479:             case OPT_FLAG:
                    480:                 printf("%s=%s ", list->name, list->value.n ? "on" : "off");
                    481:                 break;
                    482:             case OPT_SIZE:
                    483:             case OPT_NUMBER:
                    484:                 printf("%s=%" PRId64 " ", list->name, list->value.n);
                    485:                 break;
                    486:             default:
1.1.1.6 ! root      487:                 printf("%s=(unknown type) ", list->name);
1.1       root      488:                 break;
                    489:         }
                    490:         list++;
                    491:     }
                    492: }
                    493: 
                    494: /*
                    495:  * Prints an overview of all available options
                    496:  */
                    497: void print_option_help(QEMUOptionParameter *list)
                    498: {
                    499:     printf("Supported options:\n");
                    500:     while (list && list->name) {
                    501:         printf("%-16s %s\n", list->name,
                    502:             list->help ? list->help : "No description available");
                    503:         list++;
                    504:     }
                    505: }
1.1.1.2   root      506: 
                    507: /* ------------------------------------------------------------------ */
                    508: 
                    509: struct QemuOpt {
                    510:     const char   *name;
                    511:     const char   *str;
                    512: 
1.1.1.3   root      513:     const QemuOptDesc *desc;
1.1.1.2   root      514:     union {
1.1.1.5   root      515:         bool boolean;
1.1.1.2   root      516:         uint64_t uint;
                    517:     } value;
                    518: 
                    519:     QemuOpts     *opts;
                    520:     QTAILQ_ENTRY(QemuOpt) next;
                    521: };
                    522: 
                    523: struct QemuOpts {
                    524:     char *id;
                    525:     QemuOptsList *list;
1.1.1.3   root      526:     Location loc;
1.1.1.2   root      527:     QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
                    528:     QTAILQ_ENTRY(QemuOpts) next;
                    529: };
                    530: 
                    531: static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
                    532: {
                    533:     QemuOpt *opt;
                    534: 
                    535:     QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
                    536:         if (strcmp(opt->name, name) != 0)
                    537:             continue;
                    538:         return opt;
                    539:     }
                    540:     return NULL;
                    541: }
                    542: 
                    543: const char *qemu_opt_get(QemuOpts *opts, const char *name)
                    544: {
                    545:     QemuOpt *opt = qemu_opt_find(opts, name);
                    546:     return opt ? opt->str : NULL;
                    547: }
                    548: 
1.1.1.5   root      549: bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
1.1.1.2   root      550: {
                    551:     QemuOpt *opt = qemu_opt_find(opts, name);
                    552: 
                    553:     if (opt == NULL)
                    554:         return defval;
                    555:     assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
                    556:     return opt->value.boolean;
                    557: }
                    558: 
                    559: uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
                    560: {
                    561:     QemuOpt *opt = qemu_opt_find(opts, name);
                    562: 
                    563:     if (opt == NULL)
                    564:         return defval;
                    565:     assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
                    566:     return opt->value.uint;
                    567: }
                    568: 
                    569: uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
                    570: {
                    571:     QemuOpt *opt = qemu_opt_find(opts, name);
                    572: 
                    573:     if (opt == NULL)
                    574:         return defval;
                    575:     assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
                    576:     return opt->value.uint;
                    577: }
                    578: 
                    579: static int qemu_opt_parse(QemuOpt *opt)
                    580: {
                    581:     if (opt->desc == NULL)
                    582:         return 0;
                    583:     switch (opt->desc->type) {
                    584:     case QEMU_OPT_STRING:
                    585:         /* nothing */
                    586:         return 0;
                    587:     case QEMU_OPT_BOOL:
                    588:         return parse_option_bool(opt->name, opt->str, &opt->value.boolean);
                    589:     case QEMU_OPT_NUMBER:
                    590:         return parse_option_number(opt->name, opt->str, &opt->value.uint);
                    591:     case QEMU_OPT_SIZE:
                    592:         return parse_option_size(opt->name, opt->str, &opt->value.uint);
                    593:     default:
                    594:         abort();
                    595:     }
                    596: }
                    597: 
                    598: static void qemu_opt_del(QemuOpt *opt)
                    599: {
                    600:     QTAILQ_REMOVE(&opt->opts->head, opt, next);
1.1.1.5   root      601:     g_free((/* !const */ char*)opt->name);
                    602:     g_free((/* !const */ char*)opt->str);
                    603:     g_free(opt);
1.1.1.2   root      604: }
                    605: 
1.1.1.6 ! root      606: static int opt_set(QemuOpts *opts, const char *name, const char *value,
        !           607:                    bool prepend)
1.1.1.2   root      608: {
                    609:     QemuOpt *opt;
1.1.1.3   root      610:     const QemuOptDesc *desc = opts->list->desc;
1.1.1.2   root      611:     int i;
                    612: 
                    613:     for (i = 0; desc[i].name != NULL; i++) {
                    614:         if (strcmp(desc[i].name, name) == 0) {
                    615:             break;
                    616:         }
                    617:     }
                    618:     if (desc[i].name == NULL) {
                    619:         if (i == 0) {
                    620:             /* empty list -> allow any */;
                    621:         } else {
1.1.1.3   root      622:             qerror_report(QERR_INVALID_PARAMETER, name);
1.1.1.2   root      623:             return -1;
                    624:         }
                    625:     }
                    626: 
1.1.1.5   root      627:     opt = g_malloc0(sizeof(*opt));
                    628:     opt->name = g_strdup(name);
1.1.1.2   root      629:     opt->opts = opts;
1.1.1.6 ! root      630:     if (prepend) {
        !           631:         QTAILQ_INSERT_HEAD(&opts->head, opt, next);
        !           632:     } else {
        !           633:         QTAILQ_INSERT_TAIL(&opts->head, opt, next);
        !           634:     }
1.1.1.2   root      635:     if (desc[i].name != NULL) {
                    636:         opt->desc = desc+i;
                    637:     }
                    638:     if (value) {
1.1.1.5   root      639:         opt->str = g_strdup(value);
1.1.1.2   root      640:     }
                    641:     if (qemu_opt_parse(opt) < 0) {
                    642:         qemu_opt_del(opt);
                    643:         return -1;
                    644:     }
                    645:     return 0;
                    646: }
                    647: 
1.1.1.6 ! root      648: int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
        !           649: {
        !           650:     return opt_set(opts, name, value, false);
        !           651: }
        !           652: 
1.1.1.5   root      653: int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
                    654: {
                    655:     QemuOpt *opt;
                    656:     const QemuOptDesc *desc = opts->list->desc;
                    657:     int i;
                    658: 
                    659:     for (i = 0; desc[i].name != NULL; i++) {
                    660:         if (strcmp(desc[i].name, name) == 0) {
                    661:             break;
                    662:         }
                    663:     }
                    664:     if (desc[i].name == NULL) {
                    665:         if (i == 0) {
                    666:             /* empty list -> allow any */;
                    667:         } else {
                    668:             qerror_report(QERR_INVALID_PARAMETER, name);
                    669:             return -1;
                    670:         }
                    671:     }
                    672: 
                    673:     opt = g_malloc0(sizeof(*opt));
                    674:     opt->name = g_strdup(name);
                    675:     opt->opts = opts;
                    676:     QTAILQ_INSERT_TAIL(&opts->head, opt, next);
                    677:     if (desc[i].name != NULL) {
                    678:         opt->desc = desc+i;
                    679:     }
                    680:     opt->value.boolean = !!val;
                    681:     return 0;
                    682: }
                    683: 
1.1.1.2   root      684: int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
                    685:                      int abort_on_failure)
                    686: {
                    687:     QemuOpt *opt;
                    688:     int rc = 0;
                    689: 
                    690:     QTAILQ_FOREACH(opt, &opts->head, next) {
                    691:         rc = func(opt->name, opt->str, opaque);
                    692:         if (abort_on_failure  &&  rc != 0)
                    693:             break;
                    694:     }
                    695:     return rc;
                    696: }
                    697: 
                    698: QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
                    699: {
                    700:     QemuOpts *opts;
                    701: 
                    702:     QTAILQ_FOREACH(opts, &list->head, next) {
                    703:         if (!opts->id) {
1.1.1.6 ! root      704:             if (!id) {
        !           705:                 return opts;
        !           706:             }
1.1.1.2   root      707:             continue;
                    708:         }
                    709:         if (strcmp(opts->id, id) != 0) {
                    710:             continue;
                    711:         }
                    712:         return opts;
                    713:     }
                    714:     return NULL;
                    715: }
                    716: 
1.1.1.3   root      717: static int id_wellformed(const char *id)
                    718: {
                    719:     int i;
                    720: 
                    721:     if (!qemu_isalpha(id[0])) {
                    722:         return 0;
                    723:     }
                    724:     for (i = 1; id[i]; i++) {
                    725:         if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) {
                    726:             return 0;
                    727:         }
                    728:     }
                    729:     return 1;
                    730: }
                    731: 
1.1.1.2   root      732: QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
                    733: {
                    734:     QemuOpts *opts = NULL;
                    735: 
                    736:     if (id) {
1.1.1.3   root      737:         if (!id_wellformed(id)) {
                    738:             qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
                    739:             error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
                    740:             return NULL;
                    741:         }
1.1.1.2   root      742:         opts = qemu_opts_find(list, id);
                    743:         if (opts != NULL) {
1.1.1.6 ! root      744:             if (fail_if_exists && !list->merge_lists) {
1.1.1.3   root      745:                 qerror_report(QERR_DUPLICATE_ID, id, list->name);
1.1.1.2   root      746:                 return NULL;
                    747:             } else {
                    748:                 return opts;
                    749:             }
                    750:         }
1.1.1.6 ! root      751:     } else if (list->merge_lists) {
        !           752:         opts = qemu_opts_find(list, NULL);
        !           753:         if (opts) {
        !           754:             return opts;
        !           755:         }
1.1.1.2   root      756:     }
1.1.1.5   root      757:     opts = g_malloc0(sizeof(*opts));
1.1.1.2   root      758:     if (id) {
1.1.1.5   root      759:         opts->id = g_strdup(id);
1.1.1.2   root      760:     }
                    761:     opts->list = list;
1.1.1.3   root      762:     loc_save(&opts->loc);
1.1.1.2   root      763:     QTAILQ_INIT(&opts->head);
                    764:     QTAILQ_INSERT_TAIL(&list->head, opts, next);
                    765:     return opts;
                    766: }
                    767: 
1.1.1.3   root      768: void qemu_opts_reset(QemuOptsList *list)
                    769: {
                    770:     QemuOpts *opts, *next_opts;
                    771: 
                    772:     QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) {
                    773:         qemu_opts_del(opts);
                    774:     }
                    775: }
                    776: 
                    777: void qemu_opts_loc_restore(QemuOpts *opts)
                    778: {
                    779:     loc_restore(&opts->loc);
                    780: }
                    781: 
1.1.1.2   root      782: int qemu_opts_set(QemuOptsList *list, const char *id,
                    783:                   const char *name, const char *value)
                    784: {
                    785:     QemuOpts *opts;
                    786: 
                    787:     opts = qemu_opts_create(list, id, 1);
                    788:     if (opts == NULL) {
                    789:         return -1;
                    790:     }
                    791:     return qemu_opt_set(opts, name, value);
                    792: }
                    793: 
                    794: const char *qemu_opts_id(QemuOpts *opts)
                    795: {
                    796:     return opts->id;
                    797: }
                    798: 
                    799: void qemu_opts_del(QemuOpts *opts)
                    800: {
                    801:     QemuOpt *opt;
                    802: 
                    803:     for (;;) {
                    804:         opt = QTAILQ_FIRST(&opts->head);
                    805:         if (opt == NULL)
                    806:             break;
                    807:         qemu_opt_del(opt);
                    808:     }
                    809:     QTAILQ_REMOVE(&opts->list->head, opts, next);
1.1.1.5   root      810:     g_free(opts->id);
                    811:     g_free(opts);
1.1.1.2   root      812: }
                    813: 
                    814: int qemu_opts_print(QemuOpts *opts, void *dummy)
                    815: {
                    816:     QemuOpt *opt;
                    817: 
                    818:     fprintf(stderr, "%s: %s:", opts->list->name,
                    819:             opts->id ? opts->id : "<noid>");
                    820:     QTAILQ_FOREACH(opt, &opts->head, next) {
                    821:         fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
                    822:     }
                    823:     fprintf(stderr, "\n");
                    824:     return 0;
                    825: }
                    826: 
1.1.1.6 ! root      827: static int opts_do_parse(QemuOpts *opts, const char *params,
        !           828:                          const char *firstname, bool prepend)
1.1.1.2   root      829: {
                    830:     char option[128], value[1024];
                    831:     const char *p,*pe,*pc;
                    832: 
                    833:     for (p = params; *p != '\0'; p++) {
                    834:         pe = strchr(p, '=');
                    835:         pc = strchr(p, ',');
                    836:         if (!pe || (pc && pc < pe)) {
                    837:             /* found "foo,more" */
                    838:             if (p == params && firstname) {
                    839:                 /* implicitly named first option */
                    840:                 pstrcpy(option, sizeof(option), firstname);
                    841:                 p = get_opt_value(value, sizeof(value), p);
                    842:             } else {
                    843:                 /* option without value, probably a flag */
                    844:                 p = get_opt_name(option, sizeof(option), p, ',');
                    845:                 if (strncmp(option, "no", 2) == 0) {
                    846:                     memmove(option, option+2, strlen(option+2)+1);
                    847:                     pstrcpy(value, sizeof(value), "off");
                    848:                 } else {
                    849:                     pstrcpy(value, sizeof(value), "on");
                    850:                 }
                    851:             }
                    852:         } else {
                    853:             /* found "foo=bar,more" */
                    854:             p = get_opt_name(option, sizeof(option), p, '=');
                    855:             if (*p != '=') {
                    856:                 break;
                    857:             }
                    858:             p++;
                    859:             p = get_opt_value(value, sizeof(value), p);
                    860:         }
                    861:         if (strcmp(option, "id") != 0) {
                    862:             /* store and parse */
1.1.1.6 ! root      863:             if (opt_set(opts, option, value, prepend) == -1) {
1.1.1.2   root      864:                 return -1;
                    865:             }
                    866:         }
                    867:         if (*p != ',') {
                    868:             break;
                    869:         }
                    870:     }
                    871:     return 0;
                    872: }
                    873: 
1.1.1.6 ! root      874: int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
        !           875: {
        !           876:     return opts_do_parse(opts, params, firstname, false);
        !           877: }
        !           878: 
        !           879: static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
        !           880:                             int permit_abbrev, bool defaults)
1.1.1.2   root      881: {
1.1.1.3   root      882:     const char *firstname;
1.1.1.2   root      883:     char value[1024], *id = NULL;
                    884:     const char *p;
                    885:     QemuOpts *opts;
                    886: 
1.1.1.3   root      887:     assert(!permit_abbrev || list->implied_opt_name);
                    888:     firstname = permit_abbrev ? list->implied_opt_name : NULL;
                    889: 
1.1.1.2   root      890:     if (strncmp(params, "id=", 3) == 0) {
                    891:         get_opt_value(value, sizeof(value), params+3);
1.1.1.3   root      892:         id = value;
1.1.1.2   root      893:     } else if ((p = strstr(params, ",id=")) != NULL) {
                    894:         get_opt_value(value, sizeof(value), p+4);
1.1.1.3   root      895:         id = value;
1.1.1.2   root      896:     }
1.1.1.6 ! root      897:     if (defaults) {
        !           898:         if (!id && !QTAILQ_EMPTY(&list->head)) {
        !           899:             opts = qemu_opts_find(list, NULL);
        !           900:         } else {
        !           901:             opts = qemu_opts_create(list, id, 0);
        !           902:         }
        !           903:     } else {
        !           904:         opts = qemu_opts_create(list, id, 1);
        !           905:     }
1.1.1.2   root      906:     if (opts == NULL)
                    907:         return NULL;
                    908: 
1.1.1.6 ! root      909:     if (opts_do_parse(opts, params, firstname, defaults) != 0) {
1.1.1.2   root      910:         qemu_opts_del(opts);
                    911:         return NULL;
                    912:     }
                    913: 
                    914:     return opts;
                    915: }
                    916: 
1.1.1.6 ! root      917: QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
        !           918:                           int permit_abbrev)
        !           919: {
        !           920:     return opts_parse(list, params, permit_abbrev, false);
        !           921: }
        !           922: 
        !           923: void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
        !           924:                             int permit_abbrev)
        !           925: {
        !           926:     QemuOpts *opts;
        !           927: 
        !           928:     opts = opts_parse(list, params, permit_abbrev, true);
        !           929:     assert(opts);
        !           930: }
        !           931: 
1.1.1.3   root      932: static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
                    933: {
                    934:     char buf[32];
                    935:     const char *value;
                    936:     int n;
                    937: 
                    938:     if (!strcmp(key, "id")) {
                    939:         return;
                    940:     }
                    941: 
                    942:     switch (qobject_type(obj)) {
                    943:     case QTYPE_QSTRING:
                    944:         value = qstring_get_str(qobject_to_qstring(obj));
                    945:         break;
                    946:     case QTYPE_QINT:
                    947:         n = snprintf(buf, sizeof(buf), "%" PRId64,
                    948:                      qint_get_int(qobject_to_qint(obj)));
                    949:         assert(n < sizeof(buf));
                    950:         value = buf;
                    951:         break;
                    952:     case QTYPE_QFLOAT:
                    953:         n = snprintf(buf, sizeof(buf), "%.17g",
                    954:                      qfloat_get_double(qobject_to_qfloat(obj)));
                    955:         assert(n < sizeof(buf));
                    956:         value = buf;
                    957:         break;
                    958:     case QTYPE_QBOOL:
                    959:         pstrcpy(buf, sizeof(buf),
                    960:                 qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off");
                    961:         value = buf;
                    962:         break;
                    963:     default:
                    964:         return;
                    965:     }
                    966:     qemu_opt_set(opaque, key, value);
                    967: }
                    968: 
                    969: /*
                    970:  * Create QemuOpts from a QDict.
                    971:  * Use value of key "id" as ID if it exists and is a QString.
                    972:  * Only QStrings, QInts, QFloats and QBools are copied.  Entries with
                    973:  * other types are silently ignored.
                    974:  */
                    975: QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
                    976: {
                    977:     QemuOpts *opts;
                    978: 
                    979:     opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1);
                    980:     if (opts == NULL)
                    981:         return NULL;
                    982: 
                    983:     qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
                    984:     return opts;
                    985: }
                    986: 
                    987: /*
                    988:  * Convert from QemuOpts to QDict.
                    989:  * The QDict values are of type QString.
                    990:  * TODO We'll want to use types appropriate for opt->desc->type, but
                    991:  * this is enough for now.
                    992:  */
                    993: QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
                    994: {
                    995:     QemuOpt *opt;
                    996:     QObject *val;
                    997: 
                    998:     if (!qdict) {
                    999:         qdict = qdict_new();
                   1000:     }
                   1001:     if (opts->id) {
                   1002:         qdict_put(qdict, "id", qstring_from_str(opts->id));
                   1003:     }
                   1004:     QTAILQ_FOREACH(opt, &opts->head, next) {
                   1005:         val = QOBJECT(qstring_from_str(opt->str));
                   1006:         qdict_put_obj(qdict, opt->name, val);
                   1007:     }
                   1008:     return qdict;
                   1009: }
                   1010: 
1.1.1.2   root     1011: /* Validate parsed opts against descriptions where no
                   1012:  * descriptions were provided in the QemuOptsList.
                   1013:  */
1.1.1.3   root     1014: int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
1.1.1.2   root     1015: {
                   1016:     QemuOpt *opt;
                   1017: 
                   1018:     assert(opts->list->desc[0].name == NULL);
                   1019: 
                   1020:     QTAILQ_FOREACH(opt, &opts->head, next) {
                   1021:         int i;
                   1022: 
                   1023:         for (i = 0; desc[i].name != NULL; i++) {
                   1024:             if (strcmp(desc[i].name, opt->name) == 0) {
                   1025:                 break;
                   1026:             }
                   1027:         }
                   1028:         if (desc[i].name == NULL) {
1.1.1.3   root     1029:             qerror_report(QERR_INVALID_PARAMETER, opt->name);
1.1.1.2   root     1030:             return -1;
                   1031:         }
                   1032: 
                   1033:         opt->desc = &desc[i];
                   1034: 
                   1035:         if (qemu_opt_parse(opt) < 0) {
                   1036:             return -1;
                   1037:         }
                   1038:     }
                   1039: 
                   1040:     return 0;
                   1041: }
                   1042: 
                   1043: int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
                   1044:                       int abort_on_failure)
                   1045: {
1.1.1.3   root     1046:     Location loc;
1.1.1.2   root     1047:     QemuOpts *opts;
                   1048:     int rc = 0;
                   1049: 
1.1.1.3   root     1050:     loc_push_none(&loc);
1.1.1.2   root     1051:     QTAILQ_FOREACH(opts, &list->head, next) {
1.1.1.3   root     1052:         loc_restore(&opts->loc);
                   1053:         rc |= func(opts, opaque);
1.1.1.2   root     1054:         if (abort_on_failure  &&  rc != 0)
                   1055:             break;
                   1056:     }
1.1.1.3   root     1057:     loc_pop(&loc);
1.1.1.2   root     1058:     return rc;
                   1059: }

unix.superglobalmegacorp.com