qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 2/9] qemu-config: friends don't let friends use ssca


From: Anthony Liguori
Subject: [Qemu-devel] [PATCH 2/9] qemu-config: friends don't let friends use sscanf
Date: Mon, 19 Mar 2012 10:09:16 -0500

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 <address@hidden>
---
 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]