summary refs log tree commit diff stats
path: root/util/qemu-config.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2012-12-20 15:58:44 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2013-01-12 18:42:50 +0100
commitbaacf04799ace72a9c735dd9306a1ceaf305e7cf (patch)
tree5e6750afe4b31c4343f9dd4bc07827cbdcb51466 /util/qemu-config.c
parentf157ebba2de4a6225679e13cc1ce01ff5d147c76 (diff)
downloadfocaccia-qemu-baacf04799ace72a9c735dd9306a1ceaf305e7cf.tar.gz
focaccia-qemu-baacf04799ace72a9c735dd9306a1ceaf305e7cf.zip
build: move libqemuutil.a components to util/
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'util/qemu-config.c')
-rw-r--r--util/qemu-config.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/util/qemu-config.c b/util/qemu-config.c
new file mode 100644
index 0000000000..47c81f72d3
--- /dev/null
+++ b/util/qemu-config.c
@@ -0,0 +1,215 @@
+#include "qemu-common.h"
+#include "qemu/error-report.h"
+#include "qemu/option.h"
+#include "qemu/config-file.h"
+#include "hw/qdev.h"
+#include "qapi/error.h"
+
+static QemuOptsList *vm_config_groups[32];
+
+static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
+                               Error **errp)
+{
+    int i;
+
+    for (i = 0; lists[i] != NULL; i++) {
+        if (strcmp(lists[i]->name, group) == 0)
+            break;
+    }
+    if (lists[i] == NULL) {
+        error_set(errp, QERR_INVALID_OPTION_GROUP, group);
+    }
+    return lists[i];
+}
+
+QemuOptsList *qemu_find_opts(const char *group)
+{
+    QemuOptsList *ret;
+    Error *local_err = NULL;
+
+    ret = find_list(vm_config_groups, group, &local_err);
+    if (error_is_set(&local_err)) {
+        error_report("%s\n", error_get_pretty(local_err));
+        error_free(local_err);
+    }
+
+    return ret;
+}
+
+QemuOptsList *qemu_find_opts_err(const char *group, Error **errp)
+{
+    return find_list(vm_config_groups, group, errp);
+}
+
+void qemu_add_opts(QemuOptsList *list)
+{
+    int entries, i;
+
+    entries = ARRAY_SIZE(vm_config_groups);
+    entries--; /* keep list NULL terminated */
+    for (i = 0; i < entries; i++) {
+        if (vm_config_groups[i] == NULL) {
+            vm_config_groups[i] = list;
+            return;
+        }
+    }
+    fprintf(stderr, "ran out of space in vm_config_groups");
+    abort();
+}
+
+int qemu_set_option(const char *str)
+{
+    char group[64], id[64], arg[64];
+    QemuOptsList *list;
+    QemuOpts *opts;
+    int rc, offset;
+
+    rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
+    if (rc < 3 || str[offset] != '=') {
+        error_report("can't parse: \"%s\"", str);
+        return -1;
+    }
+
+    list = qemu_find_opts(group);
+    if (list == NULL) {
+        return -1;
+    }
+
+    opts = qemu_opts_find(list, id);
+    if (!opts) {
+        error_report("there is no %s \"%s\" defined",
+                     list->name, id);
+        return -1;
+    }
+
+    if (qemu_opt_set(opts, arg, str+offset+1) == -1) {
+        return -1;
+    }
+    return 0;
+}
+
+struct ConfigWriteData {
+    QemuOptsList *list;
+    FILE *fp;
+};
+
+static int config_write_opt(const char *name, const char *value, void *opaque)
+{
+    struct ConfigWriteData *data = opaque;
+
+    fprintf(data->fp, "  %s = \"%s\"\n", name, value);
+    return 0;
+}
+
+static int config_write_opts(QemuOpts *opts, void *opaque)
+{
+    struct ConfigWriteData *data = opaque;
+    const char *id = qemu_opts_id(opts);
+
+    if (id) {
+        fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id);
+    } else {
+        fprintf(data->fp, "[%s]\n", data->list->name);
+    }
+    qemu_opt_foreach(opts, config_write_opt, data, 0);
+    fprintf(data->fp, "\n");
+    return 0;
+}
+
+void qemu_config_write(FILE *fp)
+{
+    struct ConfigWriteData data = { .fp = fp };
+    QemuOptsList **lists = vm_config_groups;
+    int i;
+
+    fprintf(fp, "# qemu config file\n\n");
+    for (i = 0; lists[i] != NULL; i++) {
+        data.list = lists[i];
+        qemu_opts_foreach(data.list, config_write_opts, &data, 0);
+    }
+}
+
+int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
+{
+    char line[1024], group[64], id[64], arg[64], value[1024];
+    Location loc;
+    QemuOptsList *list = NULL;
+    Error *local_err = NULL;
+    QemuOpts *opts = NULL;
+    int res = -1, lno = 0;
+
+    loc_push_none(&loc);
+    while (fgets(line, sizeof(line), fp) != NULL) {
+        loc_set_file(fname, ++lno);
+        if (line[0] == '\n') {
+            /* skip empty lines */
+            continue;
+        }
+        if (line[0] == '#') {
+            /* comment */
+            continue;
+        }
+        if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
+            /* group with id */
+            list = find_list(lists, group, &local_err);
+            if (error_is_set(&local_err)) {
+                error_report("%s\n", error_get_pretty(local_err));
+                error_free(local_err);
+                goto out;
+            }
+            opts = qemu_opts_create(list, id, 1, NULL);
+            continue;
+        }
+        if (sscanf(line, "[%63[^]]]", group) == 1) {
+            /* group without id */
+            list = find_list(lists, group, &local_err);
+            if (error_is_set(&local_err)) {
+                error_report("%s\n", error_get_pretty(local_err));
+                error_free(local_err);
+                goto out;
+            }
+            opts = qemu_opts_create_nofail(list);
+            continue;
+        }
+        if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
+            /* arg = value */
+            if (opts == NULL) {
+                error_report("no group defined");
+                goto out;
+            }
+            if (qemu_opt_set(opts, arg, value) != 0) {
+                goto out;
+            }
+            continue;
+        }
+        error_report("parse error");
+        goto out;
+    }
+    if (ferror(fp)) {
+        error_report("error reading file");
+        goto out;
+    }
+    res = 0;
+out:
+    loc_pop(&loc);
+    return res;
+}
+
+int qemu_read_config_file(const char *filename)
+{
+    FILE *f = fopen(filename, "r");
+    int ret;
+
+    if (f == NULL) {
+        return -errno;
+    }
+
+    ret = qemu_config_parse(f, vm_config_groups, filename);
+    fclose(f);
+
+    if (ret == 0) {
+        return 0;
+    } else {
+        return -EINVAL;
+    }
+}