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

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:  *
1.1.1.4 ! root      397:  * list is the template option list. If dest is NULL, a new copy of list is
        !           398:  * created. If list is NULL, this function fails.
1.1       root      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: 
                    420:     if (list == NULL) {
                    421:         return NULL;
                    422:     }
                    423: 
                    424:     if (dest == NULL) {
1.1.1.4 ! root      425:         dest = allocated = append_option_parameters(NULL, list);
1.1       root      426:     }
                    427: 
                    428:     while (*param) {
                    429: 
                    430:         // Find parameter name and value in the string
                    431:         param_delim = strchr(param, ',');
                    432:         value_delim = strchr(param, '=');
                    433: 
                    434:         if (value_delim && (value_delim < param_delim || !param_delim)) {
                    435:             next_delim = '=';
                    436:         } else {
                    437:             next_delim = ',';
                    438:             value_delim = NULL;
                    439:         }
                    440: 
                    441:         param = get_opt_name(name, sizeof(name), param, next_delim);
                    442:         if (value_delim) {
                    443:             param = get_opt_value(value, sizeof(value), param + 1);
                    444:         }
                    445:         if (*param != '\0') {
                    446:             param++;
                    447:         }
                    448: 
                    449:         // Set the parameter
                    450:         if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
                    451:             goto fail;
                    452:         }
                    453:     }
                    454: 
                    455:     return dest;
                    456: 
                    457: fail:
                    458:     // Only free the list if it was newly allocated
                    459:     free_option_parameters(allocated);
                    460:     return NULL;
                    461: }
                    462: 
                    463: /*
                    464:  * Prints all options of a list that have a value to stdout
                    465:  */
                    466: void print_option_parameters(QEMUOptionParameter *list)
                    467: {
                    468:     while (list && list->name) {
                    469:         switch (list->type) {
                    470:             case OPT_STRING:
                    471:                  if (list->value.s != NULL) {
                    472:                      printf("%s='%s' ", list->name, list->value.s);
                    473:                  }
                    474:                 break;
                    475:             case OPT_FLAG:
                    476:                 printf("%s=%s ", list->name, list->value.n ? "on" : "off");
                    477:                 break;
                    478:             case OPT_SIZE:
                    479:             case OPT_NUMBER:
                    480:                 printf("%s=%" PRId64 " ", list->name, list->value.n);
                    481:                 break;
                    482:             default:
                    483:                 printf("%s=(unkown type) ", list->name);
                    484:                 break;
                    485:         }
                    486:         list++;
                    487:     }
                    488: }
                    489: 
                    490: /*
                    491:  * Prints an overview of all available options
                    492:  */
                    493: void print_option_help(QEMUOptionParameter *list)
                    494: {
                    495:     printf("Supported options:\n");
                    496:     while (list && list->name) {
                    497:         printf("%-16s %s\n", list->name,
                    498:             list->help ? list->help : "No description available");
                    499:         list++;
                    500:     }
                    501: }
1.1.1.2   root      502: 
                    503: /* ------------------------------------------------------------------ */
                    504: 
                    505: struct QemuOpt {
                    506:     const char   *name;
                    507:     const char   *str;
                    508: 
1.1.1.3   root      509:     const QemuOptDesc *desc;
1.1.1.2   root      510:     union {
                    511:         int      boolean;
                    512:         uint64_t uint;
                    513:     } value;
                    514: 
                    515:     QemuOpts     *opts;
                    516:     QTAILQ_ENTRY(QemuOpt) next;
                    517: };
                    518: 
                    519: struct QemuOpts {
                    520:     char *id;
                    521:     QemuOptsList *list;
1.1.1.3   root      522:     Location loc;
1.1.1.2   root      523:     QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
                    524:     QTAILQ_ENTRY(QemuOpts) next;
                    525: };
                    526: 
                    527: static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
                    528: {
                    529:     QemuOpt *opt;
                    530: 
                    531:     QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
                    532:         if (strcmp(opt->name, name) != 0)
                    533:             continue;
                    534:         return opt;
                    535:     }
                    536:     return NULL;
                    537: }
                    538: 
                    539: const char *qemu_opt_get(QemuOpts *opts, const char *name)
                    540: {
                    541:     QemuOpt *opt = qemu_opt_find(opts, name);
                    542:     return opt ? opt->str : NULL;
                    543: }
                    544: 
                    545: int qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval)
                    546: {
                    547:     QemuOpt *opt = qemu_opt_find(opts, name);
                    548: 
                    549:     if (opt == NULL)
                    550:         return defval;
                    551:     assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
                    552:     return opt->value.boolean;
                    553: }
                    554: 
                    555: uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
                    556: {
                    557:     QemuOpt *opt = qemu_opt_find(opts, name);
                    558: 
                    559:     if (opt == NULL)
                    560:         return defval;
                    561:     assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
                    562:     return opt->value.uint;
                    563: }
                    564: 
                    565: uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
                    566: {
                    567:     QemuOpt *opt = qemu_opt_find(opts, name);
                    568: 
                    569:     if (opt == NULL)
                    570:         return defval;
                    571:     assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
                    572:     return opt->value.uint;
                    573: }
                    574: 
                    575: static int qemu_opt_parse(QemuOpt *opt)
                    576: {
                    577:     if (opt->desc == NULL)
                    578:         return 0;
                    579:     switch (opt->desc->type) {
                    580:     case QEMU_OPT_STRING:
                    581:         /* nothing */
                    582:         return 0;
                    583:     case QEMU_OPT_BOOL:
                    584:         return parse_option_bool(opt->name, opt->str, &opt->value.boolean);
                    585:     case QEMU_OPT_NUMBER:
                    586:         return parse_option_number(opt->name, opt->str, &opt->value.uint);
                    587:     case QEMU_OPT_SIZE:
                    588:         return parse_option_size(opt->name, opt->str, &opt->value.uint);
                    589:     default:
                    590:         abort();
                    591:     }
                    592: }
                    593: 
                    594: static void qemu_opt_del(QemuOpt *opt)
                    595: {
                    596:     QTAILQ_REMOVE(&opt->opts->head, opt, next);
                    597:     qemu_free((/* !const */ char*)opt->name);
                    598:     qemu_free((/* !const */ char*)opt->str);
                    599:     qemu_free(opt);
                    600: }
                    601: 
                    602: int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
                    603: {
                    604:     QemuOpt *opt;
1.1.1.3   root      605:     const QemuOptDesc *desc = opts->list->desc;
1.1.1.2   root      606:     int i;
                    607: 
                    608:     for (i = 0; desc[i].name != NULL; i++) {
                    609:         if (strcmp(desc[i].name, name) == 0) {
                    610:             break;
                    611:         }
                    612:     }
                    613:     if (desc[i].name == NULL) {
                    614:         if (i == 0) {
                    615:             /* empty list -> allow any */;
                    616:         } else {
1.1.1.3   root      617:             qerror_report(QERR_INVALID_PARAMETER, name);
1.1.1.2   root      618:             return -1;
                    619:         }
                    620:     }
                    621: 
                    622:     opt = qemu_mallocz(sizeof(*opt));
                    623:     opt->name = qemu_strdup(name);
                    624:     opt->opts = opts;
                    625:     QTAILQ_INSERT_TAIL(&opts->head, opt, next);
                    626:     if (desc[i].name != NULL) {
                    627:         opt->desc = desc+i;
                    628:     }
                    629:     if (value) {
                    630:         opt->str = qemu_strdup(value);
                    631:     }
                    632:     if (qemu_opt_parse(opt) < 0) {
                    633:         qemu_opt_del(opt);
                    634:         return -1;
                    635:     }
                    636:     return 0;
                    637: }
                    638: 
                    639: int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
                    640:                      int abort_on_failure)
                    641: {
                    642:     QemuOpt *opt;
                    643:     int rc = 0;
                    644: 
                    645:     QTAILQ_FOREACH(opt, &opts->head, next) {
                    646:         rc = func(opt->name, opt->str, opaque);
                    647:         if (abort_on_failure  &&  rc != 0)
                    648:             break;
                    649:     }
                    650:     return rc;
                    651: }
                    652: 
                    653: QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
                    654: {
                    655:     QemuOpts *opts;
                    656: 
                    657:     QTAILQ_FOREACH(opts, &list->head, next) {
                    658:         if (!opts->id) {
                    659:             continue;
                    660:         }
                    661:         if (strcmp(opts->id, id) != 0) {
                    662:             continue;
                    663:         }
                    664:         return opts;
                    665:     }
                    666:     return NULL;
                    667: }
                    668: 
1.1.1.3   root      669: static int id_wellformed(const char *id)
                    670: {
                    671:     int i;
                    672: 
                    673:     if (!qemu_isalpha(id[0])) {
                    674:         return 0;
                    675:     }
                    676:     for (i = 1; id[i]; i++) {
                    677:         if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) {
                    678:             return 0;
                    679:         }
                    680:     }
                    681:     return 1;
                    682: }
                    683: 
1.1.1.2   root      684: QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
                    685: {
                    686:     QemuOpts *opts = NULL;
                    687: 
                    688:     if (id) {
1.1.1.3   root      689:         if (!id_wellformed(id)) {
                    690:             qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
                    691:             error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
                    692:             return NULL;
                    693:         }
1.1.1.2   root      694:         opts = qemu_opts_find(list, id);
                    695:         if (opts != NULL) {
                    696:             if (fail_if_exists) {
1.1.1.3   root      697:                 qerror_report(QERR_DUPLICATE_ID, id, list->name);
1.1.1.2   root      698:                 return NULL;
                    699:             } else {
                    700:                 return opts;
                    701:             }
                    702:         }
                    703:     }
                    704:     opts = qemu_mallocz(sizeof(*opts));
                    705:     if (id) {
                    706:         opts->id = qemu_strdup(id);
                    707:     }
                    708:     opts->list = list;
1.1.1.3   root      709:     loc_save(&opts->loc);
1.1.1.2   root      710:     QTAILQ_INIT(&opts->head);
                    711:     QTAILQ_INSERT_TAIL(&list->head, opts, next);
                    712:     return opts;
                    713: }
                    714: 
1.1.1.3   root      715: void qemu_opts_reset(QemuOptsList *list)
                    716: {
                    717:     QemuOpts *opts, *next_opts;
                    718: 
                    719:     QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) {
                    720:         qemu_opts_del(opts);
                    721:     }
                    722: }
                    723: 
                    724: void qemu_opts_loc_restore(QemuOpts *opts)
                    725: {
                    726:     loc_restore(&opts->loc);
                    727: }
                    728: 
1.1.1.2   root      729: int qemu_opts_set(QemuOptsList *list, const char *id,
                    730:                   const char *name, const char *value)
                    731: {
                    732:     QemuOpts *opts;
                    733: 
                    734:     opts = qemu_opts_create(list, id, 1);
                    735:     if (opts == NULL) {
                    736:         return -1;
                    737:     }
                    738:     return qemu_opt_set(opts, name, value);
                    739: }
                    740: 
                    741: const char *qemu_opts_id(QemuOpts *opts)
                    742: {
                    743:     return opts->id;
                    744: }
                    745: 
                    746: void qemu_opts_del(QemuOpts *opts)
                    747: {
                    748:     QemuOpt *opt;
                    749: 
                    750:     for (;;) {
                    751:         opt = QTAILQ_FIRST(&opts->head);
                    752:         if (opt == NULL)
                    753:             break;
                    754:         qemu_opt_del(opt);
                    755:     }
                    756:     QTAILQ_REMOVE(&opts->list->head, opts, next);
                    757:     qemu_free(opts->id);
                    758:     qemu_free(opts);
                    759: }
                    760: 
                    761: int qemu_opts_print(QemuOpts *opts, void *dummy)
                    762: {
                    763:     QemuOpt *opt;
                    764: 
                    765:     fprintf(stderr, "%s: %s:", opts->list->name,
                    766:             opts->id ? opts->id : "<noid>");
                    767:     QTAILQ_FOREACH(opt, &opts->head, next) {
                    768:         fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
                    769:     }
                    770:     fprintf(stderr, "\n");
                    771:     return 0;
                    772: }
                    773: 
                    774: int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
                    775: {
                    776:     char option[128], value[1024];
                    777:     const char *p,*pe,*pc;
                    778: 
                    779:     for (p = params; *p != '\0'; p++) {
                    780:         pe = strchr(p, '=');
                    781:         pc = strchr(p, ',');
                    782:         if (!pe || (pc && pc < pe)) {
                    783:             /* found "foo,more" */
                    784:             if (p == params && firstname) {
                    785:                 /* implicitly named first option */
                    786:                 pstrcpy(option, sizeof(option), firstname);
                    787:                 p = get_opt_value(value, sizeof(value), p);
                    788:             } else {
                    789:                 /* option without value, probably a flag */
                    790:                 p = get_opt_name(option, sizeof(option), p, ',');
                    791:                 if (strncmp(option, "no", 2) == 0) {
                    792:                     memmove(option, option+2, strlen(option+2)+1);
                    793:                     pstrcpy(value, sizeof(value), "off");
                    794:                 } else {
                    795:                     pstrcpy(value, sizeof(value), "on");
                    796:                 }
                    797:             }
                    798:         } else {
                    799:             /* found "foo=bar,more" */
                    800:             p = get_opt_name(option, sizeof(option), p, '=');
                    801:             if (*p != '=') {
                    802:                 break;
                    803:             }
                    804:             p++;
                    805:             p = get_opt_value(value, sizeof(value), p);
                    806:         }
                    807:         if (strcmp(option, "id") != 0) {
                    808:             /* store and parse */
                    809:             if (qemu_opt_set(opts, option, value) == -1) {
                    810:                 return -1;
                    811:             }
                    812:         }
                    813:         if (*p != ',') {
                    814:             break;
                    815:         }
                    816:     }
                    817:     return 0;
                    818: }
                    819: 
1.1.1.3   root      820: QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
                    821:                           int permit_abbrev)
1.1.1.2   root      822: {
1.1.1.3   root      823:     const char *firstname;
1.1.1.2   root      824:     char value[1024], *id = NULL;
                    825:     const char *p;
                    826:     QemuOpts *opts;
                    827: 
1.1.1.3   root      828:     assert(!permit_abbrev || list->implied_opt_name);
                    829:     firstname = permit_abbrev ? list->implied_opt_name : NULL;
                    830: 
1.1.1.2   root      831:     if (strncmp(params, "id=", 3) == 0) {
                    832:         get_opt_value(value, sizeof(value), params+3);
1.1.1.3   root      833:         id = value;
1.1.1.2   root      834:     } else if ((p = strstr(params, ",id=")) != NULL) {
                    835:         get_opt_value(value, sizeof(value), p+4);
1.1.1.3   root      836:         id = value;
1.1.1.2   root      837:     }
                    838:     opts = qemu_opts_create(list, id, 1);
                    839:     if (opts == NULL)
                    840:         return NULL;
                    841: 
                    842:     if (qemu_opts_do_parse(opts, params, firstname) != 0) {
                    843:         qemu_opts_del(opts);
                    844:         return NULL;
                    845:     }
                    846: 
                    847:     return opts;
                    848: }
                    849: 
1.1.1.3   root      850: static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
                    851: {
                    852:     char buf[32];
                    853:     const char *value;
                    854:     int n;
                    855: 
                    856:     if (!strcmp(key, "id")) {
                    857:         return;
                    858:     }
                    859: 
                    860:     switch (qobject_type(obj)) {
                    861:     case QTYPE_QSTRING:
                    862:         value = qstring_get_str(qobject_to_qstring(obj));
                    863:         break;
                    864:     case QTYPE_QINT:
                    865:         n = snprintf(buf, sizeof(buf), "%" PRId64,
                    866:                      qint_get_int(qobject_to_qint(obj)));
                    867:         assert(n < sizeof(buf));
                    868:         value = buf;
                    869:         break;
                    870:     case QTYPE_QFLOAT:
                    871:         n = snprintf(buf, sizeof(buf), "%.17g",
                    872:                      qfloat_get_double(qobject_to_qfloat(obj)));
                    873:         assert(n < sizeof(buf));
                    874:         value = buf;
                    875:         break;
                    876:     case QTYPE_QBOOL:
                    877:         pstrcpy(buf, sizeof(buf),
                    878:                 qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off");
                    879:         value = buf;
                    880:         break;
                    881:     default:
                    882:         return;
                    883:     }
                    884:     qemu_opt_set(opaque, key, value);
                    885: }
                    886: 
                    887: /*
                    888:  * Create QemuOpts from a QDict.
                    889:  * Use value of key "id" as ID if it exists and is a QString.
                    890:  * Only QStrings, QInts, QFloats and QBools are copied.  Entries with
                    891:  * other types are silently ignored.
                    892:  */
                    893: QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
                    894: {
                    895:     QemuOpts *opts;
                    896: 
                    897:     opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1);
                    898:     if (opts == NULL)
                    899:         return NULL;
                    900: 
                    901:     qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
                    902:     return opts;
                    903: }
                    904: 
                    905: /*
                    906:  * Convert from QemuOpts to QDict.
                    907:  * The QDict values are of type QString.
                    908:  * TODO We'll want to use types appropriate for opt->desc->type, but
                    909:  * this is enough for now.
                    910:  */
                    911: QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
                    912: {
                    913:     QemuOpt *opt;
                    914:     QObject *val;
                    915: 
                    916:     if (!qdict) {
                    917:         qdict = qdict_new();
                    918:     }
                    919:     if (opts->id) {
                    920:         qdict_put(qdict, "id", qstring_from_str(opts->id));
                    921:     }
                    922:     QTAILQ_FOREACH(opt, &opts->head, next) {
                    923:         val = QOBJECT(qstring_from_str(opt->str));
                    924:         qdict_put_obj(qdict, opt->name, val);
                    925:     }
                    926:     return qdict;
                    927: }
                    928: 
1.1.1.2   root      929: /* Validate parsed opts against descriptions where no
                    930:  * descriptions were provided in the QemuOptsList.
                    931:  */
1.1.1.3   root      932: int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
1.1.1.2   root      933: {
                    934:     QemuOpt *opt;
                    935: 
                    936:     assert(opts->list->desc[0].name == NULL);
                    937: 
                    938:     QTAILQ_FOREACH(opt, &opts->head, next) {
                    939:         int i;
                    940: 
                    941:         for (i = 0; desc[i].name != NULL; i++) {
                    942:             if (strcmp(desc[i].name, opt->name) == 0) {
                    943:                 break;
                    944:             }
                    945:         }
                    946:         if (desc[i].name == NULL) {
1.1.1.3   root      947:             qerror_report(QERR_INVALID_PARAMETER, opt->name);
1.1.1.2   root      948:             return -1;
                    949:         }
                    950: 
                    951:         opt->desc = &desc[i];
                    952: 
                    953:         if (qemu_opt_parse(opt) < 0) {
                    954:             return -1;
                    955:         }
                    956:     }
                    957: 
                    958:     return 0;
                    959: }
                    960: 
                    961: int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
                    962:                       int abort_on_failure)
                    963: {
1.1.1.3   root      964:     Location loc;
1.1.1.2   root      965:     QemuOpts *opts;
                    966:     int rc = 0;
                    967: 
1.1.1.3   root      968:     loc_push_none(&loc);
1.1.1.2   root      969:     QTAILQ_FOREACH(opts, &list->head, next) {
1.1.1.3   root      970:         loc_restore(&opts->loc);
                    971:         rc |= func(opts, opaque);
1.1.1.2   root      972:         if (abort_on_failure  &&  rc != 0)
                    973:             break;
                    974:     }
1.1.1.3   root      975:     loc_pop(&loc);
1.1.1.2   root      976:     return rc;
                    977: }

unix.superglobalmegacorp.com