root / qemu-option.c @ 5f8ae8e2
History | View | Annotate | Download (28 kB)
1 | d3f24367 | Kevin Wolf | /*
|
---|---|---|---|
2 | d3f24367 | Kevin Wolf | * Commandline option parsing functions
|
3 | d3f24367 | Kevin Wolf | *
|
4 | d3f24367 | Kevin Wolf | * Copyright (c) 2003-2008 Fabrice Bellard
|
5 | d3f24367 | Kevin Wolf | * Copyright (c) 2009 Kevin Wolf <kwolf@redhat.com>
|
6 | d3f24367 | Kevin Wolf | *
|
7 | d3f24367 | Kevin Wolf | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 | d3f24367 | Kevin Wolf | * of this software and associated documentation files (the "Software"), to deal
|
9 | d3f24367 | Kevin Wolf | * in the Software without restriction, including without limitation the rights
|
10 | d3f24367 | Kevin Wolf | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 | d3f24367 | Kevin Wolf | * copies of the Software, and to permit persons to whom the Software is
|
12 | d3f24367 | Kevin Wolf | * furnished to do so, subject to the following conditions:
|
13 | d3f24367 | Kevin Wolf | *
|
14 | d3f24367 | Kevin Wolf | * The above copyright notice and this permission notice shall be included in
|
15 | d3f24367 | Kevin Wolf | * all copies or substantial portions of the Software.
|
16 | d3f24367 | Kevin Wolf | *
|
17 | d3f24367 | Kevin Wolf | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 | d3f24367 | Kevin Wolf | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 | d3f24367 | Kevin Wolf | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
20 | d3f24367 | Kevin Wolf | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 | d3f24367 | Kevin Wolf | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 | d3f24367 | Kevin Wolf | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 | d3f24367 | Kevin Wolf | * THE SOFTWARE.
|
24 | d3f24367 | Kevin Wolf | */
|
25 | d3f24367 | Kevin Wolf | |
26 | d3f24367 | Kevin Wolf | #include <stdio.h> |
27 | d3f24367 | Kevin Wolf | #include <string.h> |
28 | d3f24367 | Kevin Wolf | |
29 | d3f24367 | Kevin Wolf | #include "qemu-common.h" |
30 | 827b0813 | Markus Armbruster | #include "qemu-error.h" |
31 | 01e7f188 | Markus Armbruster | #include "qemu-objects.h" |
32 | 8be7e7e4 | Luiz Capitulino | #include "error.h" |
33 | 975b63a4 | Markus Armbruster | #include "qerror.h" |
34 | fdb17976 | Laszlo Ersek | #include "qemu-option-internal.h" |
35 | d3f24367 | Kevin Wolf | |
36 | d3f24367 | Kevin Wolf | /*
|
37 | d3f24367 | Kevin Wolf | * Extracts the name of an option from the parameter string (p points at the
|
38 | d3f24367 | Kevin Wolf | * first byte of the option name)
|
39 | d3f24367 | Kevin Wolf | *
|
40 | d3f24367 | Kevin Wolf | * The option name is delimited by delim (usually , or =) or the string end
|
41 | d3f24367 | Kevin Wolf | * and is copied into buf. If the option name is longer than buf_size, it is
|
42 | d3f24367 | Kevin Wolf | * truncated. buf is always zero terminated.
|
43 | d3f24367 | Kevin Wolf | *
|
44 | d3f24367 | Kevin Wolf | * The return value is the position of the delimiter/zero byte after the option
|
45 | d3f24367 | Kevin Wolf | * name in p.
|
46 | d3f24367 | Kevin Wolf | */
|
47 | d3f24367 | Kevin Wolf | const char *get_opt_name(char *buf, int buf_size, const char *p, char delim) |
48 | d3f24367 | Kevin Wolf | { |
49 | d3f24367 | Kevin Wolf | char *q;
|
50 | d3f24367 | Kevin Wolf | |
51 | d3f24367 | Kevin Wolf | q = buf; |
52 | d3f24367 | Kevin Wolf | while (*p != '\0' && *p != delim) { |
53 | d3f24367 | Kevin Wolf | if (q && (q - buf) < buf_size - 1) |
54 | d3f24367 | Kevin Wolf | *q++ = *p; |
55 | d3f24367 | Kevin Wolf | p++; |
56 | d3f24367 | Kevin Wolf | } |
57 | d3f24367 | Kevin Wolf | if (q)
|
58 | d3f24367 | Kevin Wolf | *q = '\0';
|
59 | d3f24367 | Kevin Wolf | |
60 | d3f24367 | Kevin Wolf | return p;
|
61 | d3f24367 | Kevin Wolf | } |
62 | d3f24367 | Kevin Wolf | |
63 | d3f24367 | Kevin Wolf | /*
|
64 | d3f24367 | Kevin Wolf | * Extracts the value of an option from the parameter string p (p points at the
|
65 | d3f24367 | Kevin Wolf | * first byte of the option value)
|
66 | d3f24367 | Kevin Wolf | *
|
67 | d3f24367 | Kevin Wolf | * This function is comparable to get_opt_name with the difference that the
|
68 | d3f24367 | Kevin Wolf | * delimiter is fixed to be comma which starts a new option. To specify an
|
69 | d3f24367 | Kevin Wolf | * option value that contains commas, double each comma.
|
70 | d3f24367 | Kevin Wolf | */
|
71 | d3f24367 | Kevin Wolf | const char *get_opt_value(char *buf, int buf_size, const char *p) |
72 | d3f24367 | Kevin Wolf | { |
73 | d3f24367 | Kevin Wolf | char *q;
|
74 | d3f24367 | Kevin Wolf | |
75 | d3f24367 | Kevin Wolf | q = buf; |
76 | d3f24367 | Kevin Wolf | while (*p != '\0') { |
77 | d3f24367 | Kevin Wolf | if (*p == ',') { |
78 | d3f24367 | Kevin Wolf | if (*(p + 1) != ',') |
79 | d3f24367 | Kevin Wolf | break;
|
80 | d3f24367 | Kevin Wolf | p++; |
81 | d3f24367 | Kevin Wolf | } |
82 | d3f24367 | Kevin Wolf | if (q && (q - buf) < buf_size - 1) |
83 | d3f24367 | Kevin Wolf | *q++ = *p; |
84 | d3f24367 | Kevin Wolf | p++; |
85 | d3f24367 | Kevin Wolf | } |
86 | d3f24367 | Kevin Wolf | if (q)
|
87 | d3f24367 | Kevin Wolf | *q = '\0';
|
88 | d3f24367 | Kevin Wolf | |
89 | d3f24367 | Kevin Wolf | return p;
|
90 | d3f24367 | Kevin Wolf | } |
91 | d3f24367 | Kevin Wolf | |
92 | 62c5802e | Gerd Hoffmann | int get_next_param_value(char *buf, int buf_size, |
93 | 62c5802e | Gerd Hoffmann | const char *tag, const char **pstr) |
94 | 62c5802e | Gerd Hoffmann | { |
95 | 62c5802e | Gerd Hoffmann | const char *p; |
96 | 62c5802e | Gerd Hoffmann | char option[128]; |
97 | 62c5802e | Gerd Hoffmann | |
98 | 62c5802e | Gerd Hoffmann | p = *pstr; |
99 | 62c5802e | Gerd Hoffmann | for(;;) {
|
100 | 62c5802e | Gerd Hoffmann | p = get_opt_name(option, sizeof(option), p, '='); |
101 | 62c5802e | Gerd Hoffmann | if (*p != '=') |
102 | 62c5802e | Gerd Hoffmann | break;
|
103 | 62c5802e | Gerd Hoffmann | p++; |
104 | 62c5802e | Gerd Hoffmann | if (!strcmp(tag, option)) {
|
105 | 62c5802e | Gerd Hoffmann | *pstr = get_opt_value(buf, buf_size, p); |
106 | 62c5802e | Gerd Hoffmann | if (**pstr == ',') { |
107 | 62c5802e | Gerd Hoffmann | (*pstr)++; |
108 | 62c5802e | Gerd Hoffmann | } |
109 | 62c5802e | Gerd Hoffmann | return strlen(buf);
|
110 | 62c5802e | Gerd Hoffmann | } else {
|
111 | 62c5802e | Gerd Hoffmann | p = get_opt_value(NULL, 0, p); |
112 | 62c5802e | Gerd Hoffmann | } |
113 | 62c5802e | Gerd Hoffmann | if (*p != ',') |
114 | 62c5802e | Gerd Hoffmann | break;
|
115 | 62c5802e | Gerd Hoffmann | p++; |
116 | 62c5802e | Gerd Hoffmann | } |
117 | 62c5802e | Gerd Hoffmann | return 0; |
118 | 62c5802e | Gerd Hoffmann | } |
119 | 62c5802e | Gerd Hoffmann | |
120 | 62c5802e | Gerd Hoffmann | int get_param_value(char *buf, int buf_size, |
121 | 62c5802e | Gerd Hoffmann | const char *tag, const char *str) |
122 | 62c5802e | Gerd Hoffmann | { |
123 | 62c5802e | Gerd Hoffmann | return get_next_param_value(buf, buf_size, tag, &str);
|
124 | 62c5802e | Gerd Hoffmann | } |
125 | 62c5802e | Gerd Hoffmann | |
126 | 62c5802e | Gerd Hoffmann | int check_params(char *buf, int buf_size, |
127 | 62c5802e | Gerd Hoffmann | const char * const *params, const char *str) |
128 | 62c5802e | Gerd Hoffmann | { |
129 | 62c5802e | Gerd Hoffmann | const char *p; |
130 | 62c5802e | Gerd Hoffmann | int i;
|
131 | 62c5802e | Gerd Hoffmann | |
132 | 62c5802e | Gerd Hoffmann | p = str; |
133 | 62c5802e | Gerd Hoffmann | while (*p != '\0') { |
134 | 62c5802e | Gerd Hoffmann | p = get_opt_name(buf, buf_size, p, '=');
|
135 | 62c5802e | Gerd Hoffmann | if (*p != '=') { |
136 | 62c5802e | Gerd Hoffmann | return -1; |
137 | 62c5802e | Gerd Hoffmann | } |
138 | 62c5802e | Gerd Hoffmann | p++; |
139 | 62c5802e | Gerd Hoffmann | for (i = 0; params[i] != NULL; i++) { |
140 | 62c5802e | Gerd Hoffmann | if (!strcmp(params[i], buf)) {
|
141 | 62c5802e | Gerd Hoffmann | break;
|
142 | 62c5802e | Gerd Hoffmann | } |
143 | 62c5802e | Gerd Hoffmann | } |
144 | 62c5802e | Gerd Hoffmann | if (params[i] == NULL) { |
145 | 62c5802e | Gerd Hoffmann | return -1; |
146 | 62c5802e | Gerd Hoffmann | } |
147 | 62c5802e | Gerd Hoffmann | p = get_opt_value(NULL, 0, p); |
148 | 62c5802e | Gerd Hoffmann | if (*p != ',') { |
149 | 62c5802e | Gerd Hoffmann | break;
|
150 | 62c5802e | Gerd Hoffmann | } |
151 | 62c5802e | Gerd Hoffmann | p++; |
152 | 62c5802e | Gerd Hoffmann | } |
153 | 62c5802e | Gerd Hoffmann | return 0; |
154 | 62c5802e | Gerd Hoffmann | } |
155 | 62c5802e | Gerd Hoffmann | |
156 | d3f24367 | Kevin Wolf | /*
|
157 | d3f24367 | Kevin Wolf | * Searches an option list for an option with the given name
|
158 | d3f24367 | Kevin Wolf | */
|
159 | d3f24367 | Kevin Wolf | QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list, |
160 | d3f24367 | Kevin Wolf | const char *name) |
161 | d3f24367 | Kevin Wolf | { |
162 | d3f24367 | Kevin Wolf | while (list && list->name) {
|
163 | d3f24367 | Kevin Wolf | if (!strcmp(list->name, name)) {
|
164 | d3f24367 | Kevin Wolf | return list;
|
165 | d3f24367 | Kevin Wolf | } |
166 | d3f24367 | Kevin Wolf | list++; |
167 | d3f24367 | Kevin Wolf | } |
168 | d3f24367 | Kevin Wolf | |
169 | d3f24367 | Kevin Wolf | return NULL; |
170 | d3f24367 | Kevin Wolf | } |
171 | d3f24367 | Kevin Wolf | |
172 | cf62adfa | Luiz Capitulino | static void parse_option_bool(const char *name, const char *value, bool *ret, |
173 | cf62adfa | Luiz Capitulino | Error **errp) |
174 | 67b1355b | Gerd Hoffmann | { |
175 | 67b1355b | Gerd Hoffmann | if (value != NULL) { |
176 | 67b1355b | Gerd Hoffmann | if (!strcmp(value, "on")) { |
177 | 67b1355b | Gerd Hoffmann | *ret = 1;
|
178 | 67b1355b | Gerd Hoffmann | } else if (!strcmp(value, "off")) { |
179 | 67b1355b | Gerd Hoffmann | *ret = 0;
|
180 | 67b1355b | Gerd Hoffmann | } else {
|
181 | cf62adfa | Luiz Capitulino | error_set(errp,QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'");
|
182 | 67b1355b | Gerd Hoffmann | } |
183 | 67b1355b | Gerd Hoffmann | } else {
|
184 | 67b1355b | Gerd Hoffmann | *ret = 1;
|
185 | 67b1355b | Gerd Hoffmann | } |
186 | 67b1355b | Gerd Hoffmann | } |
187 | 67b1355b | Gerd Hoffmann | |
188 | 2f39df5b | Luiz Capitulino | static void parse_option_number(const char *name, const char *value, |
189 | 2f39df5b | Luiz Capitulino | uint64_t *ret, Error **errp) |
190 | e27c88fe | Gerd Hoffmann | { |
191 | e27c88fe | Gerd Hoffmann | char *postfix;
|
192 | e27c88fe | Gerd Hoffmann | uint64_t number; |
193 | e27c88fe | Gerd Hoffmann | |
194 | e27c88fe | Gerd Hoffmann | if (value != NULL) { |
195 | e27c88fe | Gerd Hoffmann | number = strtoull(value, &postfix, 0);
|
196 | e27c88fe | Gerd Hoffmann | if (*postfix != '\0') { |
197 | 2f39df5b | Luiz Capitulino | error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
|
198 | 2f39df5b | Luiz Capitulino | return;
|
199 | e27c88fe | Gerd Hoffmann | } |
200 | 21c9f4cd | Gerd Hoffmann | *ret = number; |
201 | e27c88fe | Gerd Hoffmann | } else {
|
202 | 2f39df5b | Luiz Capitulino | error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
|
203 | e27c88fe | Gerd Hoffmann | } |
204 | e27c88fe | Gerd Hoffmann | } |
205 | e27c88fe | Gerd Hoffmann | |
206 | ec7b2ccb | Luiz Capitulino | static void parse_option_size(const char *name, const char *value, |
207 | ec7b2ccb | Luiz Capitulino | uint64_t *ret, Error **errp) |
208 | 7695019b | Gerd Hoffmann | { |
209 | 7695019b | Gerd Hoffmann | char *postfix;
|
210 | 7695019b | Gerd Hoffmann | double sizef;
|
211 | 7695019b | Gerd Hoffmann | |
212 | 7695019b | Gerd Hoffmann | if (value != NULL) { |
213 | 7695019b | Gerd Hoffmann | sizef = strtod(value, &postfix); |
214 | 7695019b | Gerd Hoffmann | switch (*postfix) {
|
215 | 7695019b | Gerd Hoffmann | case 'T': |
216 | 7695019b | Gerd Hoffmann | sizef *= 1024;
|
217 | 0b0404bf | Stefan Weil | /* fall through */
|
218 | 7695019b | Gerd Hoffmann | case 'G': |
219 | 7695019b | Gerd Hoffmann | sizef *= 1024;
|
220 | 0b0404bf | Stefan Weil | /* fall through */
|
221 | 7695019b | Gerd Hoffmann | case 'M': |
222 | 7695019b | Gerd Hoffmann | sizef *= 1024;
|
223 | 0b0404bf | Stefan Weil | /* fall through */
|
224 | 7695019b | Gerd Hoffmann | case 'K': |
225 | 7695019b | Gerd Hoffmann | case 'k': |
226 | 7695019b | Gerd Hoffmann | sizef *= 1024;
|
227 | 0b0404bf | Stefan Weil | /* fall through */
|
228 | 7695019b | Gerd Hoffmann | case 'b': |
229 | 7695019b | Gerd Hoffmann | case '\0': |
230 | 7695019b | Gerd Hoffmann | *ret = (uint64_t) sizef; |
231 | 7695019b | Gerd Hoffmann | break;
|
232 | 7695019b | Gerd Hoffmann | default:
|
233 | ec7b2ccb | Luiz Capitulino | error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
|
234 | c64f27d4 | Markus Armbruster | error_printf_unless_qmp("You may use k, M, G or T suffixes for "
|
235 | 7695019b | Gerd Hoffmann | "kilobytes, megabytes, gigabytes and terabytes.\n");
|
236 | ec7b2ccb | Luiz Capitulino | return;
|
237 | 7695019b | Gerd Hoffmann | } |
238 | 7695019b | Gerd Hoffmann | } else {
|
239 | ec7b2ccb | Luiz Capitulino | error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
|
240 | 7695019b | Gerd Hoffmann | } |
241 | 7695019b | Gerd Hoffmann | } |
242 | 7695019b | Gerd Hoffmann | |
243 | d3f24367 | Kevin Wolf | /*
|
244 | d3f24367 | Kevin Wolf | * Sets the value of a parameter in a given option list. The parsing of the
|
245 | d3f24367 | Kevin Wolf | * value depends on the type of option:
|
246 | d3f24367 | Kevin Wolf | *
|
247 | d3f24367 | Kevin Wolf | * OPT_FLAG (uses value.n):
|
248 | d3f24367 | Kevin Wolf | * If no value is given, the flag is set to 1.
|
249 | d3f24367 | Kevin Wolf | * Otherwise the value must be "on" (set to 1) or "off" (set to 0)
|
250 | d3f24367 | Kevin Wolf | *
|
251 | d3f24367 | Kevin Wolf | * OPT_STRING (uses value.s):
|
252 | d3f24367 | Kevin Wolf | * value is strdup()ed and assigned as option value
|
253 | d3f24367 | Kevin Wolf | *
|
254 | d3f24367 | Kevin Wolf | * OPT_SIZE (uses value.n):
|
255 | d3f24367 | Kevin Wolf | * The value is converted to an integer. Suffixes for kilobytes etc. are
|
256 | d3f24367 | Kevin Wolf | * allowed (powers of 1024).
|
257 | d3f24367 | Kevin Wolf | *
|
258 | d3f24367 | Kevin Wolf | * Returns 0 on succes, -1 in error cases
|
259 | d3f24367 | Kevin Wolf | */
|
260 | d3f24367 | Kevin Wolf | int set_option_parameter(QEMUOptionParameter *list, const char *name, |
261 | d3f24367 | Kevin Wolf | const char *value) |
262 | d3f24367 | Kevin Wolf | { |
263 | f02b77c9 | M. Mohan Kumar | bool flag;
|
264 | cf62adfa | Luiz Capitulino | Error *local_err = NULL;
|
265 | 67b1355b | Gerd Hoffmann | |
266 | d3f24367 | Kevin Wolf | // Find a matching parameter
|
267 | d3f24367 | Kevin Wolf | list = get_option_parameter(list, name); |
268 | d3f24367 | Kevin Wolf | if (list == NULL) { |
269 | d3f24367 | Kevin Wolf | fprintf(stderr, "Unknown option '%s'\n", name);
|
270 | d3f24367 | Kevin Wolf | return -1; |
271 | d3f24367 | Kevin Wolf | } |
272 | d3f24367 | Kevin Wolf | |
273 | d3f24367 | Kevin Wolf | // Process parameter
|
274 | d3f24367 | Kevin Wolf | switch (list->type) {
|
275 | d3f24367 | Kevin Wolf | case OPT_FLAG:
|
276 | cf62adfa | Luiz Capitulino | parse_option_bool(name, value, &flag, &local_err); |
277 | cf62adfa | Luiz Capitulino | if (!error_is_set(&local_err)) {
|
278 | cf62adfa | Luiz Capitulino | list->value.n = flag; |
279 | cf62adfa | Luiz Capitulino | } |
280 | d3f24367 | Kevin Wolf | break;
|
281 | d3f24367 | Kevin Wolf | |
282 | d3f24367 | Kevin Wolf | case OPT_STRING:
|
283 | d3f24367 | Kevin Wolf | if (value != NULL) { |
284 | 7267c094 | Anthony Liguori | list->value.s = g_strdup(value); |
285 | d3f24367 | Kevin Wolf | } else {
|
286 | d3f24367 | Kevin Wolf | fprintf(stderr, "Option '%s' needs a parameter\n", name);
|
287 | d3f24367 | Kevin Wolf | return -1; |
288 | d3f24367 | Kevin Wolf | } |
289 | d3f24367 | Kevin Wolf | break;
|
290 | d3f24367 | Kevin Wolf | |
291 | d3f24367 | Kevin Wolf | case OPT_SIZE:
|
292 | ec7b2ccb | Luiz Capitulino | parse_option_size(name, value, &list->value.n, &local_err); |
293 | d3f24367 | Kevin Wolf | break;
|
294 | 7695019b | Gerd Hoffmann | |
295 | d3f24367 | Kevin Wolf | default:
|
296 | d3f24367 | Kevin Wolf | fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
|
297 | d3f24367 | Kevin Wolf | return -1; |
298 | d3f24367 | Kevin Wolf | } |
299 | d3f24367 | Kevin Wolf | |
300 | cf62adfa | Luiz Capitulino | if (error_is_set(&local_err)) {
|
301 | cf62adfa | Luiz Capitulino | qerror_report_err(local_err); |
302 | cf62adfa | Luiz Capitulino | error_free(local_err); |
303 | cf62adfa | Luiz Capitulino | return -1; |
304 | cf62adfa | Luiz Capitulino | } |
305 | cf62adfa | Luiz Capitulino | |
306 | d3f24367 | Kevin Wolf | return 0; |
307 | d3f24367 | Kevin Wolf | } |
308 | d3f24367 | Kevin Wolf | |
309 | d3f24367 | Kevin Wolf | /*
|
310 | d3f24367 | Kevin Wolf | * Sets the given parameter to an integer instead of a string.
|
311 | d3f24367 | Kevin Wolf | * This function cannot be used to set string options.
|
312 | d3f24367 | Kevin Wolf | *
|
313 | d3f24367 | Kevin Wolf | * Returns 0 on success, -1 in error cases
|
314 | d3f24367 | Kevin Wolf | */
|
315 | d3f24367 | Kevin Wolf | int set_option_parameter_int(QEMUOptionParameter *list, const char *name, |
316 | d3f24367 | Kevin Wolf | uint64_t value) |
317 | d3f24367 | Kevin Wolf | { |
318 | d3f24367 | Kevin Wolf | // Find a matching parameter
|
319 | d3f24367 | Kevin Wolf | list = get_option_parameter(list, name); |
320 | d3f24367 | Kevin Wolf | if (list == NULL) { |
321 | d3f24367 | Kevin Wolf | fprintf(stderr, "Unknown option '%s'\n", name);
|
322 | d3f24367 | Kevin Wolf | return -1; |
323 | d3f24367 | Kevin Wolf | } |
324 | d3f24367 | Kevin Wolf | |
325 | d3f24367 | Kevin Wolf | // Process parameter
|
326 | d3f24367 | Kevin Wolf | switch (list->type) {
|
327 | d3f24367 | Kevin Wolf | case OPT_FLAG:
|
328 | d3f24367 | Kevin Wolf | case OPT_NUMBER:
|
329 | d3f24367 | Kevin Wolf | case OPT_SIZE:
|
330 | d3f24367 | Kevin Wolf | list->value.n = value; |
331 | d3f24367 | Kevin Wolf | break;
|
332 | d3f24367 | Kevin Wolf | |
333 | d3f24367 | Kevin Wolf | default:
|
334 | d3f24367 | Kevin Wolf | return -1; |
335 | d3f24367 | Kevin Wolf | } |
336 | d3f24367 | Kevin Wolf | |
337 | d3f24367 | Kevin Wolf | return 0; |
338 | d3f24367 | Kevin Wolf | } |
339 | d3f24367 | Kevin Wolf | |
340 | d3f24367 | Kevin Wolf | /*
|
341 | d3f24367 | Kevin Wolf | * Frees a option list. If it contains strings, the strings are freed as well.
|
342 | d3f24367 | Kevin Wolf | */
|
343 | d3f24367 | Kevin Wolf | void free_option_parameters(QEMUOptionParameter *list)
|
344 | d3f24367 | Kevin Wolf | { |
345 | d3f24367 | Kevin Wolf | QEMUOptionParameter *cur = list; |
346 | d3f24367 | Kevin Wolf | |
347 | d3f24367 | Kevin Wolf | while (cur && cur->name) {
|
348 | d3f24367 | Kevin Wolf | if (cur->type == OPT_STRING) {
|
349 | 7267c094 | Anthony Liguori | g_free(cur->value.s); |
350 | d3f24367 | Kevin Wolf | } |
351 | d3f24367 | Kevin Wolf | cur++; |
352 | d3f24367 | Kevin Wolf | } |
353 | d3f24367 | Kevin Wolf | |
354 | 7267c094 | Anthony Liguori | g_free(list); |
355 | d3f24367 | Kevin Wolf | } |
356 | d3f24367 | Kevin Wolf | |
357 | d3f24367 | Kevin Wolf | /*
|
358 | b50cbabc | MORITA Kazutaka | * Count valid options in list
|
359 | b50cbabc | MORITA Kazutaka | */
|
360 | b50cbabc | MORITA Kazutaka | static size_t count_option_parameters(QEMUOptionParameter *list)
|
361 | b50cbabc | MORITA Kazutaka | { |
362 | b50cbabc | MORITA Kazutaka | size_t num_options = 0;
|
363 | b50cbabc | MORITA Kazutaka | |
364 | b50cbabc | MORITA Kazutaka | while (list && list->name) {
|
365 | b50cbabc | MORITA Kazutaka | num_options++; |
366 | b50cbabc | MORITA Kazutaka | list++; |
367 | b50cbabc | MORITA Kazutaka | } |
368 | b50cbabc | MORITA Kazutaka | |
369 | b50cbabc | MORITA Kazutaka | return num_options;
|
370 | b50cbabc | MORITA Kazutaka | } |
371 | b50cbabc | MORITA Kazutaka | |
372 | b50cbabc | MORITA Kazutaka | /*
|
373 | b50cbabc | MORITA Kazutaka | * Append an option list (list) to an option list (dest).
|
374 | b50cbabc | MORITA Kazutaka | *
|
375 | b50cbabc | MORITA Kazutaka | * If dest is NULL, a new copy of list is created.
|
376 | b50cbabc | MORITA Kazutaka | *
|
377 | b50cbabc | MORITA Kazutaka | * Returns a pointer to the first element of dest (or the newly allocated copy)
|
378 | b50cbabc | MORITA Kazutaka | */
|
379 | b50cbabc | MORITA Kazutaka | QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest, |
380 | b50cbabc | MORITA Kazutaka | QEMUOptionParameter *list) |
381 | b50cbabc | MORITA Kazutaka | { |
382 | b50cbabc | MORITA Kazutaka | size_t num_options, num_dest_options; |
383 | b50cbabc | MORITA Kazutaka | |
384 | b50cbabc | MORITA Kazutaka | num_options = count_option_parameters(dest); |
385 | b50cbabc | MORITA Kazutaka | num_dest_options = num_options; |
386 | b50cbabc | MORITA Kazutaka | |
387 | b50cbabc | MORITA Kazutaka | num_options += count_option_parameters(list); |
388 | b50cbabc | MORITA Kazutaka | |
389 | 7267c094 | Anthony Liguori | dest = g_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter)); |
390 | bd69fe84 | Kevin Wolf | dest[num_dest_options].name = NULL;
|
391 | b50cbabc | MORITA Kazutaka | |
392 | b50cbabc | MORITA Kazutaka | while (list && list->name) {
|
393 | b50cbabc | MORITA Kazutaka | if (get_option_parameter(dest, list->name) == NULL) { |
394 | b50cbabc | MORITA Kazutaka | dest[num_dest_options++] = *list; |
395 | b50cbabc | MORITA Kazutaka | dest[num_dest_options].name = NULL;
|
396 | b50cbabc | MORITA Kazutaka | } |
397 | b50cbabc | MORITA Kazutaka | list++; |
398 | b50cbabc | MORITA Kazutaka | } |
399 | b50cbabc | MORITA Kazutaka | |
400 | b50cbabc | MORITA Kazutaka | return dest;
|
401 | b50cbabc | MORITA Kazutaka | } |
402 | b50cbabc | MORITA Kazutaka | |
403 | b50cbabc | MORITA Kazutaka | /*
|
404 | d3f24367 | Kevin Wolf | * Parses a parameter string (param) into an option list (dest).
|
405 | d3f24367 | Kevin Wolf | *
|
406 | 0e72e753 | Stefan Hajnoczi | * list is the template option list. If dest is NULL, a new copy of list is
|
407 | 0e72e753 | Stefan Hajnoczi | * created. If list is NULL, this function fails.
|
408 | d3f24367 | Kevin Wolf | *
|
409 | d3f24367 | Kevin Wolf | * A parameter string consists of one or more parameters, separated by commas.
|
410 | d3f24367 | Kevin Wolf | * Each parameter consists of its name and possibly of a value. In the latter
|
411 | d3f24367 | Kevin Wolf | * case, the value is delimited by an = character. To specify a value which
|
412 | d3f24367 | Kevin Wolf | * contains commas, double each comma so it won't be recognized as the end of
|
413 | d3f24367 | Kevin Wolf | * the parameter.
|
414 | d3f24367 | Kevin Wolf | *
|
415 | d3f24367 | Kevin Wolf | * For more details of the parsing see above.
|
416 | d3f24367 | Kevin Wolf | *
|
417 | d3f24367 | Kevin Wolf | * Returns a pointer to the first element of dest (or the newly allocated copy)
|
418 | d3f24367 | Kevin Wolf | * or NULL in error cases
|
419 | d3f24367 | Kevin Wolf | */
|
420 | d3f24367 | Kevin Wolf | QEMUOptionParameter *parse_option_parameters(const char *param, |
421 | d3f24367 | Kevin Wolf | QEMUOptionParameter *list, QEMUOptionParameter *dest) |
422 | d3f24367 | Kevin Wolf | { |
423 | d3f24367 | Kevin Wolf | QEMUOptionParameter *allocated = NULL;
|
424 | d3f24367 | Kevin Wolf | char name[256]; |
425 | d3f24367 | Kevin Wolf | char value[256]; |
426 | d3f24367 | Kevin Wolf | char *param_delim, *value_delim;
|
427 | d3f24367 | Kevin Wolf | char next_delim;
|
428 | d3f24367 | Kevin Wolf | |
429 | d3f24367 | Kevin Wolf | if (list == NULL) { |
430 | d3f24367 | Kevin Wolf | return NULL; |
431 | d3f24367 | Kevin Wolf | } |
432 | d3f24367 | Kevin Wolf | |
433 | d3f24367 | Kevin Wolf | if (dest == NULL) { |
434 | 898c257b | Stefan Hajnoczi | dest = allocated = append_option_parameters(NULL, list);
|
435 | d3f24367 | Kevin Wolf | } |
436 | d3f24367 | Kevin Wolf | |
437 | d3f24367 | Kevin Wolf | while (*param) {
|
438 | d3f24367 | Kevin Wolf | |
439 | d3f24367 | Kevin Wolf | // Find parameter name and value in the string
|
440 | d3f24367 | Kevin Wolf | param_delim = strchr(param, ',');
|
441 | d3f24367 | Kevin Wolf | value_delim = strchr(param, '=');
|
442 | d3f24367 | Kevin Wolf | |
443 | d3f24367 | Kevin Wolf | if (value_delim && (value_delim < param_delim || !param_delim)) {
|
444 | d3f24367 | Kevin Wolf | next_delim = '=';
|
445 | d3f24367 | Kevin Wolf | } else {
|
446 | d3f24367 | Kevin Wolf | next_delim = ',';
|
447 | d3f24367 | Kevin Wolf | value_delim = NULL;
|
448 | d3f24367 | Kevin Wolf | } |
449 | d3f24367 | Kevin Wolf | |
450 | d3f24367 | Kevin Wolf | param = get_opt_name(name, sizeof(name), param, next_delim);
|
451 | d3f24367 | Kevin Wolf | if (value_delim) {
|
452 | d3f24367 | Kevin Wolf | param = get_opt_value(value, sizeof(value), param + 1); |
453 | d3f24367 | Kevin Wolf | } |
454 | d3f24367 | Kevin Wolf | if (*param != '\0') { |
455 | d3f24367 | Kevin Wolf | param++; |
456 | d3f24367 | Kevin Wolf | } |
457 | d3f24367 | Kevin Wolf | |
458 | d3f24367 | Kevin Wolf | // Set the parameter
|
459 | d3f24367 | Kevin Wolf | if (set_option_parameter(dest, name, value_delim ? value : NULL)) { |
460 | d3f24367 | Kevin Wolf | goto fail;
|
461 | d3f24367 | Kevin Wolf | } |
462 | d3f24367 | Kevin Wolf | } |
463 | d3f24367 | Kevin Wolf | |
464 | d3f24367 | Kevin Wolf | return dest;
|
465 | d3f24367 | Kevin Wolf | |
466 | d3f24367 | Kevin Wolf | fail:
|
467 | d3f24367 | Kevin Wolf | // Only free the list if it was newly allocated
|
468 | d3f24367 | Kevin Wolf | free_option_parameters(allocated); |
469 | d3f24367 | Kevin Wolf | return NULL; |
470 | d3f24367 | Kevin Wolf | } |
471 | d3f24367 | Kevin Wolf | |
472 | d3f24367 | Kevin Wolf | /*
|
473 | d3f24367 | Kevin Wolf | * Prints all options of a list that have a value to stdout
|
474 | d3f24367 | Kevin Wolf | */
|
475 | d3f24367 | Kevin Wolf | void print_option_parameters(QEMUOptionParameter *list)
|
476 | d3f24367 | Kevin Wolf | { |
477 | d3f24367 | Kevin Wolf | while (list && list->name) {
|
478 | d3f24367 | Kevin Wolf | switch (list->type) {
|
479 | d3f24367 | Kevin Wolf | case OPT_STRING:
|
480 | d3f24367 | Kevin Wolf | if (list->value.s != NULL) { |
481 | d3f24367 | Kevin Wolf | printf("%s='%s' ", list->name, list->value.s);
|
482 | d3f24367 | Kevin Wolf | } |
483 | d3f24367 | Kevin Wolf | break;
|
484 | d3f24367 | Kevin Wolf | case OPT_FLAG:
|
485 | d3f24367 | Kevin Wolf | printf("%s=%s ", list->name, list->value.n ? "on" : "off"); |
486 | d3f24367 | Kevin Wolf | break;
|
487 | d3f24367 | Kevin Wolf | case OPT_SIZE:
|
488 | d3f24367 | Kevin Wolf | case OPT_NUMBER:
|
489 | d3f24367 | Kevin Wolf | printf("%s=%" PRId64 " ", list->name, list->value.n); |
490 | d3f24367 | Kevin Wolf | break;
|
491 | d3f24367 | Kevin Wolf | default:
|
492 | 07f35073 | Dong Xu Wang | printf("%s=(unknown type) ", list->name);
|
493 | d3f24367 | Kevin Wolf | break;
|
494 | d3f24367 | Kevin Wolf | } |
495 | d3f24367 | Kevin Wolf | list++; |
496 | d3f24367 | Kevin Wolf | } |
497 | d3f24367 | Kevin Wolf | } |
498 | db08adf5 | Kevin Wolf | |
499 | db08adf5 | Kevin Wolf | /*
|
500 | db08adf5 | Kevin Wolf | * Prints an overview of all available options
|
501 | db08adf5 | Kevin Wolf | */
|
502 | db08adf5 | Kevin Wolf | void print_option_help(QEMUOptionParameter *list)
|
503 | db08adf5 | Kevin Wolf | { |
504 | db08adf5 | Kevin Wolf | printf("Supported options:\n");
|
505 | db08adf5 | Kevin Wolf | while (list && list->name) {
|
506 | db08adf5 | Kevin Wolf | printf("%-16s %s\n", list->name,
|
507 | db08adf5 | Kevin Wolf | list->help ? list->help : "No description available");
|
508 | db08adf5 | Kevin Wolf | list++; |
509 | db08adf5 | Kevin Wolf | } |
510 | db08adf5 | Kevin Wolf | } |
511 | e27c88fe | Gerd Hoffmann | |
512 | e27c88fe | Gerd Hoffmann | /* ------------------------------------------------------------------ */
|
513 | e27c88fe | Gerd Hoffmann | |
514 | e27c88fe | Gerd Hoffmann | static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name) |
515 | e27c88fe | Gerd Hoffmann | { |
516 | e27c88fe | Gerd Hoffmann | QemuOpt *opt; |
517 | e27c88fe | Gerd Hoffmann | |
518 | dc9ca4ba | Mark McLoughlin | QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) { |
519 | e27c88fe | Gerd Hoffmann | if (strcmp(opt->name, name) != 0) |
520 | e27c88fe | Gerd Hoffmann | continue;
|
521 | e27c88fe | Gerd Hoffmann | return opt;
|
522 | e27c88fe | Gerd Hoffmann | } |
523 | e27c88fe | Gerd Hoffmann | return NULL; |
524 | e27c88fe | Gerd Hoffmann | } |
525 | e27c88fe | Gerd Hoffmann | |
526 | e27c88fe | Gerd Hoffmann | const char *qemu_opt_get(QemuOpts *opts, const char *name) |
527 | e27c88fe | Gerd Hoffmann | { |
528 | e27c88fe | Gerd Hoffmann | QemuOpt *opt = qemu_opt_find(opts, name); |
529 | e27c88fe | Gerd Hoffmann | return opt ? opt->str : NULL; |
530 | e27c88fe | Gerd Hoffmann | } |
531 | e27c88fe | Gerd Hoffmann | |
532 | c8057f95 | Peter Maydell | bool qemu_opt_has_help_opt(QemuOpts *opts)
|
533 | c8057f95 | Peter Maydell | { |
534 | c8057f95 | Peter Maydell | QemuOpt *opt; |
535 | c8057f95 | Peter Maydell | |
536 | c8057f95 | Peter Maydell | QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) { |
537 | c8057f95 | Peter Maydell | if (is_help_option(opt->name)) {
|
538 | c8057f95 | Peter Maydell | return true; |
539 | c8057f95 | Peter Maydell | } |
540 | c8057f95 | Peter Maydell | } |
541 | c8057f95 | Peter Maydell | return false; |
542 | c8057f95 | Peter Maydell | } |
543 | c8057f95 | Peter Maydell | |
544 | f02b77c9 | M. Mohan Kumar | bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval) |
545 | e27c88fe | Gerd Hoffmann | { |
546 | e27c88fe | Gerd Hoffmann | QemuOpt *opt = qemu_opt_find(opts, name); |
547 | e27c88fe | Gerd Hoffmann | |
548 | e27c88fe | Gerd Hoffmann | if (opt == NULL) |
549 | e27c88fe | Gerd Hoffmann | return defval;
|
550 | e27c88fe | Gerd Hoffmann | assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL); |
551 | 1f5c1775 | Juan Quintela | return opt->value.boolean;
|
552 | e27c88fe | Gerd Hoffmann | } |
553 | e27c88fe | Gerd Hoffmann | |
554 | e27c88fe | Gerd Hoffmann | uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval) |
555 | e27c88fe | Gerd Hoffmann | { |
556 | e27c88fe | Gerd Hoffmann | QemuOpt *opt = qemu_opt_find(opts, name); |
557 | e27c88fe | Gerd Hoffmann | |
558 | e27c88fe | Gerd Hoffmann | if (opt == NULL) |
559 | e27c88fe | Gerd Hoffmann | return defval;
|
560 | e27c88fe | Gerd Hoffmann | assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER); |
561 | e27c88fe | Gerd Hoffmann | return opt->value.uint;
|
562 | e27c88fe | Gerd Hoffmann | } |
563 | e27c88fe | Gerd Hoffmann | |
564 | e27c88fe | Gerd Hoffmann | uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval) |
565 | e27c88fe | Gerd Hoffmann | { |
566 | e27c88fe | Gerd Hoffmann | QemuOpt *opt = qemu_opt_find(opts, name); |
567 | e27c88fe | Gerd Hoffmann | |
568 | e27c88fe | Gerd Hoffmann | if (opt == NULL) |
569 | e27c88fe | Gerd Hoffmann | return defval;
|
570 | e27c88fe | Gerd Hoffmann | assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE); |
571 | e27c88fe | Gerd Hoffmann | return opt->value.uint;
|
572 | e27c88fe | Gerd Hoffmann | } |
573 | e27c88fe | Gerd Hoffmann | |
574 | 6c519404 | Luiz Capitulino | static void qemu_opt_parse(QemuOpt *opt, Error **errp) |
575 | e27c88fe | Gerd Hoffmann | { |
576 | e27c88fe | Gerd Hoffmann | if (opt->desc == NULL) |
577 | 6c519404 | Luiz Capitulino | return;
|
578 | 2f39df5b | Luiz Capitulino | |
579 | e27c88fe | Gerd Hoffmann | switch (opt->desc->type) {
|
580 | e27c88fe | Gerd Hoffmann | case QEMU_OPT_STRING:
|
581 | e27c88fe | Gerd Hoffmann | /* nothing */
|
582 | 6c519404 | Luiz Capitulino | return;
|
583 | e27c88fe | Gerd Hoffmann | case QEMU_OPT_BOOL:
|
584 | 6c519404 | Luiz Capitulino | parse_option_bool(opt->name, opt->str, &opt->value.boolean, errp); |
585 | cf62adfa | Luiz Capitulino | break;
|
586 | e27c88fe | Gerd Hoffmann | case QEMU_OPT_NUMBER:
|
587 | 6c519404 | Luiz Capitulino | parse_option_number(opt->name, opt->str, &opt->value.uint, errp); |
588 | 2f39df5b | Luiz Capitulino | break;
|
589 | e27c88fe | Gerd Hoffmann | case QEMU_OPT_SIZE:
|
590 | 6c519404 | Luiz Capitulino | parse_option_size(opt->name, opt->str, &opt->value.uint, errp); |
591 | ec7b2ccb | Luiz Capitulino | break;
|
592 | e27c88fe | Gerd Hoffmann | default:
|
593 | e27c88fe | Gerd Hoffmann | abort(); |
594 | e27c88fe | Gerd Hoffmann | } |
595 | e27c88fe | Gerd Hoffmann | } |
596 | e27c88fe | Gerd Hoffmann | |
597 | e27c88fe | Gerd Hoffmann | static void qemu_opt_del(QemuOpt *opt) |
598 | e27c88fe | Gerd Hoffmann | { |
599 | 72cf2d4f | Blue Swirl | QTAILQ_REMOVE(&opt->opts->head, opt, next); |
600 | 7267c094 | Anthony Liguori | g_free((/* !const */ char*)opt->name); |
601 | 7267c094 | Anthony Liguori | g_free((/* !const */ char*)opt->str); |
602 | 7267c094 | Anthony Liguori | g_free(opt); |
603 | e27c88fe | Gerd Hoffmann | } |
604 | e27c88fe | Gerd Hoffmann | |
605 | 584d4064 | Luiz Capitulino | static void opt_set(QemuOpts *opts, const char *name, const char *value, |
606 | 584d4064 | Luiz Capitulino | bool prepend, Error **errp)
|
607 | e27c88fe | Gerd Hoffmann | { |
608 | e27c88fe | Gerd Hoffmann | QemuOpt *opt; |
609 | 238431a9 | Blue Swirl | const QemuOptDesc *desc = opts->list->desc;
|
610 | 6c519404 | Luiz Capitulino | Error *local_err = NULL;
|
611 | dc9ca4ba | Mark McLoughlin | int i;
|
612 | e27c88fe | Gerd Hoffmann | |
613 | dc9ca4ba | Mark McLoughlin | for (i = 0; desc[i].name != NULL; i++) { |
614 | dc9ca4ba | Mark McLoughlin | if (strcmp(desc[i].name, name) == 0) { |
615 | dc9ca4ba | Mark McLoughlin | break;
|
616 | e27c88fe | Gerd Hoffmann | } |
617 | dc9ca4ba | Mark McLoughlin | } |
618 | dc9ca4ba | Mark McLoughlin | if (desc[i].name == NULL) { |
619 | dc9ca4ba | Mark McLoughlin | if (i == 0) { |
620 | dc9ca4ba | Mark McLoughlin | /* empty list -> allow any */;
|
621 | dc9ca4ba | Mark McLoughlin | } else {
|
622 | 584d4064 | Luiz Capitulino | error_set(errp, QERR_INVALID_PARAMETER, name); |
623 | 584d4064 | Luiz Capitulino | return;
|
624 | e27c88fe | Gerd Hoffmann | } |
625 | e27c88fe | Gerd Hoffmann | } |
626 | dc9ca4ba | Mark McLoughlin | |
627 | 7267c094 | Anthony Liguori | opt = g_malloc0(sizeof(*opt));
|
628 | 7267c094 | Anthony Liguori | opt->name = g_strdup(name); |
629 | dc9ca4ba | Mark McLoughlin | opt->opts = opts; |
630 | 4f6dd9af | Jan Kiszka | if (prepend) {
|
631 | 4f6dd9af | Jan Kiszka | QTAILQ_INSERT_HEAD(&opts->head, opt, next); |
632 | 4f6dd9af | Jan Kiszka | } else {
|
633 | 4f6dd9af | Jan Kiszka | QTAILQ_INSERT_TAIL(&opts->head, opt, next); |
634 | 4f6dd9af | Jan Kiszka | } |
635 | dc9ca4ba | Mark McLoughlin | if (desc[i].name != NULL) { |
636 | dc9ca4ba | Mark McLoughlin | opt->desc = desc+i; |
637 | dc9ca4ba | Mark McLoughlin | } |
638 | e27c88fe | Gerd Hoffmann | if (value) {
|
639 | 7267c094 | Anthony Liguori | opt->str = g_strdup(value); |
640 | e27c88fe | Gerd Hoffmann | } |
641 | 6c519404 | Luiz Capitulino | qemu_opt_parse(opt, &local_err); |
642 | 6c519404 | Luiz Capitulino | if (error_is_set(&local_err)) {
|
643 | 584d4064 | Luiz Capitulino | error_propagate(errp, local_err); |
644 | e27c88fe | Gerd Hoffmann | qemu_opt_del(opt); |
645 | e27c88fe | Gerd Hoffmann | } |
646 | e27c88fe | Gerd Hoffmann | } |
647 | e27c88fe | Gerd Hoffmann | |
648 | 4f6dd9af | Jan Kiszka | int qemu_opt_set(QemuOpts *opts, const char *name, const char *value) |
649 | 4f6dd9af | Jan Kiszka | { |
650 | 584d4064 | Luiz Capitulino | Error *local_err = NULL;
|
651 | 584d4064 | Luiz Capitulino | |
652 | 584d4064 | Luiz Capitulino | opt_set(opts, name, value, false, &local_err);
|
653 | 584d4064 | Luiz Capitulino | if (error_is_set(&local_err)) {
|
654 | 584d4064 | Luiz Capitulino | qerror_report_err(local_err); |
655 | 584d4064 | Luiz Capitulino | error_free(local_err); |
656 | 584d4064 | Luiz Capitulino | return -1; |
657 | 584d4064 | Luiz Capitulino | } |
658 | 584d4064 | Luiz Capitulino | |
659 | 584d4064 | Luiz Capitulino | return 0; |
660 | 4f6dd9af | Jan Kiszka | } |
661 | 4f6dd9af | Jan Kiszka | |
662 | 384f2139 | Luiz Capitulino | void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value, |
663 | 384f2139 | Luiz Capitulino | Error **errp) |
664 | 384f2139 | Luiz Capitulino | { |
665 | 384f2139 | Luiz Capitulino | opt_set(opts, name, value, false, errp);
|
666 | 384f2139 | Luiz Capitulino | } |
667 | 384f2139 | Luiz Capitulino | |
668 | f02b77c9 | M. Mohan Kumar | int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val) |
669 | f02b77c9 | M. Mohan Kumar | { |
670 | f02b77c9 | M. Mohan Kumar | QemuOpt *opt; |
671 | f02b77c9 | M. Mohan Kumar | const QemuOptDesc *desc = opts->list->desc;
|
672 | f02b77c9 | M. Mohan Kumar | int i;
|
673 | f02b77c9 | M. Mohan Kumar | |
674 | f02b77c9 | M. Mohan Kumar | for (i = 0; desc[i].name != NULL; i++) { |
675 | f02b77c9 | M. Mohan Kumar | if (strcmp(desc[i].name, name) == 0) { |
676 | f02b77c9 | M. Mohan Kumar | break;
|
677 | f02b77c9 | M. Mohan Kumar | } |
678 | f02b77c9 | M. Mohan Kumar | } |
679 | f02b77c9 | M. Mohan Kumar | if (desc[i].name == NULL) { |
680 | f02b77c9 | M. Mohan Kumar | if (i == 0) { |
681 | f02b77c9 | M. Mohan Kumar | /* empty list -> allow any */;
|
682 | f02b77c9 | M. Mohan Kumar | } else {
|
683 | f02b77c9 | M. Mohan Kumar | qerror_report(QERR_INVALID_PARAMETER, name); |
684 | f02b77c9 | M. Mohan Kumar | return -1; |
685 | f02b77c9 | M. Mohan Kumar | } |
686 | f02b77c9 | M. Mohan Kumar | } |
687 | f02b77c9 | M. Mohan Kumar | |
688 | f02b77c9 | M. Mohan Kumar | opt = g_malloc0(sizeof(*opt));
|
689 | f02b77c9 | M. Mohan Kumar | opt->name = g_strdup(name); |
690 | f02b77c9 | M. Mohan Kumar | opt->opts = opts; |
691 | f02b77c9 | M. Mohan Kumar | QTAILQ_INSERT_TAIL(&opts->head, opt, next); |
692 | f02b77c9 | M. Mohan Kumar | if (desc[i].name != NULL) { |
693 | f02b77c9 | M. Mohan Kumar | opt->desc = desc+i; |
694 | f02b77c9 | M. Mohan Kumar | } |
695 | f02b77c9 | M. Mohan Kumar | opt->value.boolean = !!val; |
696 | f02b77c9 | M. Mohan Kumar | return 0; |
697 | f02b77c9 | M. Mohan Kumar | } |
698 | f02b77c9 | M. Mohan Kumar | |
699 | 48026075 | Gerd Hoffmann | int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque, |
700 | 48026075 | Gerd Hoffmann | int abort_on_failure)
|
701 | 48026075 | Gerd Hoffmann | { |
702 | 48026075 | Gerd Hoffmann | QemuOpt *opt; |
703 | 48026075 | Gerd Hoffmann | int rc = 0; |
704 | 48026075 | Gerd Hoffmann | |
705 | 72cf2d4f | Blue Swirl | QTAILQ_FOREACH(opt, &opts->head, next) { |
706 | 48026075 | Gerd Hoffmann | rc = func(opt->name, opt->str, opaque); |
707 | 48026075 | Gerd Hoffmann | if (abort_on_failure && rc != 0) |
708 | 48026075 | Gerd Hoffmann | break;
|
709 | 48026075 | Gerd Hoffmann | } |
710 | 48026075 | Gerd Hoffmann | return rc;
|
711 | 48026075 | Gerd Hoffmann | } |
712 | 48026075 | Gerd Hoffmann | |
713 | e27c88fe | Gerd Hoffmann | QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id) |
714 | e27c88fe | Gerd Hoffmann | { |
715 | e27c88fe | Gerd Hoffmann | QemuOpts *opts; |
716 | e27c88fe | Gerd Hoffmann | |
717 | 72cf2d4f | Blue Swirl | QTAILQ_FOREACH(opts, &list->head, next) { |
718 | e27c88fe | Gerd Hoffmann | if (!opts->id) {
|
719 | 4f6dd9af | Jan Kiszka | if (!id) {
|
720 | 4f6dd9af | Jan Kiszka | return opts;
|
721 | 4f6dd9af | Jan Kiszka | } |
722 | e27c88fe | Gerd Hoffmann | continue;
|
723 | e27c88fe | Gerd Hoffmann | } |
724 | e27c88fe | Gerd Hoffmann | if (strcmp(opts->id, id) != 0) { |
725 | e27c88fe | Gerd Hoffmann | continue;
|
726 | e27c88fe | Gerd Hoffmann | } |
727 | e27c88fe | Gerd Hoffmann | return opts;
|
728 | e27c88fe | Gerd Hoffmann | } |
729 | e27c88fe | Gerd Hoffmann | return NULL; |
730 | e27c88fe | Gerd Hoffmann | } |
731 | e27c88fe | Gerd Hoffmann | |
732 | b560a9ab | Markus Armbruster | static int id_wellformed(const char *id) |
733 | b560a9ab | Markus Armbruster | { |
734 | b560a9ab | Markus Armbruster | int i;
|
735 | b560a9ab | Markus Armbruster | |
736 | b560a9ab | Markus Armbruster | if (!qemu_isalpha(id[0])) { |
737 | b560a9ab | Markus Armbruster | return 0; |
738 | b560a9ab | Markus Armbruster | } |
739 | b560a9ab | Markus Armbruster | for (i = 1; id[i]; i++) { |
740 | b560a9ab | Markus Armbruster | if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) { |
741 | b560a9ab | Markus Armbruster | return 0; |
742 | b560a9ab | Markus Armbruster | } |
743 | b560a9ab | Markus Armbruster | } |
744 | b560a9ab | Markus Armbruster | return 1; |
745 | b560a9ab | Markus Armbruster | } |
746 | b560a9ab | Markus Armbruster | |
747 | 8be7e7e4 | Luiz Capitulino | QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, |
748 | 8be7e7e4 | Luiz Capitulino | int fail_if_exists, Error **errp)
|
749 | e27c88fe | Gerd Hoffmann | { |
750 | e27c88fe | Gerd Hoffmann | QemuOpts *opts = NULL;
|
751 | e27c88fe | Gerd Hoffmann | |
752 | e27c88fe | Gerd Hoffmann | if (id) {
|
753 | b560a9ab | Markus Armbruster | if (!id_wellformed(id)) {
|
754 | 8be7e7e4 | Luiz Capitulino | error_set(errp,QERR_INVALID_PARAMETER_VALUE, "id", "an identifier"); |
755 | b560a9ab | Markus Armbruster | error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
|
756 | b560a9ab | Markus Armbruster | return NULL; |
757 | b560a9ab | Markus Armbruster | } |
758 | e27c88fe | Gerd Hoffmann | opts = qemu_opts_find(list, id); |
759 | e27c88fe | Gerd Hoffmann | if (opts != NULL) { |
760 | da93318a | Peter Maydell | if (fail_if_exists && !list->merge_lists) {
|
761 | 8be7e7e4 | Luiz Capitulino | error_set(errp, QERR_DUPLICATE_ID, id, list->name); |
762 | e27c88fe | Gerd Hoffmann | return NULL; |
763 | e27c88fe | Gerd Hoffmann | } else {
|
764 | e27c88fe | Gerd Hoffmann | return opts;
|
765 | e27c88fe | Gerd Hoffmann | } |
766 | e27c88fe | Gerd Hoffmann | } |
767 | da93318a | Peter Maydell | } else if (list->merge_lists) { |
768 | da93318a | Peter Maydell | opts = qemu_opts_find(list, NULL);
|
769 | da93318a | Peter Maydell | if (opts) {
|
770 | da93318a | Peter Maydell | return opts;
|
771 | da93318a | Peter Maydell | } |
772 | e27c88fe | Gerd Hoffmann | } |
773 | 7267c094 | Anthony Liguori | opts = g_malloc0(sizeof(*opts));
|
774 | e27c88fe | Gerd Hoffmann | if (id) {
|
775 | 7267c094 | Anthony Liguori | opts->id = g_strdup(id); |
776 | e27c88fe | Gerd Hoffmann | } |
777 | e27c88fe | Gerd Hoffmann | opts->list = list; |
778 | 827b0813 | Markus Armbruster | loc_save(&opts->loc); |
779 | 72cf2d4f | Blue Swirl | QTAILQ_INIT(&opts->head); |
780 | 72cf2d4f | Blue Swirl | QTAILQ_INSERT_TAIL(&list->head, opts, next); |
781 | e27c88fe | Gerd Hoffmann | return opts;
|
782 | e27c88fe | Gerd Hoffmann | } |
783 | e27c88fe | Gerd Hoffmann | |
784 | bb67ab02 | Markus Armbruster | void qemu_opts_reset(QemuOptsList *list)
|
785 | bb67ab02 | Markus Armbruster | { |
786 | bb67ab02 | Markus Armbruster | QemuOpts *opts, *next_opts; |
787 | bb67ab02 | Markus Armbruster | |
788 | bb67ab02 | Markus Armbruster | QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) { |
789 | bb67ab02 | Markus Armbruster | qemu_opts_del(opts); |
790 | bb67ab02 | Markus Armbruster | } |
791 | bb67ab02 | Markus Armbruster | } |
792 | bb67ab02 | Markus Armbruster | |
793 | 94ac7268 | Markus Armbruster | void qemu_opts_loc_restore(QemuOpts *opts)
|
794 | 94ac7268 | Markus Armbruster | { |
795 | 94ac7268 | Markus Armbruster | loc_restore(&opts->loc); |
796 | 94ac7268 | Markus Armbruster | } |
797 | 94ac7268 | Markus Armbruster | |
798 | e27c88fe | Gerd Hoffmann | int qemu_opts_set(QemuOptsList *list, const char *id, |
799 | e27c88fe | Gerd Hoffmann | const char *name, const char *value) |
800 | e27c88fe | Gerd Hoffmann | { |
801 | e27c88fe | Gerd Hoffmann | QemuOpts *opts; |
802 | 8be7e7e4 | Luiz Capitulino | Error *local_err = NULL;
|
803 | e27c88fe | Gerd Hoffmann | |
804 | 8be7e7e4 | Luiz Capitulino | opts = qemu_opts_create(list, id, 1, &local_err);
|
805 | 8be7e7e4 | Luiz Capitulino | if (error_is_set(&local_err)) {
|
806 | 8be7e7e4 | Luiz Capitulino | qerror_report_err(local_err); |
807 | 8be7e7e4 | Luiz Capitulino | error_free(local_err); |
808 | e27c88fe | Gerd Hoffmann | return -1; |
809 | e27c88fe | Gerd Hoffmann | } |
810 | e27c88fe | Gerd Hoffmann | return qemu_opt_set(opts, name, value);
|
811 | e27c88fe | Gerd Hoffmann | } |
812 | e27c88fe | Gerd Hoffmann | |
813 | 48026075 | Gerd Hoffmann | const char *qemu_opts_id(QemuOpts *opts) |
814 | 48026075 | Gerd Hoffmann | { |
815 | 48026075 | Gerd Hoffmann | return opts->id;
|
816 | 48026075 | Gerd Hoffmann | } |
817 | 48026075 | Gerd Hoffmann | |
818 | e27c88fe | Gerd Hoffmann | void qemu_opts_del(QemuOpts *opts)
|
819 | e27c88fe | Gerd Hoffmann | { |
820 | e27c88fe | Gerd Hoffmann | QemuOpt *opt; |
821 | e27c88fe | Gerd Hoffmann | |
822 | e27c88fe | Gerd Hoffmann | for (;;) {
|
823 | 72cf2d4f | Blue Swirl | opt = QTAILQ_FIRST(&opts->head); |
824 | e27c88fe | Gerd Hoffmann | if (opt == NULL) |
825 | e27c88fe | Gerd Hoffmann | break;
|
826 | e27c88fe | Gerd Hoffmann | qemu_opt_del(opt); |
827 | e27c88fe | Gerd Hoffmann | } |
828 | 72cf2d4f | Blue Swirl | QTAILQ_REMOVE(&opts->list->head, opts, next); |
829 | 7267c094 | Anthony Liguori | g_free(opts->id); |
830 | 7267c094 | Anthony Liguori | g_free(opts); |
831 | e27c88fe | Gerd Hoffmann | } |
832 | e27c88fe | Gerd Hoffmann | |
833 | e27c88fe | Gerd Hoffmann | int qemu_opts_print(QemuOpts *opts, void *dummy) |
834 | e27c88fe | Gerd Hoffmann | { |
835 | e27c88fe | Gerd Hoffmann | QemuOpt *opt; |
836 | e27c88fe | Gerd Hoffmann | |
837 | e27c88fe | Gerd Hoffmann | fprintf(stderr, "%s: %s:", opts->list->name,
|
838 | e27c88fe | Gerd Hoffmann | opts->id ? opts->id : "<noid>");
|
839 | 72cf2d4f | Blue Swirl | QTAILQ_FOREACH(opt, &opts->head, next) { |
840 | e27c88fe | Gerd Hoffmann | fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
|
841 | e27c88fe | Gerd Hoffmann | } |
842 | e27c88fe | Gerd Hoffmann | fprintf(stderr, "\n");
|
843 | e27c88fe | Gerd Hoffmann | return 0; |
844 | e27c88fe | Gerd Hoffmann | } |
845 | e27c88fe | Gerd Hoffmann | |
846 | 4f6dd9af | Jan Kiszka | static int opts_do_parse(QemuOpts *opts, const char *params, |
847 | 4f6dd9af | Jan Kiszka | const char *firstname, bool prepend) |
848 | e27c88fe | Gerd Hoffmann | { |
849 | d318ff99 | Gerd Hoffmann | char option[128], value[1024]; |
850 | e27c88fe | Gerd Hoffmann | const char *p,*pe,*pc; |
851 | 584d4064 | Luiz Capitulino | Error *local_err = NULL;
|
852 | e27c88fe | Gerd Hoffmann | |
853 | 2cfa571f | Mark McLoughlin | for (p = params; *p != '\0'; p++) { |
854 | e27c88fe | Gerd Hoffmann | pe = strchr(p, '=');
|
855 | e27c88fe | Gerd Hoffmann | pc = strchr(p, ',');
|
856 | e27c88fe | Gerd Hoffmann | if (!pe || (pc && pc < pe)) {
|
857 | e27c88fe | Gerd Hoffmann | /* found "foo,more" */
|
858 | e27c88fe | Gerd Hoffmann | if (p == params && firstname) {
|
859 | e27c88fe | Gerd Hoffmann | /* implicitly named first option */
|
860 | e27c88fe | Gerd Hoffmann | pstrcpy(option, sizeof(option), firstname);
|
861 | e27c88fe | Gerd Hoffmann | p = get_opt_value(value, sizeof(value), p);
|
862 | e27c88fe | Gerd Hoffmann | } else {
|
863 | e27c88fe | Gerd Hoffmann | /* option without value, probably a flag */
|
864 | e27c88fe | Gerd Hoffmann | p = get_opt_name(option, sizeof(option), p, ','); |
865 | 96729cbd | Gerd Hoffmann | if (strncmp(option, "no", 2) == 0) { |
866 | e27c88fe | Gerd Hoffmann | memmove(option, option+2, strlen(option+2)+1); |
867 | e27c88fe | Gerd Hoffmann | pstrcpy(value, sizeof(value), "off"); |
868 | e27c88fe | Gerd Hoffmann | } else {
|
869 | e27c88fe | Gerd Hoffmann | pstrcpy(value, sizeof(value), "on"); |
870 | e27c88fe | Gerd Hoffmann | } |
871 | e27c88fe | Gerd Hoffmann | } |
872 | e27c88fe | Gerd Hoffmann | } else {
|
873 | e27c88fe | Gerd Hoffmann | /* found "foo=bar,more" */
|
874 | e27c88fe | Gerd Hoffmann | p = get_opt_name(option, sizeof(option), p, '='); |
875 | e27c88fe | Gerd Hoffmann | if (*p != '=') { |
876 | e27c88fe | Gerd Hoffmann | break;
|
877 | e27c88fe | Gerd Hoffmann | } |
878 | e27c88fe | Gerd Hoffmann | p++; |
879 | e27c88fe | Gerd Hoffmann | p = get_opt_value(value, sizeof(value), p);
|
880 | e27c88fe | Gerd Hoffmann | } |
881 | e27c88fe | Gerd Hoffmann | if (strcmp(option, "id") != 0) { |
882 | e27c88fe | Gerd Hoffmann | /* store and parse */
|
883 | 584d4064 | Luiz Capitulino | opt_set(opts, option, value, prepend, &local_err); |
884 | 584d4064 | Luiz Capitulino | if (error_is_set(&local_err)) {
|
885 | 584d4064 | Luiz Capitulino | qerror_report_err(local_err); |
886 | 584d4064 | Luiz Capitulino | error_free(local_err); |
887 | 96729cbd | Gerd Hoffmann | return -1; |
888 | e27c88fe | Gerd Hoffmann | } |
889 | e27c88fe | Gerd Hoffmann | } |
890 | e27c88fe | Gerd Hoffmann | if (*p != ',') { |
891 | e27c88fe | Gerd Hoffmann | break;
|
892 | e27c88fe | Gerd Hoffmann | } |
893 | e27c88fe | Gerd Hoffmann | } |
894 | 96729cbd | Gerd Hoffmann | return 0; |
895 | 96729cbd | Gerd Hoffmann | } |
896 | 96729cbd | Gerd Hoffmann | |
897 | 4f6dd9af | Jan Kiszka | int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname) |
898 | 4f6dd9af | Jan Kiszka | { |
899 | 4f6dd9af | Jan Kiszka | return opts_do_parse(opts, params, firstname, false); |
900 | 4f6dd9af | Jan Kiszka | } |
901 | 4f6dd9af | Jan Kiszka | |
902 | 4f6dd9af | Jan Kiszka | static QemuOpts *opts_parse(QemuOptsList *list, const char *params, |
903 | 4f6dd9af | Jan Kiszka | int permit_abbrev, bool defaults) |
904 | 96729cbd | Gerd Hoffmann | { |
905 | 8212c64f | Markus Armbruster | const char *firstname; |
906 | d318ff99 | Gerd Hoffmann | char value[1024], *id = NULL; |
907 | 96729cbd | Gerd Hoffmann | const char *p; |
908 | 96729cbd | Gerd Hoffmann | QemuOpts *opts; |
909 | 8be7e7e4 | Luiz Capitulino | Error *local_err = NULL;
|
910 | 96729cbd | Gerd Hoffmann | |
911 | 8212c64f | Markus Armbruster | assert(!permit_abbrev || list->implied_opt_name); |
912 | 8212c64f | Markus Armbruster | firstname = permit_abbrev ? list->implied_opt_name : NULL;
|
913 | 8212c64f | Markus Armbruster | |
914 | 96729cbd | Gerd Hoffmann | if (strncmp(params, "id=", 3) == 0) { |
915 | 96729cbd | Gerd Hoffmann | get_opt_value(value, sizeof(value), params+3); |
916 | d510c5cf | Jan Kiszka | id = value; |
917 | 96729cbd | Gerd Hoffmann | } else if ((p = strstr(params, ",id=")) != NULL) { |
918 | 96729cbd | Gerd Hoffmann | get_opt_value(value, sizeof(value), p+4); |
919 | d510c5cf | Jan Kiszka | id = value; |
920 | 96729cbd | Gerd Hoffmann | } |
921 | 4f6dd9af | Jan Kiszka | if (defaults) {
|
922 | 4f6dd9af | Jan Kiszka | if (!id && !QTAILQ_EMPTY(&list->head)) {
|
923 | 4f6dd9af | Jan Kiszka | opts = qemu_opts_find(list, NULL);
|
924 | 4f6dd9af | Jan Kiszka | } else {
|
925 | 8be7e7e4 | Luiz Capitulino | opts = qemu_opts_create(list, id, 0, &local_err);
|
926 | 4f6dd9af | Jan Kiszka | } |
927 | 4f6dd9af | Jan Kiszka | } else {
|
928 | 8be7e7e4 | Luiz Capitulino | opts = qemu_opts_create(list, id, 1, &local_err);
|
929 | 4f6dd9af | Jan Kiszka | } |
930 | 8be7e7e4 | Luiz Capitulino | if (opts == NULL) { |
931 | 8be7e7e4 | Luiz Capitulino | if (error_is_set(&local_err)) {
|
932 | 8be7e7e4 | Luiz Capitulino | qerror_report_err(local_err); |
933 | 8be7e7e4 | Luiz Capitulino | error_free(local_err); |
934 | 8be7e7e4 | Luiz Capitulino | } |
935 | 96729cbd | Gerd Hoffmann | return NULL; |
936 | 8be7e7e4 | Luiz Capitulino | } |
937 | 96729cbd | Gerd Hoffmann | |
938 | 4f6dd9af | Jan Kiszka | if (opts_do_parse(opts, params, firstname, defaults) != 0) { |
939 | 96729cbd | Gerd Hoffmann | qemu_opts_del(opts); |
940 | 96729cbd | Gerd Hoffmann | return NULL; |
941 | 96729cbd | Gerd Hoffmann | } |
942 | 96729cbd | Gerd Hoffmann | |
943 | e27c88fe | Gerd Hoffmann | return opts;
|
944 | e27c88fe | Gerd Hoffmann | } |
945 | e27c88fe | Gerd Hoffmann | |
946 | 4f6dd9af | Jan Kiszka | QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, |
947 | 4f6dd9af | Jan Kiszka | int permit_abbrev)
|
948 | 4f6dd9af | Jan Kiszka | { |
949 | 4f6dd9af | Jan Kiszka | return opts_parse(list, params, permit_abbrev, false); |
950 | 4f6dd9af | Jan Kiszka | } |
951 | 4f6dd9af | Jan Kiszka | |
952 | 4f6dd9af | Jan Kiszka | void qemu_opts_set_defaults(QemuOptsList *list, const char *params, |
953 | 4f6dd9af | Jan Kiszka | int permit_abbrev)
|
954 | 4f6dd9af | Jan Kiszka | { |
955 | 4f6dd9af | Jan Kiszka | QemuOpts *opts; |
956 | 4f6dd9af | Jan Kiszka | |
957 | 4f6dd9af | Jan Kiszka | opts = opts_parse(list, params, permit_abbrev, true);
|
958 | 4f6dd9af | Jan Kiszka | assert(opts); |
959 | 4f6dd9af | Jan Kiszka | } |
960 | 4f6dd9af | Jan Kiszka | |
961 | 4e89978e | Luiz Capitulino | typedef struct OptsFromQDictState { |
962 | 4e89978e | Luiz Capitulino | QemuOpts *opts; |
963 | 4e89978e | Luiz Capitulino | Error **errp; |
964 | 4e89978e | Luiz Capitulino | } OptsFromQDictState; |
965 | 4e89978e | Luiz Capitulino | |
966 | 01e7f188 | Markus Armbruster | static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque) |
967 | 01e7f188 | Markus Armbruster | { |
968 | 4e89978e | Luiz Capitulino | OptsFromQDictState *state = opaque; |
969 | 01e7f188 | Markus Armbruster | char buf[32]; |
970 | 01e7f188 | Markus Armbruster | const char *value; |
971 | 01e7f188 | Markus Armbruster | int n;
|
972 | 01e7f188 | Markus Armbruster | |
973 | 4e89978e | Luiz Capitulino | if (!strcmp(key, "id") || error_is_set(state->errp)) { |
974 | 01e7f188 | Markus Armbruster | return;
|
975 | 01e7f188 | Markus Armbruster | } |
976 | 01e7f188 | Markus Armbruster | |
977 | 01e7f188 | Markus Armbruster | switch (qobject_type(obj)) {
|
978 | 01e7f188 | Markus Armbruster | case QTYPE_QSTRING:
|
979 | 01e7f188 | Markus Armbruster | value = qstring_get_str(qobject_to_qstring(obj)); |
980 | 01e7f188 | Markus Armbruster | break;
|
981 | 01e7f188 | Markus Armbruster | case QTYPE_QINT:
|
982 | 01e7f188 | Markus Armbruster | n = snprintf(buf, sizeof(buf), "%" PRId64, |
983 | 01e7f188 | Markus Armbruster | qint_get_int(qobject_to_qint(obj))); |
984 | 01e7f188 | Markus Armbruster | assert(n < sizeof(buf));
|
985 | 01e7f188 | Markus Armbruster | value = buf; |
986 | 01e7f188 | Markus Armbruster | break;
|
987 | 01e7f188 | Markus Armbruster | case QTYPE_QFLOAT:
|
988 | 01e7f188 | Markus Armbruster | n = snprintf(buf, sizeof(buf), "%.17g", |
989 | 01e7f188 | Markus Armbruster | qfloat_get_double(qobject_to_qfloat(obj))); |
990 | 01e7f188 | Markus Armbruster | assert(n < sizeof(buf));
|
991 | 01e7f188 | Markus Armbruster | value = buf; |
992 | 01e7f188 | Markus Armbruster | break;
|
993 | 01e7f188 | Markus Armbruster | case QTYPE_QBOOL:
|
994 | d35215f8 | Blue Swirl | pstrcpy(buf, sizeof(buf),
|
995 | d35215f8 | Blue Swirl | qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off"); |
996 | 01e7f188 | Markus Armbruster | value = buf; |
997 | 01e7f188 | Markus Armbruster | break;
|
998 | 01e7f188 | Markus Armbruster | default:
|
999 | 01e7f188 | Markus Armbruster | return;
|
1000 | 01e7f188 | Markus Armbruster | } |
1001 | 4e89978e | Luiz Capitulino | |
1002 | 4e89978e | Luiz Capitulino | qemu_opt_set_err(state->opts, key, value, state->errp); |
1003 | 01e7f188 | Markus Armbruster | } |
1004 | 01e7f188 | Markus Armbruster | |
1005 | 01e7f188 | Markus Armbruster | /*
|
1006 | 01e7f188 | Markus Armbruster | * Create QemuOpts from a QDict.
|
1007 | 01e7f188 | Markus Armbruster | * Use value of key "id" as ID if it exists and is a QString.
|
1008 | 01e7f188 | Markus Armbruster | * Only QStrings, QInts, QFloats and QBools are copied. Entries with
|
1009 | 01e7f188 | Markus Armbruster | * other types are silently ignored.
|
1010 | 01e7f188 | Markus Armbruster | */
|
1011 | 4e89978e | Luiz Capitulino | QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
|
1012 | 4e89978e | Luiz Capitulino | Error **errp) |
1013 | 01e7f188 | Markus Armbruster | { |
1014 | 4e89978e | Luiz Capitulino | OptsFromQDictState state; |
1015 | 8be7e7e4 | Luiz Capitulino | Error *local_err = NULL;
|
1016 | 4e89978e | Luiz Capitulino | QemuOpts *opts; |
1017 | 01e7f188 | Markus Armbruster | |
1018 | 8be7e7e4 | Luiz Capitulino | opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1, |
1019 | 8be7e7e4 | Luiz Capitulino | &local_err); |
1020 | 8be7e7e4 | Luiz Capitulino | if (error_is_set(&local_err)) {
|
1021 | 4e89978e | Luiz Capitulino | error_propagate(errp, local_err); |
1022 | 01e7f188 | Markus Armbruster | return NULL; |
1023 | 8be7e7e4 | Luiz Capitulino | } |
1024 | 01e7f188 | Markus Armbruster | |
1025 | 8be7e7e4 | Luiz Capitulino | assert(opts != NULL);
|
1026 | 4e89978e | Luiz Capitulino | |
1027 | 4e89978e | Luiz Capitulino | state.errp = &local_err; |
1028 | 4e89978e | Luiz Capitulino | state.opts = opts; |
1029 | 4e89978e | Luiz Capitulino | qdict_iter(qdict, qemu_opts_from_qdict_1, &state); |
1030 | 4e89978e | Luiz Capitulino | if (error_is_set(&local_err)) {
|
1031 | 4e89978e | Luiz Capitulino | error_propagate(errp, local_err); |
1032 | 4e89978e | Luiz Capitulino | qemu_opts_del(opts); |
1033 | 4e89978e | Luiz Capitulino | return NULL; |
1034 | 4e89978e | Luiz Capitulino | } |
1035 | 4e89978e | Luiz Capitulino | |
1036 | 01e7f188 | Markus Armbruster | return opts;
|
1037 | 01e7f188 | Markus Armbruster | } |
1038 | 01e7f188 | Markus Armbruster | |
1039 | 01e7f188 | Markus Armbruster | /*
|
1040 | 01e7f188 | Markus Armbruster | * Convert from QemuOpts to QDict.
|
1041 | 01e7f188 | Markus Armbruster | * The QDict values are of type QString.
|
1042 | 01e7f188 | Markus Armbruster | * TODO We'll want to use types appropriate for opt->desc->type, but
|
1043 | 01e7f188 | Markus Armbruster | * this is enough for now.
|
1044 | 01e7f188 | Markus Armbruster | */
|
1045 | 01e7f188 | Markus Armbruster | QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict) |
1046 | 01e7f188 | Markus Armbruster | { |
1047 | 01e7f188 | Markus Armbruster | QemuOpt *opt; |
1048 | 01e7f188 | Markus Armbruster | QObject *val; |
1049 | 01e7f188 | Markus Armbruster | |
1050 | 01e7f188 | Markus Armbruster | if (!qdict) {
|
1051 | 01e7f188 | Markus Armbruster | qdict = qdict_new(); |
1052 | 01e7f188 | Markus Armbruster | } |
1053 | 01e7f188 | Markus Armbruster | if (opts->id) {
|
1054 | 01e7f188 | Markus Armbruster | qdict_put(qdict, "id", qstring_from_str(opts->id));
|
1055 | 01e7f188 | Markus Armbruster | } |
1056 | 01e7f188 | Markus Armbruster | QTAILQ_FOREACH(opt, &opts->head, next) { |
1057 | 01e7f188 | Markus Armbruster | val = QOBJECT(qstring_from_str(opt->str)); |
1058 | 01e7f188 | Markus Armbruster | qdict_put_obj(qdict, opt->name, val); |
1059 | 01e7f188 | Markus Armbruster | } |
1060 | 01e7f188 | Markus Armbruster | return qdict;
|
1061 | 01e7f188 | Markus Armbruster | } |
1062 | 01e7f188 | Markus Armbruster | |
1063 | 5dc519ef | Mark McLoughlin | /* Validate parsed opts against descriptions where no
|
1064 | 5dc519ef | Mark McLoughlin | * descriptions were provided in the QemuOptsList.
|
1065 | 5dc519ef | Mark McLoughlin | */
|
1066 | 29952866 | Luiz Capitulino | void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp) |
1067 | 5dc519ef | Mark McLoughlin | { |
1068 | 5dc519ef | Mark McLoughlin | QemuOpt *opt; |
1069 | 6c519404 | Luiz Capitulino | Error *local_err = NULL;
|
1070 | 5dc519ef | Mark McLoughlin | |
1071 | 5dc519ef | Mark McLoughlin | assert(opts->list->desc[0].name == NULL); |
1072 | 5dc519ef | Mark McLoughlin | |
1073 | 5dc519ef | Mark McLoughlin | QTAILQ_FOREACH(opt, &opts->head, next) { |
1074 | 5dc519ef | Mark McLoughlin | int i;
|
1075 | 5dc519ef | Mark McLoughlin | |
1076 | 5dc519ef | Mark McLoughlin | for (i = 0; desc[i].name != NULL; i++) { |
1077 | 5dc519ef | Mark McLoughlin | if (strcmp(desc[i].name, opt->name) == 0) { |
1078 | 5dc519ef | Mark McLoughlin | break;
|
1079 | 5dc519ef | Mark McLoughlin | } |
1080 | 5dc519ef | Mark McLoughlin | } |
1081 | 5dc519ef | Mark McLoughlin | if (desc[i].name == NULL) { |
1082 | 29952866 | Luiz Capitulino | error_set(errp, QERR_INVALID_PARAMETER, opt->name); |
1083 | 29952866 | Luiz Capitulino | return;
|
1084 | 5dc519ef | Mark McLoughlin | } |
1085 | 5dc519ef | Mark McLoughlin | |
1086 | 5dc519ef | Mark McLoughlin | opt->desc = &desc[i]; |
1087 | 5dc519ef | Mark McLoughlin | |
1088 | 6c519404 | Luiz Capitulino | qemu_opt_parse(opt, &local_err); |
1089 | 6c519404 | Luiz Capitulino | if (error_is_set(&local_err)) {
|
1090 | 29952866 | Luiz Capitulino | error_propagate(errp, local_err); |
1091 | 29952866 | Luiz Capitulino | return;
|
1092 | 5dc519ef | Mark McLoughlin | } |
1093 | 5dc519ef | Mark McLoughlin | } |
1094 | 5dc519ef | Mark McLoughlin | } |
1095 | 5dc519ef | Mark McLoughlin | |
1096 | e27c88fe | Gerd Hoffmann | int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque, |
1097 | e27c88fe | Gerd Hoffmann | int abort_on_failure)
|
1098 | e27c88fe | Gerd Hoffmann | { |
1099 | 827b0813 | Markus Armbruster | Location loc; |
1100 | e27c88fe | Gerd Hoffmann | QemuOpts *opts; |
1101 | e27c88fe | Gerd Hoffmann | int rc = 0; |
1102 | e27c88fe | Gerd Hoffmann | |
1103 | 827b0813 | Markus Armbruster | loc_push_none(&loc); |
1104 | 72cf2d4f | Blue Swirl | QTAILQ_FOREACH(opts, &list->head, next) { |
1105 | 827b0813 | Markus Armbruster | loc_restore(&opts->loc); |
1106 | 4a2594dd | Markus Armbruster | rc |= func(opts, opaque); |
1107 | e27c88fe | Gerd Hoffmann | if (abort_on_failure && rc != 0) |
1108 | e27c88fe | Gerd Hoffmann | break;
|
1109 | e27c88fe | Gerd Hoffmann | } |
1110 | 827b0813 | Markus Armbruster | loc_pop(&loc); |
1111 | e27c88fe | Gerd Hoffmann | return rc;
|
1112 | e27c88fe | Gerd Hoffmann | } |