dcavalca / rpms / qemu

Forked from rpms/qemu 10 months ago
Clone

Blame 0003-qemu-config-parse-configuration-files-to-a-QDict.patch

Paolo Bonzini d9c8b5
From a0520e180e6f235b8a3a531b0756e45cbfe36e15 Mon Sep 17 00:00:00 2001
Paolo Bonzini d9c8b5
From: Paolo Bonzini <pbonzini@redhat.com>
Paolo Bonzini d9c8b5
Date: Tue, 18 May 2021 11:40:57 -0400
Paolo Bonzini d9c8b5
Subject: [PATCH 3/5] qemu-config: parse configuration files to a QDict
Paolo Bonzini d9c8b5
Paolo Bonzini d9c8b5
Change the parser to put the values into a QDict and pass them
Paolo Bonzini d9c8b5
to a callback.  qemu_config_parse's QemuOpts creation is
Paolo Bonzini d9c8b5
itself turned into a callback function.
Paolo Bonzini d9c8b5
Paolo Bonzini d9c8b5
This is useful for -readconfig to support keyval-based options;
Paolo Bonzini d9c8b5
getting a QDict from the parser removes a roundtrip from
Paolo Bonzini d9c8b5
QDict to QemuOpts and then back to QDict.
Paolo Bonzini d9c8b5
Paolo Bonzini d9c8b5
Unfortunately there is a disadvantage in that semantic errors will
Paolo Bonzini d9c8b5
point to the last line of the group, because the entries of the QDict
Paolo Bonzini d9c8b5
do not have a location attached.
Paolo Bonzini d9c8b5
Paolo Bonzini d9c8b5
Cc: Kevin Wolf <kwolf@redhat.com>
Paolo Bonzini d9c8b5
Cc: Markus Armbruster <armbru@redhat.com>
Paolo Bonzini d9c8b5
Cc: qemu-stable@nongnu.org
Paolo Bonzini d9c8b5
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Paolo Bonzini d9c8b5
Message-Id: <20210524105752.3318299-2-pbonzini@redhat.com>
Paolo Bonzini d9c8b5
---
Paolo Bonzini d9c8b5
 include/qemu/config-file.h |  7 ++-
Paolo Bonzini d9c8b5
 softmmu/vl.c               |  4 +-
Paolo Bonzini d9c8b5
 util/qemu-config.c         | 97 ++++++++++++++++++++++++++------------
Paolo Bonzini d9c8b5
 3 files changed, 75 insertions(+), 33 deletions(-)
Paolo Bonzini d9c8b5
Paolo Bonzini d9c8b5
diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h
Paolo Bonzini d9c8b5
index 0500b36..f605423 100644
Paolo Bonzini d9c8b5
--- a/include/qemu/config-file.h
Paolo Bonzini d9c8b5
+++ b/include/qemu/config-file.h
Paolo Bonzini d9c8b5
@@ -1,6 +1,8 @@
Paolo Bonzini d9c8b5
 #ifndef QEMU_CONFIG_FILE_H
Paolo Bonzini d9c8b5
 #define QEMU_CONFIG_FILE_H
Paolo Bonzini d9c8b5
 
Paolo Bonzini d9c8b5
+typedef void QEMUConfigCB(const char *group, QDict *qdict, void *opaque, Error **errp);
Paolo Bonzini d9c8b5
+
Paolo Bonzini d9c8b5
 void qemu_load_module_for_opts(const char *group);
Paolo Bonzini d9c8b5
 QemuOptsList *qemu_find_opts(const char *group);
Paolo Bonzini d9c8b5
 QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
Paolo Bonzini d9c8b5
@@ -14,7 +16,10 @@ void qemu_config_write(FILE *fp);
Paolo Bonzini d9c8b5
 int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname,
Paolo Bonzini d9c8b5
                       Error **errp);
Paolo Bonzini d9c8b5
 
Paolo Bonzini d9c8b5
-int qemu_read_config_file(const char *filename, Error **errp);
Paolo Bonzini d9c8b5
+/* A default callback for qemu_read_config_file().  */
Paolo Bonzini d9c8b5
+void qemu_config_do_parse(const char *group, QDict *qdict, void *opaque, Error **errp);
Paolo Bonzini d9c8b5
+
Paolo Bonzini d9c8b5
+int qemu_read_config_file(const char *filename, QEMUConfigCB *f, Error **errp);
Paolo Bonzini d9c8b5
 
Paolo Bonzini d9c8b5
 /* Parse QDict options as a replacement for a config file (allowing multiple
Paolo Bonzini d9c8b5
    enumerated (0..(n-1)) configuration "sections") */
Paolo Bonzini d9c8b5
diff --git a/softmmu/vl.c b/softmmu/vl.c
Paolo Bonzini d9c8b5
index 4641f08..da5042f 100644
Paolo Bonzini d9c8b5
--- a/softmmu/vl.c
Paolo Bonzini d9c8b5
+++ b/softmmu/vl.c
Paolo Bonzini d9c8b5
@@ -2119,7 +2119,7 @@ static void qemu_read_default_config_file(Error **errp)
Paolo Bonzini d9c8b5
     int ret;
Paolo Bonzini d9c8b5
     g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf");
Paolo Bonzini d9c8b5
 
Paolo Bonzini d9c8b5
-    ret = qemu_read_config_file(file, errp);
Paolo Bonzini d9c8b5
+    ret = qemu_read_config_file(file, qemu_config_do_parse, errp);
Paolo Bonzini d9c8b5
     if (ret < 0) {
Paolo Bonzini d9c8b5
         if (ret == -ENOENT) {
Paolo Bonzini d9c8b5
             error_free(*errp);
Paolo Bonzini d9c8b5
@@ -3385,7 +3385,7 @@ void qemu_init(int argc, char **argv, char **envp)
Paolo Bonzini d9c8b5
                 qemu_plugin_opt_parse(optarg, &plugin_list);
Paolo Bonzini d9c8b5
                 break;
Paolo Bonzini d9c8b5
             case QEMU_OPTION_readconfig:
Paolo Bonzini d9c8b5
-                qemu_read_config_file(optarg, &error_fatal);
Paolo Bonzini d9c8b5
+                qemu_read_config_file(optarg, qemu_config_do_parse, &error_fatal);
Paolo Bonzini d9c8b5
                 break;
Paolo Bonzini d9c8b5
             case QEMU_OPTION_spice:
Paolo Bonzini d9c8b5
                 olist = qemu_find_opts_err("spice", NULL);
Paolo Bonzini d9c8b5
diff --git a/util/qemu-config.c b/util/qemu-config.c
Paolo Bonzini d9c8b5
index 34974c4..f6eaff9 100644
Paolo Bonzini d9c8b5
--- a/util/qemu-config.c
Paolo Bonzini d9c8b5
+++ b/util/qemu-config.c
Paolo Bonzini d9c8b5
@@ -2,6 +2,7 @@
Paolo Bonzini d9c8b5
 #include "block/qdict.h" /* for qdict_extract_subqdict() */
Paolo Bonzini d9c8b5
 #include "qapi/error.h"
Paolo Bonzini d9c8b5
 #include "qapi/qapi-commands-misc.h"
Paolo Bonzini d9c8b5
+#include "qapi/qmp/qerror.h"
Paolo Bonzini d9c8b5
 #include "qapi/qmp/qdict.h"
Paolo Bonzini d9c8b5
 #include "qapi/qmp/qlist.h"
Paolo Bonzini d9c8b5
 #include "qemu/error-report.h"
Paolo Bonzini d9c8b5
@@ -351,19 +352,19 @@ void qemu_config_write(FILE *fp)
Paolo Bonzini d9c8b5
 }
Paolo Bonzini d9c8b5
 
Paolo Bonzini d9c8b5
 /* Returns number of config groups on success, -errno on error */
Paolo Bonzini d9c8b5
-int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp)
Paolo Bonzini d9c8b5
+static int qemu_config_foreach(FILE *fp, QEMUConfigCB *cb, void *opaque,
Paolo Bonzini d9c8b5
+                               const char *fname, Error **errp)
Paolo Bonzini d9c8b5
 {
Paolo Bonzini d9c8b5
-    char line[1024], group[64], id[64], arg[64], value[1024];
Paolo Bonzini d9c8b5
+    char line[1024], prev_group[64], group[64], arg[64], value[1024];
Paolo Bonzini d9c8b5
     Location loc;
Paolo Bonzini d9c8b5
-    QemuOptsList *list = NULL;
Paolo Bonzini d9c8b5
     Error *local_err = NULL;
Paolo Bonzini d9c8b5
-    QemuOpts *opts = NULL;
Paolo Bonzini d9c8b5
+    QDict *qdict = NULL;
Paolo Bonzini d9c8b5
     int res = -EINVAL, lno = 0;
Paolo Bonzini d9c8b5
     int count = 0;
Paolo Bonzini d9c8b5
 
Paolo Bonzini d9c8b5
     loc_push_none(&loc;;
Paolo Bonzini d9c8b5
     while (fgets(line, sizeof(line), fp) != NULL) {
Paolo Bonzini d9c8b5
-        loc_set_file(fname, ++lno);
Paolo Bonzini d9c8b5
+        ++lno;
Paolo Bonzini d9c8b5
         if (line[0] == '\n') {
Paolo Bonzini d9c8b5
             /* skip empty lines */
Paolo Bonzini d9c8b5
             continue;
Paolo Bonzini d9c8b5
@@ -372,39 +373,39 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error *
Paolo Bonzini d9c8b5
             /* comment */
Paolo Bonzini d9c8b5
             continue;
Paolo Bonzini d9c8b5
         }
Paolo Bonzini d9c8b5
-        if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
Paolo Bonzini d9c8b5
-            /* group with id */
Paolo Bonzini d9c8b5
-            list = find_list(lists, group, &local_err);
Paolo Bonzini d9c8b5
-            if (local_err) {
Paolo Bonzini d9c8b5
-                error_propagate(errp, local_err);
Paolo Bonzini d9c8b5
-                goto out;
Paolo Bonzini d9c8b5
+        if (line[0] == '[') {
Paolo Bonzini d9c8b5
+            QDict *prev = qdict;
Paolo Bonzini d9c8b5
+            if (sscanf(line, "[%63s \"%63[^\"]\"]", group, value) == 2) {
Paolo Bonzini d9c8b5
+                qdict = qdict_new();
Paolo Bonzini d9c8b5
+                qdict_put_str(qdict, "id", value);
Paolo Bonzini d9c8b5
+                count++;
Paolo Bonzini d9c8b5
+            } else if (sscanf(line, "[%63[^]]]", group) == 1) {
Paolo Bonzini d9c8b5
+                qdict = qdict_new();
Paolo Bonzini d9c8b5
+                count++;
Paolo Bonzini d9c8b5
             }
Paolo Bonzini d9c8b5
-            opts = qemu_opts_create(list, id, 1, NULL);
Paolo Bonzini d9c8b5
-            count++;
Paolo Bonzini d9c8b5
-            continue;
Paolo Bonzini d9c8b5
-        }
Paolo Bonzini d9c8b5
-        if (sscanf(line, "[%63[^]]]", group) == 1) {
Paolo Bonzini d9c8b5
-            /* group without id */
Paolo Bonzini d9c8b5
-            list = find_list(lists, group, &local_err);
Paolo Bonzini d9c8b5
-            if (local_err) {
Paolo Bonzini d9c8b5
-                error_propagate(errp, local_err);
Paolo Bonzini d9c8b5
-                goto out;
Paolo Bonzini d9c8b5
+            if (qdict != prev) {
Paolo Bonzini d9c8b5
+                if (prev) {
Paolo Bonzini d9c8b5
+                    cb(prev_group, prev, opaque, &local_err);
Paolo Bonzini d9c8b5
+                    qobject_unref(prev);
Paolo Bonzini d9c8b5
+                    if (local_err) {
Paolo Bonzini d9c8b5
+                        error_propagate(errp, local_err);
Paolo Bonzini d9c8b5
+                        goto out;
Paolo Bonzini d9c8b5
+                    }
Paolo Bonzini d9c8b5
+                }
Paolo Bonzini d9c8b5
+                strcpy(prev_group, group);
Paolo Bonzini d9c8b5
+                continue;
Paolo Bonzini d9c8b5
             }
Paolo Bonzini d9c8b5
-            opts = qemu_opts_create(list, NULL, 0, &error_abort);
Paolo Bonzini d9c8b5
-            count++;
Paolo Bonzini d9c8b5
-            continue;
Paolo Bonzini d9c8b5
         }
Paolo Bonzini d9c8b5
+        loc_set_file(fname, lno);
Paolo Bonzini d9c8b5
         value[0] = '\0';
Paolo Bonzini d9c8b5
         if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2 ||
Paolo Bonzini d9c8b5
             sscanf(line, " %63s = \"\"", arg) == 1) {
Paolo Bonzini d9c8b5
             /* arg = value */
Paolo Bonzini d9c8b5
-            if (opts == NULL) {
Paolo Bonzini d9c8b5
+            if (qdict == NULL) {
Paolo Bonzini d9c8b5
                 error_setg(errp, "no group defined");
Paolo Bonzini d9c8b5
                 goto out;
Paolo Bonzini d9c8b5
             }
Paolo Bonzini d9c8b5
-            if (!qemu_opt_set(opts, arg, value, errp)) {
Paolo Bonzini d9c8b5
-                goto out;
Paolo Bonzini d9c8b5
-            }
Paolo Bonzini d9c8b5
+            qdict_put_str(qdict, arg, value);
Paolo Bonzini d9c8b5
             continue;
Paolo Bonzini d9c8b5
         }
Paolo Bonzini d9c8b5
         error_setg(errp, "parse error");
Paolo Bonzini d9c8b5
@@ -417,11 +418,47 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error *
Paolo Bonzini d9c8b5
     }
Paolo Bonzini d9c8b5
     res = count;
Paolo Bonzini d9c8b5
 out:
Paolo Bonzini d9c8b5
+    if (qdict) {
Paolo Bonzini d9c8b5
+        cb(group, qdict, opaque, errp);
Paolo Bonzini d9c8b5
+        qobject_unref(qdict);
Paolo Bonzini d9c8b5
+    }
Paolo Bonzini d9c8b5
     loc_pop(&loc;;
Paolo Bonzini d9c8b5
     return res;
Paolo Bonzini d9c8b5
 }
Paolo Bonzini d9c8b5
 
Paolo Bonzini d9c8b5
-int qemu_read_config_file(const char *filename, Error **errp)
Paolo Bonzini d9c8b5
+void qemu_config_do_parse(const char *group, QDict *qdict, void *opaque, Error **errp)
Paolo Bonzini d9c8b5
+{
Paolo Bonzini d9c8b5
+    QemuOptsList **lists = opaque;
Paolo Bonzini d9c8b5
+    const char *id = qdict_get_try_str(qdict, "id");
Paolo Bonzini d9c8b5
+    QemuOptsList *list;
Paolo Bonzini d9c8b5
+    QemuOpts *opts;
Paolo Bonzini d9c8b5
+    const QDictEntry *unrecognized;
Paolo Bonzini d9c8b5
+
Paolo Bonzini d9c8b5
+    list = find_list(lists, group, errp);
Paolo Bonzini d9c8b5
+    if (!list) {
Paolo Bonzini d9c8b5
+        return;
Paolo Bonzini d9c8b5
+    }
Paolo Bonzini d9c8b5
+
Paolo Bonzini d9c8b5
+    opts = qemu_opts_create(list, id, 1, errp);
Paolo Bonzini d9c8b5
+    if (!opts) {
Paolo Bonzini d9c8b5
+        return;
Paolo Bonzini d9c8b5
+    }
Paolo Bonzini d9c8b5
+    if (!qemu_opts_absorb_qdict(opts, qdict, errp)) {
Paolo Bonzini d9c8b5
+        return;
Paolo Bonzini d9c8b5
+    }
Paolo Bonzini d9c8b5
+    unrecognized = qdict_first(qdict);
Paolo Bonzini d9c8b5
+    if (unrecognized) {
Paolo Bonzini d9c8b5
+        error_setg(errp, QERR_INVALID_PARAMETER, unrecognized->key);
Paolo Bonzini d9c8b5
+        qemu_opts_del(opts);
Paolo Bonzini d9c8b5
+    }
Paolo Bonzini d9c8b5
+}
Paolo Bonzini d9c8b5
+
Paolo Bonzini d9c8b5
+int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp)
Paolo Bonzini d9c8b5
+{
Paolo Bonzini d9c8b5
+    return qemu_config_foreach(fp, qemu_config_do_parse, lists, fname, errp);
Paolo Bonzini d9c8b5
+}
Paolo Bonzini d9c8b5
+
Paolo Bonzini d9c8b5
+int qemu_read_config_file(const char *filename, QEMUConfigCB *cb, Error **errp)
Paolo Bonzini d9c8b5
 {
Paolo Bonzini d9c8b5
     FILE *f = fopen(filename, "r");
Paolo Bonzini d9c8b5
     int ret;
Paolo Bonzini d9c8b5
@@ -431,7 +468,7 @@ int qemu_read_config_file(const char *filename, Error **errp)
Paolo Bonzini d9c8b5
         return -errno;
Paolo Bonzini d9c8b5
     }
Paolo Bonzini d9c8b5
 
Paolo Bonzini d9c8b5
-    ret = qemu_config_parse(f, vm_config_groups, filename, errp);
Paolo Bonzini d9c8b5
+    ret = qemu_config_foreach(f, cb, vm_config_groups, filename, errp);
Paolo Bonzini d9c8b5
     fclose(f);
Paolo Bonzini d9c8b5
     return ret;
Paolo Bonzini d9c8b5
 }
Paolo Bonzini d9c8b5
-- 
Paolo Bonzini d9c8b5
2.31.1
Paolo Bonzini d9c8b5