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