xref: /openbmc/qemu/util/qemu-option.c (revision da34e65c)
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 "qemu/osdep.h"
27 
28 #include "qapi/error.h"
29 #include "qemu-common.h"
30 #include "qemu/error-report.h"
31 #include "qapi/qmp/types.h"
32 #include "qapi/qmp/qerror.h"
33 #include "qemu/option_int.h"
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 
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 static void parse_option_bool(const char *name, const char *value, bool *ret,
126                               Error **errp)
127 {
128     if (value != NULL) {
129         if (!strcmp(value, "on")) {
130             *ret = 1;
131         } else if (!strcmp(value, "off")) {
132             *ret = 0;
133         } else {
134             error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
135                        name, "'on' or 'off'");
136         }
137     } else {
138         *ret = 1;
139     }
140 }
141 
142 static void parse_option_number(const char *name, const char *value,
143                                 uint64_t *ret, Error **errp)
144 {
145     char *postfix;
146     uint64_t number;
147 
148     if (value != NULL) {
149         number = strtoull(value, &postfix, 0);
150         if (*postfix != '\0') {
151             error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
152             return;
153         }
154         *ret = number;
155     } else {
156         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
157     }
158 }
159 
160 static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
161                                             const char *name)
162 {
163     int i;
164 
165     for (i = 0; desc[i].name != NULL; i++) {
166         if (strcmp(desc[i].name, name) == 0) {
167             return &desc[i];
168         }
169     }
170 
171     return NULL;
172 }
173 
174 void parse_option_size(const char *name, const char *value,
175                        uint64_t *ret, Error **errp)
176 {
177     char *postfix;
178     double sizef;
179 
180     if (value != NULL) {
181         sizef = strtod(value, &postfix);
182         if (sizef < 0 || sizef > UINT64_MAX) {
183             error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
184                              "a non-negative number below 2^64");
185             return;
186         }
187         switch (*postfix) {
188         case 'T':
189             sizef *= 1024;
190             /* fall through */
191         case 'G':
192             sizef *= 1024;
193             /* fall through */
194         case 'M':
195             sizef *= 1024;
196             /* fall through */
197         case 'K':
198         case 'k':
199             sizef *= 1024;
200             /* fall through */
201         case 'b':
202         case '\0':
203             *ret = (uint64_t) sizef;
204             break;
205         default:
206             error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
207             error_append_hint(errp, "You may use k, M, G or T suffixes for "
208                     "kilobytes, megabytes, gigabytes and terabytes.\n");
209             return;
210         }
211     } else {
212         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
213     }
214 }
215 
216 bool has_help_option(const char *param)
217 {
218     size_t buflen = strlen(param) + 1;
219     char *buf = g_malloc(buflen);
220     const char *p = param;
221     bool result = false;
222 
223     while (*p) {
224         p = get_opt_value(buf, buflen, p);
225         if (*p) {
226             p++;
227         }
228 
229         if (is_help_option(buf)) {
230             result = true;
231             goto out;
232         }
233     }
234 
235 out:
236     g_free(buf);
237     return result;
238 }
239 
240 bool is_valid_option_list(const char *param)
241 {
242     size_t buflen = strlen(param) + 1;
243     char *buf = g_malloc(buflen);
244     const char *p = param;
245     bool result = true;
246 
247     while (*p) {
248         p = get_opt_value(buf, buflen, p);
249         if (*p && !*++p) {
250             result = false;
251             goto out;
252         }
253 
254         if (!*buf || *buf == ',') {
255             result = false;
256             goto out;
257         }
258     }
259 
260 out:
261     g_free(buf);
262     return result;
263 }
264 
265 void qemu_opts_print_help(QemuOptsList *list)
266 {
267     QemuOptDesc *desc;
268 
269     assert(list);
270     desc = list->desc;
271     printf("Supported options:\n");
272     while (desc && desc->name) {
273         printf("%-16s %s\n", desc->name,
274                desc->help ? desc->help : "No description available");
275         desc++;
276     }
277 }
278 /* ------------------------------------------------------------------ */
279 
280 QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
281 {
282     QemuOpt *opt;
283 
284     QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
285         if (strcmp(opt->name, name) != 0)
286             continue;
287         return opt;
288     }
289     return NULL;
290 }
291 
292 static void qemu_opt_del(QemuOpt *opt)
293 {
294     QTAILQ_REMOVE(&opt->opts->head, opt, next);
295     g_free(opt->name);
296     g_free(opt->str);
297     g_free(opt);
298 }
299 
300 /* qemu_opt_set allows many settings for the same option.
301  * This function deletes all settings for an option.
302  */
303 static void qemu_opt_del_all(QemuOpts *opts, const char *name)
304 {
305     QemuOpt *opt, *next_opt;
306 
307     QTAILQ_FOREACH_SAFE(opt, &opts->head, next, next_opt) {
308         if (!strcmp(opt->name, name)) {
309             qemu_opt_del(opt);
310         }
311     }
312 }
313 
314 const char *qemu_opt_get(QemuOpts *opts, const char *name)
315 {
316     QemuOpt *opt;
317 
318     if (opts == NULL) {
319         return NULL;
320     }
321 
322     opt = qemu_opt_find(opts, name);
323     if (!opt) {
324         const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
325         if (desc && desc->def_value_str) {
326             return desc->def_value_str;
327         }
328     }
329     return opt ? opt->str : NULL;
330 }
331 
332 /* Get a known option (or its default) and remove it from the list
333  * all in one action. Return a malloced string of the option value.
334  * Result must be freed by caller with g_free().
335  */
336 char *qemu_opt_get_del(QemuOpts *opts, const char *name)
337 {
338     QemuOpt *opt;
339     const QemuOptDesc *desc;
340     char *str = NULL;
341 
342     if (opts == NULL) {
343         return NULL;
344     }
345 
346     opt = qemu_opt_find(opts, name);
347     if (!opt) {
348         desc = find_desc_by_name(opts->list->desc, name);
349         if (desc && desc->def_value_str) {
350             str = g_strdup(desc->def_value_str);
351         }
352         return str;
353     }
354     str = opt->str;
355     opt->str = NULL;
356     qemu_opt_del_all(opts, name);
357     return str;
358 }
359 
360 bool qemu_opt_has_help_opt(QemuOpts *opts)
361 {
362     QemuOpt *opt;
363 
364     QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
365         if (is_help_option(opt->name)) {
366             return true;
367         }
368     }
369     return false;
370 }
371 
372 static bool qemu_opt_get_bool_helper(QemuOpts *opts, const char *name,
373                                      bool defval, bool del)
374 {
375     QemuOpt *opt;
376     bool ret = defval;
377 
378     if (opts == NULL) {
379         return ret;
380     }
381 
382     opt = qemu_opt_find(opts, name);
383     if (opt == NULL) {
384         const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
385         if (desc && desc->def_value_str) {
386             parse_option_bool(name, desc->def_value_str, &ret, &error_abort);
387         }
388         return ret;
389     }
390     assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
391     ret = opt->value.boolean;
392     if (del) {
393         qemu_opt_del_all(opts, name);
394     }
395     return ret;
396 }
397 
398 bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
399 {
400     return qemu_opt_get_bool_helper(opts, name, defval, false);
401 }
402 
403 bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval)
404 {
405     return qemu_opt_get_bool_helper(opts, name, defval, true);
406 }
407 
408 static uint64_t qemu_opt_get_number_helper(QemuOpts *opts, const char *name,
409                                            uint64_t defval, bool del)
410 {
411     QemuOpt *opt;
412     uint64_t ret = defval;
413 
414     if (opts == NULL) {
415         return ret;
416     }
417 
418     opt = qemu_opt_find(opts, name);
419     if (opt == NULL) {
420         const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
421         if (desc && desc->def_value_str) {
422             parse_option_number(name, desc->def_value_str, &ret, &error_abort);
423         }
424         return ret;
425     }
426     assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
427     ret = opt->value.uint;
428     if (del) {
429         qemu_opt_del_all(opts, name);
430     }
431     return ret;
432 }
433 
434 uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
435 {
436     return qemu_opt_get_number_helper(opts, name, defval, false);
437 }
438 
439 uint64_t qemu_opt_get_number_del(QemuOpts *opts, const char *name,
440                                  uint64_t defval)
441 {
442     return qemu_opt_get_number_helper(opts, name, defval, true);
443 }
444 
445 static uint64_t qemu_opt_get_size_helper(QemuOpts *opts, const char *name,
446                                          uint64_t defval, bool del)
447 {
448     QemuOpt *opt;
449     uint64_t ret = defval;
450 
451     if (opts == NULL) {
452         return ret;
453     }
454 
455     opt = qemu_opt_find(opts, name);
456     if (opt == NULL) {
457         const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
458         if (desc && desc->def_value_str) {
459             parse_option_size(name, desc->def_value_str, &ret, &error_abort);
460         }
461         return ret;
462     }
463     assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
464     ret = opt->value.uint;
465     if (del) {
466         qemu_opt_del_all(opts, name);
467     }
468     return ret;
469 }
470 
471 uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
472 {
473     return qemu_opt_get_size_helper(opts, name, defval, false);
474 }
475 
476 uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
477                                uint64_t defval)
478 {
479     return qemu_opt_get_size_helper(opts, name, defval, true);
480 }
481 
482 static void qemu_opt_parse(QemuOpt *opt, Error **errp)
483 {
484     if (opt->desc == NULL)
485         return;
486 
487     switch (opt->desc->type) {
488     case QEMU_OPT_STRING:
489         /* nothing */
490         return;
491     case QEMU_OPT_BOOL:
492         parse_option_bool(opt->name, opt->str, &opt->value.boolean, errp);
493         break;
494     case QEMU_OPT_NUMBER:
495         parse_option_number(opt->name, opt->str, &opt->value.uint, errp);
496         break;
497     case QEMU_OPT_SIZE:
498         parse_option_size(opt->name, opt->str, &opt->value.uint, errp);
499         break;
500     default:
501         abort();
502     }
503 }
504 
505 static bool opts_accepts_any(const QemuOpts *opts)
506 {
507     return opts->list->desc[0].name == NULL;
508 }
509 
510 int qemu_opt_unset(QemuOpts *opts, const char *name)
511 {
512     QemuOpt *opt = qemu_opt_find(opts, name);
513 
514     assert(opts_accepts_any(opts));
515 
516     if (opt == NULL) {
517         return -1;
518     } else {
519         qemu_opt_del(opt);
520         return 0;
521     }
522 }
523 
524 static void opt_set(QemuOpts *opts, const char *name, const char *value,
525                     bool prepend, Error **errp)
526 {
527     QemuOpt *opt;
528     const QemuOptDesc *desc;
529     Error *local_err = NULL;
530 
531     desc = find_desc_by_name(opts->list->desc, name);
532     if (!desc && !opts_accepts_any(opts)) {
533         error_setg(errp, QERR_INVALID_PARAMETER, name);
534         return;
535     }
536 
537     opt = g_malloc0(sizeof(*opt));
538     opt->name = g_strdup(name);
539     opt->opts = opts;
540     if (prepend) {
541         QTAILQ_INSERT_HEAD(&opts->head, opt, next);
542     } else {
543         QTAILQ_INSERT_TAIL(&opts->head, opt, next);
544     }
545     opt->desc = desc;
546     opt->str = g_strdup(value);
547     qemu_opt_parse(opt, &local_err);
548     if (local_err) {
549         error_propagate(errp, local_err);
550         qemu_opt_del(opt);
551     }
552 }
553 
554 void qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
555                   Error **errp)
556 {
557     opt_set(opts, name, value, false, errp);
558 }
559 
560 void qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val,
561                        Error **errp)
562 {
563     QemuOpt *opt;
564     const QemuOptDesc *desc = opts->list->desc;
565 
566     opt = g_malloc0(sizeof(*opt));
567     opt->desc = find_desc_by_name(desc, name);
568     if (!opt->desc && !opts_accepts_any(opts)) {
569         error_setg(errp, QERR_INVALID_PARAMETER, name);
570         g_free(opt);
571         return;
572     }
573 
574     opt->name = g_strdup(name);
575     opt->opts = opts;
576     opt->value.boolean = !!val;
577     opt->str = g_strdup(val ? "on" : "off");
578     QTAILQ_INSERT_TAIL(&opts->head, opt, next);
579 }
580 
581 void qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val,
582                          Error **errp)
583 {
584     QemuOpt *opt;
585     const QemuOptDesc *desc = opts->list->desc;
586 
587     opt = g_malloc0(sizeof(*opt));
588     opt->desc = find_desc_by_name(desc, name);
589     if (!opt->desc && !opts_accepts_any(opts)) {
590         error_setg(errp, QERR_INVALID_PARAMETER, name);
591         g_free(opt);
592         return;
593     }
594 
595     opt->name = g_strdup(name);
596     opt->opts = opts;
597     opt->value.uint = val;
598     opt->str = g_strdup_printf("%" PRId64, val);
599     QTAILQ_INSERT_TAIL(&opts->head, opt, next);
600 }
601 
602 /**
603  * For each member of @opts, call @func(@opaque, name, value, @errp).
604  * @func() may store an Error through @errp, but must return non-zero then.
605  * When @func() returns non-zero, break the loop and return that value.
606  * Return zero when the loop completes.
607  */
608 int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
609                      Error **errp)
610 {
611     QemuOpt *opt;
612     int rc;
613 
614     QTAILQ_FOREACH(opt, &opts->head, next) {
615         rc = func(opaque, opt->name, opt->str, errp);
616         if (rc) {
617             return rc;
618         }
619         assert(!errp || !*errp);
620     }
621     return 0;
622 }
623 
624 QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
625 {
626     QemuOpts *opts;
627 
628     QTAILQ_FOREACH(opts, &list->head, next) {
629         if (!opts->id && !id) {
630             return opts;
631         }
632         if (opts->id && id && !strcmp(opts->id, id)) {
633             return opts;
634         }
635     }
636     return NULL;
637 }
638 
639 QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
640                            int fail_if_exists, Error **errp)
641 {
642     QemuOpts *opts = NULL;
643 
644     if (id) {
645         if (!id_wellformed(id)) {
646             error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id",
647                        "an identifier");
648             error_append_hint(errp, "Identifiers consist of letters, digits, "
649                               "'-', '.', '_', starting with a letter.\n");
650             return NULL;
651         }
652         opts = qemu_opts_find(list, id);
653         if (opts != NULL) {
654             if (fail_if_exists && !list->merge_lists) {
655                 error_setg(errp, "Duplicate ID '%s' for %s", id, list->name);
656                 return NULL;
657             } else {
658                 return opts;
659             }
660         }
661     } else if (list->merge_lists) {
662         opts = qemu_opts_find(list, NULL);
663         if (opts) {
664             return opts;
665         }
666     }
667     opts = g_malloc0(sizeof(*opts));
668     opts->id = g_strdup(id);
669     opts->list = list;
670     loc_save(&opts->loc);
671     QTAILQ_INIT(&opts->head);
672     QTAILQ_INSERT_TAIL(&list->head, opts, next);
673     return opts;
674 }
675 
676 void qemu_opts_reset(QemuOptsList *list)
677 {
678     QemuOpts *opts, *next_opts;
679 
680     QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) {
681         qemu_opts_del(opts);
682     }
683 }
684 
685 void qemu_opts_loc_restore(QemuOpts *opts)
686 {
687     loc_restore(&opts->loc);
688 }
689 
690 void qemu_opts_set(QemuOptsList *list, const char *id,
691                    const char *name, const char *value, Error **errp)
692 {
693     QemuOpts *opts;
694     Error *local_err = NULL;
695 
696     opts = qemu_opts_create(list, id, 1, &local_err);
697     if (local_err) {
698         error_propagate(errp, local_err);
699         return;
700     }
701     qemu_opt_set(opts, name, value, errp);
702 }
703 
704 const char *qemu_opts_id(QemuOpts *opts)
705 {
706     return opts->id;
707 }
708 
709 /* The id string will be g_free()d by qemu_opts_del */
710 void qemu_opts_set_id(QemuOpts *opts, char *id)
711 {
712     opts->id = id;
713 }
714 
715 void qemu_opts_del(QemuOpts *opts)
716 {
717     QemuOpt *opt;
718 
719     if (opts == NULL) {
720         return;
721     }
722 
723     for (;;) {
724         opt = QTAILQ_FIRST(&opts->head);
725         if (opt == NULL)
726             break;
727         qemu_opt_del(opt);
728     }
729     QTAILQ_REMOVE(&opts->list->head, opts, next);
730     g_free(opts->id);
731     g_free(opts);
732 }
733 
734 /* print value, escaping any commas in value */
735 static void escaped_print(const char *value)
736 {
737     const char *ptr;
738 
739     for (ptr = value; *ptr; ++ptr) {
740         if (*ptr == ',') {
741             putchar(',');
742         }
743         putchar(*ptr);
744     }
745 }
746 
747 void qemu_opts_print(QemuOpts *opts, const char *separator)
748 {
749     QemuOpt *opt;
750     QemuOptDesc *desc = opts->list->desc;
751     const char *sep = "";
752 
753     if (opts->id) {
754         printf("id=%s", opts->id); /* passed id_wellformed -> no commas */
755         sep = separator;
756     }
757 
758     if (desc[0].name == NULL) {
759         QTAILQ_FOREACH(opt, &opts->head, next) {
760             printf("%s%s=", sep, opt->name);
761             escaped_print(opt->str);
762             sep = separator;
763         }
764         return;
765     }
766     for (; desc && desc->name; desc++) {
767         const char *value;
768         QemuOpt *opt = qemu_opt_find(opts, desc->name);
769 
770         value = opt ? opt->str : desc->def_value_str;
771         if (!value) {
772             continue;
773         }
774         if (desc->type == QEMU_OPT_STRING) {
775             printf("%s%s=", sep, desc->name);
776             escaped_print(value);
777         } else if ((desc->type == QEMU_OPT_SIZE ||
778                     desc->type == QEMU_OPT_NUMBER) && opt) {
779             printf("%s%s=%" PRId64, sep, desc->name, opt->value.uint);
780         } else {
781             printf("%s%s=%s", sep, desc->name, value);
782         }
783         sep = separator;
784     }
785 }
786 
787 static void opts_do_parse(QemuOpts *opts, const char *params,
788                           const char *firstname, bool prepend, Error **errp)
789 {
790     char option[128], value[1024];
791     const char *p,*pe,*pc;
792     Error *local_err = NULL;
793 
794     for (p = params; *p != '\0'; p++) {
795         pe = strchr(p, '=');
796         pc = strchr(p, ',');
797         if (!pe || (pc && pc < pe)) {
798             /* found "foo,more" */
799             if (p == params && firstname) {
800                 /* implicitly named first option */
801                 pstrcpy(option, sizeof(option), firstname);
802                 p = get_opt_value(value, sizeof(value), p);
803             } else {
804                 /* option without value, probably a flag */
805                 p = get_opt_name(option, sizeof(option), p, ',');
806                 if (strncmp(option, "no", 2) == 0) {
807                     memmove(option, option+2, strlen(option+2)+1);
808                     pstrcpy(value, sizeof(value), "off");
809                 } else {
810                     pstrcpy(value, sizeof(value), "on");
811                 }
812             }
813         } else {
814             /* found "foo=bar,more" */
815             p = get_opt_name(option, sizeof(option), p, '=');
816             if (*p != '=') {
817                 break;
818             }
819             p++;
820             p = get_opt_value(value, sizeof(value), p);
821         }
822         if (strcmp(option, "id") != 0) {
823             /* store and parse */
824             opt_set(opts, option, value, prepend, &local_err);
825             if (local_err) {
826                 error_propagate(errp, local_err);
827                 return;
828             }
829         }
830         if (*p != ',') {
831             break;
832         }
833     }
834 }
835 
836 /**
837  * Store options parsed from @params into @opts.
838  * If @firstname is non-null, the first key=value in @params may omit
839  * key=, and is treated as if key was @firstname.
840  * On error, store an error object through @errp if non-null.
841  */
842 void qemu_opts_do_parse(QemuOpts *opts, const char *params,
843                        const char *firstname, Error **errp)
844 {
845     opts_do_parse(opts, params, firstname, false, errp);
846 }
847 
848 static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
849                             bool permit_abbrev, bool defaults, Error **errp)
850 {
851     const char *firstname;
852     char value[1024], *id = NULL;
853     const char *p;
854     QemuOpts *opts;
855     Error *local_err = NULL;
856 
857     assert(!permit_abbrev || list->implied_opt_name);
858     firstname = permit_abbrev ? list->implied_opt_name : NULL;
859 
860     if (strncmp(params, "id=", 3) == 0) {
861         get_opt_value(value, sizeof(value), params+3);
862         id = value;
863     } else if ((p = strstr(params, ",id=")) != NULL) {
864         get_opt_value(value, sizeof(value), p+4);
865         id = value;
866     }
867 
868     /*
869      * This code doesn't work for defaults && !list->merge_lists: when
870      * params has no id=, and list has an element with !opts->id, it
871      * appends a new element instead of returning the existing opts.
872      * However, we got no use for this case.  Guard against possible
873      * (if unlikely) future misuse:
874      */
875     assert(!defaults || list->merge_lists);
876     opts = qemu_opts_create(list, id, !defaults, &local_err);
877     if (opts == NULL) {
878         error_propagate(errp, local_err);
879         return NULL;
880     }
881 
882     opts_do_parse(opts, params, firstname, defaults, &local_err);
883     if (local_err) {
884         error_propagate(errp, local_err);
885         qemu_opts_del(opts);
886         return NULL;
887     }
888 
889     return opts;
890 }
891 
892 /**
893  * Create a QemuOpts in @list and with options parsed from @params.
894  * If @permit_abbrev, the first key=value in @params may omit key=,
895  * and is treated as if key was @list->implied_opt_name.
896  * On error, store an error object through @errp if non-null.
897  * Return the new QemuOpts on success, null pointer on error.
898  */
899 QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
900                           bool permit_abbrev, Error **errp)
901 {
902     return opts_parse(list, params, permit_abbrev, false, errp);
903 }
904 
905 /**
906  * Create a QemuOpts in @list and with options parsed from @params.
907  * If @permit_abbrev, the first key=value in @params may omit key=,
908  * and is treated as if key was @list->implied_opt_name.
909  * Report errors with error_report_err().  This is inappropriate in
910  * QMP context.  Do not use this function there!
911  * Return the new QemuOpts on success, null pointer on error.
912  */
913 QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
914                                   bool permit_abbrev)
915 {
916     Error *err = NULL;
917     QemuOpts *opts;
918 
919     opts = opts_parse(list, params, permit_abbrev, false, &err);
920     if (err) {
921         error_report_err(err);
922     }
923     return opts;
924 }
925 
926 void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
927                             int permit_abbrev)
928 {
929     QemuOpts *opts;
930 
931     opts = opts_parse(list, params, permit_abbrev, true, NULL);
932     assert(opts);
933 }
934 
935 typedef struct OptsFromQDictState {
936     QemuOpts *opts;
937     Error **errp;
938 } OptsFromQDictState;
939 
940 static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
941 {
942     OptsFromQDictState *state = opaque;
943     char buf[32];
944     const char *value;
945     int n;
946 
947     if (!strcmp(key, "id") || *state->errp) {
948         return;
949     }
950 
951     switch (qobject_type(obj)) {
952     case QTYPE_QSTRING:
953         value = qstring_get_str(qobject_to_qstring(obj));
954         break;
955     case QTYPE_QINT:
956         n = snprintf(buf, sizeof(buf), "%" PRId64,
957                      qint_get_int(qobject_to_qint(obj)));
958         assert(n < sizeof(buf));
959         value = buf;
960         break;
961     case QTYPE_QFLOAT:
962         n = snprintf(buf, sizeof(buf), "%.17g",
963                      qfloat_get_double(qobject_to_qfloat(obj)));
964         assert(n < sizeof(buf));
965         value = buf;
966         break;
967     case QTYPE_QBOOL:
968         pstrcpy(buf, sizeof(buf),
969                 qbool_get_bool(qobject_to_qbool(obj)) ? "on" : "off");
970         value = buf;
971         break;
972     default:
973         return;
974     }
975 
976     qemu_opt_set(state->opts, key, value, state->errp);
977 }
978 
979 /*
980  * Create QemuOpts from a QDict.
981  * Use value of key "id" as ID if it exists and is a QString.
982  * Only QStrings, QInts, QFloats and QBools are copied.  Entries with
983  * other types are silently ignored.
984  */
985 QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
986                                Error **errp)
987 {
988     OptsFromQDictState state;
989     Error *local_err = NULL;
990     QemuOpts *opts;
991 
992     opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1,
993                             &local_err);
994     if (local_err) {
995         error_propagate(errp, local_err);
996         return NULL;
997     }
998 
999     assert(opts != NULL);
1000 
1001     state.errp = &local_err;
1002     state.opts = opts;
1003     qdict_iter(qdict, qemu_opts_from_qdict_1, &state);
1004     if (local_err) {
1005         error_propagate(errp, local_err);
1006         qemu_opts_del(opts);
1007         return NULL;
1008     }
1009 
1010     return opts;
1011 }
1012 
1013 /*
1014  * Adds all QDict entries to the QemuOpts that can be added and removes them
1015  * from the QDict. When this function returns, the QDict contains only those
1016  * entries that couldn't be added to the QemuOpts.
1017  */
1018 void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp)
1019 {
1020     const QDictEntry *entry, *next;
1021 
1022     entry = qdict_first(qdict);
1023 
1024     while (entry != NULL) {
1025         Error *local_err = NULL;
1026         OptsFromQDictState state = {
1027             .errp = &local_err,
1028             .opts = opts,
1029         };
1030 
1031         next = qdict_next(qdict, entry);
1032 
1033         if (find_desc_by_name(opts->list->desc, entry->key)) {
1034             qemu_opts_from_qdict_1(entry->key, entry->value, &state);
1035             if (local_err) {
1036                 error_propagate(errp, local_err);
1037                 return;
1038             } else {
1039                 qdict_del(qdict, entry->key);
1040             }
1041         }
1042 
1043         entry = next;
1044     }
1045 }
1046 
1047 /*
1048  * Convert from QemuOpts to QDict.
1049  * The QDict values are of type QString.
1050  * TODO We'll want to use types appropriate for opt->desc->type, but
1051  * this is enough for now.
1052  */
1053 QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
1054 {
1055     QemuOpt *opt;
1056     QObject *val;
1057 
1058     if (!qdict) {
1059         qdict = qdict_new();
1060     }
1061     if (opts->id) {
1062         qdict_put(qdict, "id", qstring_from_str(opts->id));
1063     }
1064     QTAILQ_FOREACH(opt, &opts->head, next) {
1065         val = QOBJECT(qstring_from_str(opt->str));
1066         qdict_put_obj(qdict, opt->name, val);
1067     }
1068     return qdict;
1069 }
1070 
1071 /* Validate parsed opts against descriptions where no
1072  * descriptions were provided in the QemuOptsList.
1073  */
1074 void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
1075 {
1076     QemuOpt *opt;
1077     Error *local_err = NULL;
1078 
1079     assert(opts_accepts_any(opts));
1080 
1081     QTAILQ_FOREACH(opt, &opts->head, next) {
1082         opt->desc = find_desc_by_name(desc, opt->name);
1083         if (!opt->desc) {
1084             error_setg(errp, QERR_INVALID_PARAMETER, opt->name);
1085             return;
1086         }
1087 
1088         qemu_opt_parse(opt, &local_err);
1089         if (local_err) {
1090             error_propagate(errp, local_err);
1091             return;
1092         }
1093     }
1094 }
1095 
1096 /**
1097  * For each member of @list, call @func(@opaque, member, @errp).
1098  * Call it with the current location temporarily set to the member's.
1099  * @func() may store an Error through @errp, but must return non-zero then.
1100  * When @func() returns non-zero, break the loop and return that value.
1101  * Return zero when the loop completes.
1102  */
1103 int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func,
1104                       void *opaque, Error **errp)
1105 {
1106     Location loc;
1107     QemuOpts *opts;
1108     int rc;
1109 
1110     loc_push_none(&loc);
1111     QTAILQ_FOREACH(opts, &list->head, next) {
1112         loc_restore(&opts->loc);
1113         rc = func(opaque, opts, errp);
1114         if (rc) {
1115             return rc;
1116         }
1117         assert(!errp || !*errp);
1118     }
1119     loc_pop(&loc);
1120     return 0;
1121 }
1122 
1123 static size_t count_opts_list(QemuOptsList *list)
1124 {
1125     QemuOptDesc *desc = NULL;
1126     size_t num_opts = 0;
1127 
1128     if (!list) {
1129         return 0;
1130     }
1131 
1132     desc = list->desc;
1133     while (desc && desc->name) {
1134         num_opts++;
1135         desc++;
1136     }
1137 
1138     return num_opts;
1139 }
1140 
1141 void qemu_opts_free(QemuOptsList *list)
1142 {
1143     g_free(list);
1144 }
1145 
1146 /* Realloc dst option list and append options from an option list (list)
1147  * to it. dst could be NULL or a malloced list.
1148  * The lifetime of dst must be shorter than the input list because the
1149  * QemuOptDesc->name, ->help, and ->def_value_str strings are shared.
1150  */
1151 QemuOptsList *qemu_opts_append(QemuOptsList *dst,
1152                                QemuOptsList *list)
1153 {
1154     size_t num_opts, num_dst_opts;
1155     QemuOptDesc *desc;
1156     bool need_init = false;
1157     bool need_head_update;
1158 
1159     if (!list) {
1160         return dst;
1161     }
1162 
1163     /* If dst is NULL, after realloc, some area of dst should be initialized
1164      * before adding options to it.
1165      */
1166     if (!dst) {
1167         need_init = true;
1168         need_head_update = true;
1169     } else {
1170         /* Moreover, even if dst is not NULL, the realloc may move it to a
1171          * different address in which case we may get a stale tail pointer
1172          * in dst->head. */
1173         need_head_update = QTAILQ_EMPTY(&dst->head);
1174     }
1175 
1176     num_opts = count_opts_list(dst);
1177     num_dst_opts = num_opts;
1178     num_opts += count_opts_list(list);
1179     dst = g_realloc(dst, sizeof(QemuOptsList) +
1180                     (num_opts + 1) * sizeof(QemuOptDesc));
1181     if (need_init) {
1182         dst->name = NULL;
1183         dst->implied_opt_name = NULL;
1184         dst->merge_lists = false;
1185     }
1186     if (need_head_update) {
1187         QTAILQ_INIT(&dst->head);
1188     }
1189     dst->desc[num_dst_opts].name = NULL;
1190 
1191     /* append list->desc to dst->desc */
1192     if (list) {
1193         desc = list->desc;
1194         while (desc && desc->name) {
1195             if (find_desc_by_name(dst->desc, desc->name) == NULL) {
1196                 dst->desc[num_dst_opts++] = *desc;
1197                 dst->desc[num_dst_opts].name = NULL;
1198             }
1199             desc++;
1200         }
1201     }
1202 
1203     return dst;
1204 }
1205