]> git.proxmox.com Git - mirror_qemu.git/blame - qobject/block-qdict.c
block: Make remaining uses of qobject input visitor more robust
[mirror_qemu.git] / qobject / block-qdict.c
CommitLineData
0bcc8e5b
MA
1/*
2 * Special QDict functions used by the block layer
3 *
4 * Copyright (c) 2013-2018 Red Hat, Inc.
5 *
6 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
7 * See the COPYING.LIB file in the top-level directory.
8 */
9
10#include "qemu/osdep.h"
11#include "block/qdict.h"
e5af0da1 12#include "qapi/qmp/qbool.h"
0bcc8e5b 13#include "qapi/qmp/qlist.h"
e5af0da1
MA
14#include "qapi/qmp/qnum.h"
15#include "qapi/qmp/qstring.h"
af91062e 16#include "qapi/qobject-input-visitor.h"
0bcc8e5b
MA
17#include "qemu/cutils.h"
18#include "qapi/error.h"
19
20/**
21 * qdict_copy_default(): If no entry mapped by 'key' exists in 'dst' yet, the
22 * value of 'key' in 'src' is copied there (and the refcount increased
23 * accordingly).
24 */
25void qdict_copy_default(QDict *dst, QDict *src, const char *key)
26{
27 QObject *val;
28
29 if (qdict_haskey(dst, key)) {
30 return;
31 }
32
33 val = qdict_get(src, key);
34 if (val) {
35 qdict_put_obj(dst, key, qobject_ref(val));
36 }
37}
38
39/**
40 * qdict_set_default_str(): If no entry mapped by 'key' exists in 'dst' yet, a
41 * new QString initialised by 'val' is put there.
42 */
43void qdict_set_default_str(QDict *dst, const char *key, const char *val)
44{
45 if (qdict_haskey(dst, key)) {
46 return;
47 }
48
49 qdict_put_str(dst, key, val);
50}
51
52static void qdict_flatten_qdict(QDict *qdict, QDict *target,
53 const char *prefix);
54
55static void qdict_flatten_qlist(QList *qlist, QDict *target, const char *prefix)
56{
57 QObject *value;
58 const QListEntry *entry;
59 char *new_key;
60 int i;
61
62 /* This function is never called with prefix == NULL, i.e., it is always
63 * called from within qdict_flatten_q(list|dict)(). Therefore, it does not
64 * need to remove list entries during the iteration (the whole list will be
65 * deleted eventually anyway from qdict_flatten_qdict()). */
66 assert(prefix);
67
68 entry = qlist_first(qlist);
69
70 for (i = 0; entry; entry = qlist_next(entry), i++) {
71 value = qlist_entry_obj(entry);
72 new_key = g_strdup_printf("%s.%i", prefix, i);
73
74 if (qobject_type(value) == QTYPE_QDICT) {
75 qdict_flatten_qdict(qobject_to(QDict, value), target, new_key);
76 } else if (qobject_type(value) == QTYPE_QLIST) {
77 qdict_flatten_qlist(qobject_to(QList, value), target, new_key);
78 } else {
79 /* All other types are moved to the target unchanged. */
80 qdict_put_obj(target, new_key, qobject_ref(value));
81 }
82
83 g_free(new_key);
84 }
85}
86
87static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix)
88{
89 QObject *value;
90 const QDictEntry *entry, *next;
91 char *new_key;
92 bool delete;
93
94 entry = qdict_first(qdict);
95
96 while (entry != NULL) {
97
98 next = qdict_next(qdict, entry);
99 value = qdict_entry_value(entry);
100 new_key = NULL;
101 delete = false;
102
103 if (prefix) {
104 new_key = g_strdup_printf("%s.%s", prefix, entry->key);
105 }
106
107 if (qobject_type(value) == QTYPE_QDICT) {
108 /* Entries of QDicts are processed recursively, the QDict object
109 * itself disappears. */
110 qdict_flatten_qdict(qobject_to(QDict, value), target,
111 new_key ? new_key : entry->key);
112 delete = true;
113 } else if (qobject_type(value) == QTYPE_QLIST) {
114 qdict_flatten_qlist(qobject_to(QList, value), target,
115 new_key ? new_key : entry->key);
116 delete = true;
117 } else if (prefix) {
118 /* All other objects are moved to the target unchanged. */
119 qdict_put_obj(target, new_key, qobject_ref(value));
120 delete = true;
121 }
122
123 g_free(new_key);
124
125 if (delete) {
126 qdict_del(qdict, entry->key);
127
128 /* Restart loop after modifying the iterated QDict */
129 entry = qdict_first(qdict);
130 continue;
131 }
132
133 entry = next;
134 }
135}
136
137/**
138 * qdict_flatten(): For each nested QDict with key x, all fields with key y
139 * are moved to this QDict and their key is renamed to "x.y". For each nested
140 * QList with key x, the field at index y is moved to this QDict with the key
141 * "x.y" (i.e., the reverse of what qdict_array_split() does).
142 * This operation is applied recursively for nested QDicts and QLists.
143 */
144void qdict_flatten(QDict *qdict)
145{
146 qdict_flatten_qdict(qdict, qdict, NULL);
147}
148
149/* extract all the src QDict entries starting by start into dst */
150void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start)
151
152{
153 const QDictEntry *entry, *next;
154 const char *p;
155
156 *dst = qdict_new();
157 entry = qdict_first(src);
158
159 while (entry != NULL) {
160 next = qdict_next(src, entry);
161 if (strstart(entry->key, start, &p)) {
162 qdict_put_obj(*dst, p, qobject_ref(entry->value));
163 qdict_del(src, entry->key);
164 }
165 entry = next;
166 }
167}
168
169static int qdict_count_prefixed_entries(const QDict *src, const char *start)
170{
171 const QDictEntry *entry;
172 int count = 0;
173
174 for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) {
175 if (strstart(entry->key, start, NULL)) {
176 if (count == INT_MAX) {
177 return -ERANGE;
178 }
179 count++;
180 }
181 }
182
183 return count;
184}
185
186/**
187 * qdict_array_split(): This function moves array-like elements of a QDict into
188 * a new QList. Every entry in the original QDict with a key "%u" or one
189 * prefixed "%u.", where %u designates an unsigned integer starting at 0 and
190 * incrementally counting up, will be moved to a new QDict at index %u in the
191 * output QList with the key prefix removed, if that prefix is "%u.". If the
192 * whole key is just "%u", the whole QObject will be moved unchanged without
193 * creating a new QDict. The function terminates when there is no entry in the
194 * QDict with a prefix directly (incrementally) following the last one; it also
195 * returns if there are both entries with "%u" and "%u." for the same index %u.
196 * Example: {"0.a": 42, "0.b": 23, "1.x": 0, "4.y": 1, "o.o": 7, "2": 66}
197 * (or {"1.x": 0, "4.y": 1, "0.a": 42, "o.o": 7, "0.b": 23, "2": 66})
198 * => [{"a": 42, "b": 23}, {"x": 0}, 66]
199 * and {"4.y": 1, "o.o": 7} (remainder of the old QDict)
200 */
201void qdict_array_split(QDict *src, QList **dst)
202{
203 unsigned i;
204
205 *dst = qlist_new();
206
207 for (i = 0; i < UINT_MAX; i++) {
208 QObject *subqobj;
209 bool is_subqdict;
210 QDict *subqdict;
211 char indexstr[32], prefix[32];
212 size_t snprintf_ret;
213
214 snprintf_ret = snprintf(indexstr, 32, "%u", i);
215 assert(snprintf_ret < 32);
216
217 subqobj = qdict_get(src, indexstr);
218
219 snprintf_ret = snprintf(prefix, 32, "%u.", i);
220 assert(snprintf_ret < 32);
221
222 /* Overflow is the same as positive non-zero results */
223 is_subqdict = qdict_count_prefixed_entries(src, prefix);
224
225 /*
226 * There may be either a single subordinate object (named
227 * "%u") or multiple objects (each with a key prefixed "%u."),
228 * but not both.
229 */
230 if (!subqobj == !is_subqdict) {
231 break;
232 }
233
234 if (is_subqdict) {
235 qdict_extract_subqdict(src, &subqdict, prefix);
236 assert(qdict_size(subqdict) > 0);
237 } else {
238 qobject_ref(subqobj);
239 qdict_del(src, indexstr);
240 }
241
242 qlist_append_obj(*dst, subqobj ?: QOBJECT(subqdict));
243 }
244}
245
246/**
247 * qdict_split_flat_key:
248 * @key: the key string to split
249 * @prefix: non-NULL pointer to hold extracted prefix
250 * @suffix: non-NULL pointer to remaining suffix
251 *
252 * Given a flattened key such as 'foo.0.bar', split it into two parts
253 * at the first '.' separator. Allows double dot ('..') to escape the
254 * normal separator.
255 *
256 * e.g.
257 * 'foo.0.bar' -> prefix='foo' and suffix='0.bar'
258 * 'foo..0.bar' -> prefix='foo.0' and suffix='bar'
259 *
260 * The '..' sequence will be unescaped in the returned 'prefix'
261 * string. The 'suffix' string will be left in escaped format, so it
262 * can be fed back into the qdict_split_flat_key() key as the input
263 * later.
264 *
265 * The caller is responsible for freeing the string returned in @prefix
266 * using g_free().
267 */
268static void qdict_split_flat_key(const char *key, char **prefix,
269 const char **suffix)
270{
271 const char *separator;
272 size_t i, j;
273
274 /* Find first '.' separator, but if there is a pair '..'
275 * that acts as an escape, so skip over '..' */
276 separator = NULL;
277 do {
278 if (separator) {
279 separator += 2;
280 } else {
281 separator = key;
282 }
283 separator = strchr(separator, '.');
284 } while (separator && separator[1] == '.');
285
286 if (separator) {
287 *prefix = g_strndup(key, separator - key);
288 *suffix = separator + 1;
289 } else {
290 *prefix = g_strdup(key);
291 *suffix = NULL;
292 }
293
294 /* Unescape the '..' sequence into '.' */
295 for (i = 0, j = 0; (*prefix)[i] != '\0'; i++, j++) {
296 if ((*prefix)[i] == '.') {
297 assert((*prefix)[i + 1] == '.');
298 i++;
299 }
300 (*prefix)[j] = (*prefix)[i];
301 }
302 (*prefix)[j] = '\0';
303}
304
305/**
306 * qdict_is_list:
307 * @maybe_list: dict to check if keys represent list elements.
308 *
309 * Determine whether all keys in @maybe_list are valid list elements.
310 * If @maybe_list is non-zero in length and all the keys look like
311 * valid list indexes, this will return 1. If @maybe_list is zero
312 * length or all keys are non-numeric then it will return 0 to indicate
313 * it is a normal qdict. If there is a mix of numeric and non-numeric
314 * keys, or the list indexes are non-contiguous, an error is reported.
315 *
316 * Returns: 1 if a valid list, 0 if a dict, -1 on error
317 */
318static int qdict_is_list(QDict *maybe_list, Error **errp)
319{
320 const QDictEntry *ent;
321 ssize_t len = 0;
322 ssize_t max = -1;
323 int is_list = -1;
324 int64_t val;
325
326 for (ent = qdict_first(maybe_list); ent != NULL;
327 ent = qdict_next(maybe_list, ent)) {
328
329 if (qemu_strtoi64(ent->key, NULL, 10, &val) == 0) {
330 if (is_list == -1) {
331 is_list = 1;
332 } else if (!is_list) {
333 error_setg(errp,
334 "Cannot mix list and non-list keys");
335 return -1;
336 }
337 len++;
338 if (val > max) {
339 max = val;
340 }
341 } else {
342 if (is_list == -1) {
343 is_list = 0;
344 } else if (is_list) {
345 error_setg(errp,
346 "Cannot mix list and non-list keys");
347 return -1;
348 }
349 }
350 }
351
352 if (is_list == -1) {
353 assert(!qdict_size(maybe_list));
354 is_list = 0;
355 }
356
357 /* NB this isn't a perfect check - e.g. it won't catch
358 * a list containing '1', '+1', '01', '3', but that
359 * does not matter - we've still proved that the
360 * input is a list. It is up the caller to do a
361 * stricter check if desired */
362 if (len != (max + 1)) {
363 error_setg(errp, "List indices are not contiguous, "
364 "saw %zd elements but %zd largest index",
365 len, max);
366 return -1;
367 }
368
369 return is_list;
370}
371
372/**
373 * qdict_crumple:
374 * @src: the original flat dictionary (only scalar values) to crumple
375 *
376 * Takes a flat dictionary whose keys use '.' separator to indicate
377 * nesting, and values are scalars, and crumples it into a nested
378 * structure.
379 *
380 * To include a literal '.' in a key name, it must be escaped as '..'
381 *
382 * For example, an input of:
383 *
384 * { 'foo.0.bar': 'one', 'foo.0.wizz': '1',
385 * 'foo.1.bar': 'two', 'foo.1.wizz': '2' }
386 *
387 * will result in an output of:
388 *
389 * {
390 * 'foo': [
391 * { 'bar': 'one', 'wizz': '1' },
392 * { 'bar': 'two', 'wizz': '2' }
393 * ],
394 * }
395 *
396 * The following scenarios in the input dict will result in an
397 * error being returned:
398 *
399 * - Any values in @src are non-scalar types
400 * - If keys in @src imply that a particular level is both a
401 * list and a dict. e.g., "foo.0.bar" and "foo.eek.bar".
402 * - If keys in @src imply that a particular level is a list,
403 * but the indices are non-contiguous. e.g. "foo.0.bar" and
404 * "foo.2.bar" without any "foo.1.bar" present.
405 * - If keys in @src represent list indexes, but are not in
406 * the "%zu" format. e.g. "foo.+0.bar"
407 *
408 * Returns: either a QDict or QList for the nested data structure, or NULL
409 * on error
410 */
411QObject *qdict_crumple(const QDict *src, Error **errp)
412{
413 const QDictEntry *ent;
414 QDict *two_level, *multi_level = NULL;
415 QObject *dst = NULL, *child;
416 size_t i;
417 char *prefix = NULL;
418 const char *suffix = NULL;
419 int is_list;
420
421 two_level = qdict_new();
422
423 /* Step 1: split our totally flat dict into a two level dict */
424 for (ent = qdict_first(src); ent != NULL; ent = qdict_next(src, ent)) {
425 if (qobject_type(ent->value) == QTYPE_QDICT ||
426 qobject_type(ent->value) == QTYPE_QLIST) {
427 error_setg(errp, "Value %s is not a scalar",
428 ent->key);
429 goto error;
430 }
431
432 qdict_split_flat_key(ent->key, &prefix, &suffix);
433
434 child = qdict_get(two_level, prefix);
435 if (suffix) {
436 QDict *child_dict = qobject_to(QDict, child);
437 if (!child_dict) {
438 if (child) {
439 error_setg(errp, "Key %s prefix is already set as a scalar",
440 prefix);
441 goto error;
442 }
443
444 child_dict = qdict_new();
445 qdict_put_obj(two_level, prefix, QOBJECT(child_dict));
446 }
447
448 qdict_put_obj(child_dict, suffix, qobject_ref(ent->value));
449 } else {
450 if (child) {
451 error_setg(errp, "Key %s prefix is already set as a dict",
452 prefix);
453 goto error;
454 }
455 qdict_put_obj(two_level, prefix, qobject_ref(ent->value));
456 }
457
458 g_free(prefix);
459 prefix = NULL;
460 }
461
462 /* Step 2: optionally process the two level dict recursively
463 * into a multi-level dict */
464 multi_level = qdict_new();
465 for (ent = qdict_first(two_level); ent != NULL;
466 ent = qdict_next(two_level, ent)) {
467 QDict *dict = qobject_to(QDict, ent->value);
468 if (dict) {
469 child = qdict_crumple(dict, errp);
470 if (!child) {
471 goto error;
472 }
473
474 qdict_put_obj(multi_level, ent->key, child);
475 } else {
476 qdict_put_obj(multi_level, ent->key, qobject_ref(ent->value));
477 }
478 }
479 qobject_unref(two_level);
480 two_level = NULL;
481
482 /* Step 3: detect if we need to turn our dict into list */
483 is_list = qdict_is_list(multi_level, errp);
484 if (is_list < 0) {
485 goto error;
486 }
487
488 if (is_list) {
489 dst = QOBJECT(qlist_new());
490
491 for (i = 0; i < qdict_size(multi_level); i++) {
492 char *key = g_strdup_printf("%zu", i);
493
494 child = qdict_get(multi_level, key);
495 g_free(key);
496
497 if (!child) {
498 error_setg(errp, "Missing list index %zu", i);
499 goto error;
500 }
501
502 qlist_append_obj(qobject_to(QList, dst), qobject_ref(child));
503 }
504 qobject_unref(multi_level);
505 multi_level = NULL;
506 } else {
507 dst = QOBJECT(multi_level);
508 }
509
510 return dst;
511
512 error:
513 g_free(prefix);
514 qobject_unref(multi_level);
515 qobject_unref(two_level);
516 qobject_unref(dst);
517 return NULL;
518}
519
e5af0da1
MA
520/**
521 * qdict_crumple_for_keyval_qiv:
522 * @src: the flat dictionary (only scalar values) to crumple
523 * @errp: location to store error
524 *
525 * Like qdict_crumple(), but additionally transforms scalar values so
526 * the result can be passed to qobject_input_visitor_new_keyval().
527 *
528 * The block subsystem uses this function to prepare its flat QDict
529 * with possibly confused scalar types for a visit. It should not be
530 * used for anything else, and it should go away once the block
531 * subsystem has been cleaned up.
532 */
af91062e 533static QObject *qdict_crumple_for_keyval_qiv(QDict *src, Error **errp)
e5af0da1
MA
534{
535 QDict *tmp = NULL;
536 char *buf;
537 const char *s;
538 const QDictEntry *ent;
539 QObject *dst;
540
541 for (ent = qdict_first(src); ent; ent = qdict_next(src, ent)) {
542 buf = NULL;
543 switch (qobject_type(ent->value)) {
544 case QTYPE_QNULL:
545 case QTYPE_QSTRING:
546 continue;
547 case QTYPE_QNUM:
548 s = buf = qnum_to_string(qobject_to(QNum, ent->value));
549 break;
550 case QTYPE_QDICT:
551 case QTYPE_QLIST:
552 /* @src isn't flat; qdict_crumple() will fail */
553 continue;
554 case QTYPE_QBOOL:
555 s = qbool_get_bool(qobject_to(QBool, ent->value))
556 ? "on" : "off";
557 break;
558 default:
559 abort();
560 }
561
562 if (!tmp) {
563 tmp = qdict_clone_shallow(src);
564 }
565 qdict_put(tmp, ent->key, qstring_from_str(s));
566 g_free(buf);
567 }
568
569 dst = qdict_crumple(tmp ?: src, errp);
570 qobject_unref(tmp);
571 return dst;
572}
573
0bcc8e5b
MA
574/**
575 * qdict_array_entries(): Returns the number of direct array entries if the
576 * sub-QDict of src specified by the prefix in subqdict (or src itself for
577 * prefix == "") is valid as an array, i.e. the length of the created list if
578 * the sub-QDict would become empty after calling qdict_array_split() on it. If
579 * the array is not valid, -EINVAL is returned.
580 */
581int qdict_array_entries(QDict *src, const char *subqdict)
582{
583 const QDictEntry *entry;
584 unsigned i;
585 unsigned entries = 0;
586 size_t subqdict_len = strlen(subqdict);
587
588 assert(!subqdict_len || subqdict[subqdict_len - 1] == '.');
589
590 /* qdict_array_split() loops until UINT_MAX, but as we want to return
591 * negative errors, we only have a signed return value here. Any additional
592 * entries will lead to -EINVAL. */
593 for (i = 0; i < INT_MAX; i++) {
594 QObject *subqobj;
595 int subqdict_entries;
596 char *prefix = g_strdup_printf("%s%u.", subqdict, i);
597
598 subqdict_entries = qdict_count_prefixed_entries(src, prefix);
599
600 /* Remove ending "." */
601 prefix[strlen(prefix) - 1] = 0;
602 subqobj = qdict_get(src, prefix);
603
604 g_free(prefix);
605
606 if (subqdict_entries < 0) {
607 return subqdict_entries;
608 }
609
610 /* There may be either a single subordinate object (named "%u") or
611 * multiple objects (each with a key prefixed "%u."), but not both. */
612 if (subqobj && subqdict_entries) {
613 return -EINVAL;
614 } else if (!subqobj && !subqdict_entries) {
615 break;
616 }
617
618 entries += subqdict_entries ? subqdict_entries : 1;
619 }
620
621 /* Consider everything handled that isn't part of the given sub-QDict */
622 for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) {
623 if (!strstart(qdict_entry_key(entry), subqdict, NULL)) {
624 entries++;
625 }
626 }
627
628 /* Anything left in the sub-QDict that wasn't handled? */
629 if (qdict_size(src) != entries) {
630 return -EINVAL;
631 }
632
633 return i;
634}
635
636/**
637 * qdict_join(): Absorb the src QDict into the dest QDict, that is, move all
638 * elements from src to dest.
639 *
640 * If an element from src has a key already present in dest, it will not be
641 * moved unless overwrite is true.
642 *
643 * If overwrite is true, the conflicting values in dest will be discarded and
644 * replaced by the corresponding values from src.
645 *
646 * Therefore, with overwrite being true, the src QDict will always be empty when
647 * this function returns. If overwrite is false, the src QDict will be empty
648 * iff there were no conflicts.
649 */
650void qdict_join(QDict *dest, QDict *src, bool overwrite)
651{
652 const QDictEntry *entry, *next;
653
654 entry = qdict_first(src);
655 while (entry) {
656 next = qdict_next(src, entry);
657
658 if (overwrite || !qdict_haskey(dest, entry->key)) {
659 qdict_put_obj(dest, entry->key, qobject_ref(entry->value));
660 qdict_del(src, entry->key);
661 }
662
663 entry = next;
664 }
665}
666
667/**
668 * qdict_rename_keys(): Rename keys in qdict according to the replacements
669 * specified in the array renames. The array must be terminated by an entry
670 * with from = NULL.
671 *
672 * The renames are performed individually in the order of the array, so entries
673 * may be renamed multiple times and may or may not conflict depending on the
674 * order of the renames array.
675 *
676 * Returns true for success, false in error cases.
677 */
678bool qdict_rename_keys(QDict *qdict, const QDictRenames *renames, Error **errp)
679{
680 QObject *qobj;
681
682 while (renames->from) {
683 if (qdict_haskey(qdict, renames->from)) {
684 if (qdict_haskey(qdict, renames->to)) {
685 error_setg(errp, "'%s' and its alias '%s' can't be used at the "
686 "same time", renames->to, renames->from);
687 return false;
688 }
689
690 qobj = qdict_get(qdict, renames->from);
691 qdict_put_obj(qdict, renames->to, qobject_ref(qobj));
692 qdict_del(qdict, renames->from);
693 }
694
695 renames++;
696 }
697 return true;
698}
af91062e
MA
699
700/*
701 * Create a QObject input visitor for flat @qdict with possibly
702 * confused scalar types.
703 *
704 * The block subsystem uses this function to visit its flat QDict with
705 * possibly confused scalar types. It should not be used for anything
706 * else, and it should go away once the block subsystem has been
707 * cleaned up.
708 */
709Visitor *qobject_input_visitor_new_flat_confused(QDict *qdict,
710 Error **errp)
711{
712 QObject *crumpled;
713 Visitor *v;
714
715 crumpled = qdict_crumple_for_keyval_qiv(qdict, errp);
716 if (!crumpled) {
717 return NULL;
718 }
719
720 v = qobject_input_visitor_new_keyval(crumpled);
721 qobject_unref(crumpled);
722 return v;
723}