qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Anthony Liguori <aliguori@us.ibm.com>
To: qemu-devel@nongnu.org
Cc: Anthony Liguori <aliguori@us.ibm.com>,
	Eric Blake <eblake@redhat.com>,
	Eduardo Habkost <ehabkost@redhat.com>,
	Gerd Hoffman <kraxel@redhat.com>
Subject: [Qemu-devel] [PATCH 2/9] qemu-config: friends don't let friends use sscanf
Date: Mon, 19 Mar 2012 10:09:16 -0500	[thread overview]
Message-ID: <1332169763-30665-3-git-send-email-aliguori@us.ibm.com> (raw)
In-Reply-To: <1332169763-30665-1-git-send-email-aliguori@us.ibm.com>

The current qemu-config code uses a simple sscanf parser.  The use of scanf is
actually incorrect as scanf is incredibly hard to use correctly.  Moreover, it
introduces unnecessary strictness in terms of how whitespace is handled.

Fortunately, glib has a key value pair parser that will work very well for our
purposes.  Switch the code to use this.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 block/blkdebug.c |    9 +---
 qemu-config.c    |  141 ++++++++++++++++++++++++++++++------------------------
 qemu-config.h    |    2 +-
 3 files changed, 81 insertions(+), 71 deletions(-)

diff --git a/block/blkdebug.c b/block/blkdebug.c
index a251802..71f1cab 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -244,16 +244,10 @@ static int add_rule(QemuOpts *opts, void *opaque)
 
 static int read_config(BDRVBlkdebugState *s, const char *filename)
 {
-    FILE *f;
     int ret;
     struct add_rule_data d;
 
-    f = fopen(filename, "r");
-    if (f == NULL) {
-        return -errno;
-    }
-
-    ret = qemu_config_parse(f, config_groups, filename);
+    ret = qemu_config_parse(config_groups, filename);
     if (ret < 0) {
         goto fail;
     }
@@ -269,7 +263,6 @@ static int read_config(BDRVBlkdebugState *s, const char *filename)
 fail:
     qemu_opts_reset(&inject_error_opts);
     qemu_opts_reset(&set_state_opts);
-    fclose(f);
     return ret;
 }
 
diff --git a/qemu-config.c b/qemu-config.c
index be84a03..daf6557 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -757,80 +757,97 @@ void qemu_config_write(FILE *fp)
     }
 }
 
-int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
+int qemu_config_parse(QemuOptsList **lists, const char *filename)
 {
-    char line[1024], group[64], id[64], arg[64], value[1024];
-    Location loc;
-    QemuOptsList *list = 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;
+    GKeyFile *f;
+    GError *err = NULL;
+    gchar **groups;
+    gsize i, nb_groups = 0;
+
+    f = g_key_file_new();
+    if (!g_key_file_load_from_file(f, filename, 0, &err)) {
+        if (err->code == G_FILE_ERROR_NOENT) {
+            return 0;
         }
-        if (line[0] == '#') {
-            /* comment */
-            continue;
+        fprintf(stderr, "could not parse config: %s\n", err->message);
+        g_error_free(err);
+        return -EINVAL;
+    }
+
+    groups = g_key_file_get_groups(f, &nb_groups);
+    for (i = 0; i < nb_groups; i++) {
+        gchar **keys;
+        gchar *subkey = NULL;
+        gchar *group;
+        gsize j, nb_keys = 0;
+        char *ptr;
+        QemuOpts *opts;
+        QemuOptsList *list;
+
+        group = g_strdup(groups[i]);
+
+        ptr = strchr(group, '"');
+        if (ptr) {
+            *ptr = 0;
+            subkey = g_strdup(ptr + 1);
+            ptr = strchr(subkey, '"');
+            *ptr = 0;
+            g_strchomp(group);
         }
-        if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
-            /* group with id */
-            list = find_list(lists, group);
-            if (list == NULL)
-                goto out;
-            opts = qemu_opts_create(list, id, 1);
-            continue;
+            
+        list = find_list(lists, group);
+        if (list == NULL) {
+            break;
         }
-        if (sscanf(line, "[%63[^]]]", group) == 1) {
-            /* group without id */
-            list = find_list(lists, group);
-            if (list == NULL)
-                goto out;
+
+        if (subkey) {
+            opts = qemu_opts_create(list, subkey, 1);
+        } else {
             opts = qemu_opts_create(list, NULL, 0);
-            continue;
         }
-        if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
-            /* arg = value */
-            if (opts == NULL) {
-                error_report("no group defined");
-                goto out;
+
+        keys = g_key_file_get_keys(f, groups[i], &nb_keys, NULL);
+        for (j = 0; j < nb_keys; j++) {
+            gchar *value;
+            gsize len;
+
+            value = g_key_file_get_string(f, groups[i], keys[j], &err);
+            if (err) {
+                fprintf(stderr,
+                        "warning: failed to read key `%s' in section `%s': %s\n",
+                        keys[j], groups[i], err->message);
+                g_free(value);
+                g_error_free(err);
+                break;
             }
-            if (qemu_opt_set(opts, arg, value) != 0) {
-                goto out;
+            
+            if (value[0] == '"') {
+                value[0] = ' ';
             }
-            continue;
+
+            len = strlen(value);
+            if (value[len - 1] == '"') {
+                value[len - 1] = 0;
+            }
+            g_strchug(value);
+
+            qemu_opt_set(opts, keys[j], value);
+            g_free(value);
         }
-        error_report("parse error");
-        goto out;
-    }
-    if (ferror(fp)) {
-        error_report("error reading file");
-        goto out;
+
+        g_free(subkey);
+        g_free(group);
+        g_strfreev(keys);
     }
-    res = 0;
-out:
-    loc_pop(&loc);
-    return res;
-}
 
-int qemu_read_config_file(const char *filename)
-{
-    FILE *f = fopen(filename, "r");
-    int ret;
+    g_strfreev(groups);
 
-    if (f == NULL) {
-        return -errno;
-    }
+    g_key_file_free(f);
 
-    ret = qemu_config_parse(f, vm_config_groups, filename);
-    fclose(f);
+    return 0;
+}
 
-    if (ret == 0) {
-        return 0;
-    } else {
-        return -EINVAL;
-    }
+int qemu_read_config_file(const char *filename)
+{
+    return qemu_config_parse(vm_config_groups, filename);
 }
diff --git a/qemu-config.h b/qemu-config.h
index 20d707f..d767d51 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -12,7 +12,7 @@ int qemu_global_option(const char *str);
 void qemu_add_globals(void);
 
 void qemu_config_write(FILE *fp);
-int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname);
+int qemu_config_parse(QemuOptsList **lists, const char *fname);
 
 int qemu_read_config_file(const char *filename);
 
-- 
1.7.5.4

  parent reply	other threads:[~2012-03-19 15:10 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-19 15:09 [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Anthony Liguori
2012-03-19 15:09 ` [Qemu-devel] [PATCH 1/9] qemu-config: fix -writeconfig when using qemu_opt_set_bool Anthony Liguori
2012-03-19 15:09 ` Anthony Liguori [this message]
2012-03-19 15:09 ` [Qemu-devel] [PATCH 3/9] vl: refactor command line parsing to allow options to be set via config Anthony Liguori
2012-03-19 15:09 ` [Qemu-devel] [PATCH 4/9] vl: mark system configuration options in qemu-options.hx Anthony Liguori
2012-03-19 15:09 ` [Qemu-devel] [PATCH 5/9] vl: enable system configuration to be used Anthony Liguori
2012-03-19 15:09 ` [Qemu-devel] [PATCH 6/9] vl: parse all options via QemuOpts Anthony Liguori
2012-03-19 15:09 ` [Qemu-devel] [PATCH 7/9] qmp: expose a command to query capabilities of config parser Anthony Liguori
2012-03-19 20:10   ` Eric Blake
2012-03-19 20:19     ` Anthony Liguori
2012-03-19 20:31       ` Eric Blake
2012-03-19 20:41         ` Anthony Liguori
2012-03-19 15:09 ` [Qemu-devel] [PATCH 8/9] vl: add -query-capabilities Anthony Liguori
2012-03-20  7:49   ` Gerd Hoffmann
2012-03-20 10:33     ` Daniel P. Berrange
2012-03-20 19:39   ` Eduardo Habkost
2012-03-19 15:09 ` [Qemu-devel] [PATCH 9/9] Add a management tool writer's guide Anthony Liguori
2012-03-19 16:09 ` [Qemu-devel] [RFC PATCH 0/9] qemu capabilities reporting and config changes Paolo Bonzini
2012-03-19 16:31   ` Anthony Liguori
2012-03-19 16:33     ` Paolo Bonzini
2012-03-19 16:41       ` Anthony Liguori
2012-03-19 16:45         ` Paolo Bonzini
2012-03-19 16:53           ` Anthony Liguori
2012-03-19 17:03             ` Paolo Bonzini
2012-03-20  7:54     ` Gerd Hoffmann
2012-03-20 19:47   ` Eduardo Habkost

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1332169763-30665-3-git-send-email-aliguori@us.ibm.com \
    --to=aliguori@us.ibm.com \
    --cc=eblake@redhat.com \
    --cc=ehabkost@redhat.com \
    --cc=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).