qemu-block
[Top][All Lists]
Advanced

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

[Qemu-block] [PATCH 1/2] nbd: change option parsing scheme


From: Denis V. Lunev
Subject: [Qemu-block] [PATCH 1/2] nbd: change option parsing scheme
Date: Wed, 5 Oct 2016 12:33:07 +0300

From: Denis Plotnikov <address@hidden>

This is a preparatory commit to make code more generic. We are going to
add more options in the next patch.

Signed-off-by: Denis Plotnikov <address@hidden>
Signed-off-by: Denis V. Lunev <address@hidden>
CC: Paolo Bonzini <address@hidden>
CC: Kevin Wolf <address@hidden>
CC: Max Reitz <address@hidden>
---
 block/nbd.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 124 insertions(+), 19 deletions(-)

diff --git a/block/nbd.c b/block/nbd.c
index 6bc06d6..3b133ed 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -38,7 +38,9 @@
 #include "qapi/qmp/qstring.h"
 #include "qemu/cutils.h"
 
-#define EN_OPTSTR ":exportname="
+#define EN_OPTSTR "exportname"
+
+#define PATH_PARAM      (1u << 0)
 
 typedef struct BDRVNBDState {
     NbdClientSession client;
@@ -47,6 +49,46 @@ typedef struct BDRVNBDState {
     char *path, *host, *port, *export, *tlscredsid;
 } BDRVNBDState;
 
+/*
+ * helpers for dealing with option parsing
+ * to ease futher params adding and managing
+ */
+
+/*
+ *  @param_flags - bit flags defining a set of param names to be parsed
+ */
+static bool parse_query_params(QueryParams *qp, QDict *options,
+                               unsigned int param_flags)
+{
+    int i;
+    for (i = 0; i < qp->n; i++) {
+        QueryParam *param = &qp->p[i];
+
+        if ((PATH_PARAM & param_flags) &&
+            strcmp(param->name, "socket") == 0) {
+            qdict_put(options, "path", qstring_from_str(param->value));
+            continue;
+        }
+
+    }
+    return true;
+}
+
+static bool find_prohibited_params(QueryParams *qp, unsigned int param_flags)
+{
+    int i;
+    for (i = 0; i < qp->n; i++) {
+        QueryParam *param = &qp->p[i];
+
+        if ((PATH_PARAM & param_flags) &&
+            strcmp(param->name, "socket") == 0) {
+            return true;
+        }
+    }
+    return false;
+}
+
+
 static int nbd_parse_uri(const char *filename, QDict *options)
 {
     URI *uri;
@@ -79,18 +121,18 @@ static int nbd_parse_uri(const char *filename, QDict 
*options)
     }
 
     qp = query_params_parse(uri->query);
-    if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) {
-        ret = -EINVAL;
-        goto out;
-    }
 
     if (is_unix) {
         /* nbd+unix:///export?socket=path */
-        if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) {
+        if (uri->server || uri->port) {
+            ret = -EINVAL;
+            goto out;
+        }
+
+        if (!parse_query_params(qp, options, PATH_PARAM)) {
             ret = -EINVAL;
             goto out;
         }
-        qdict_put(options, "path", qstring_from_str(qp->p[0].value));
     } else {
         QString *host;
         /* nbd[+tcp]://host[:port]/export */
@@ -113,6 +155,11 @@ static int nbd_parse_uri(const char *filename, QDict 
*options)
             qdict_put(options, "port", qstring_from_str(port_str));
             g_free(port_str);
         }
+
+        if (find_prohibited_params(qp, PATH_PARAM)) {
+            ret = -EINVAL;
+            goto out;
+        }
     }
 
 out:
@@ -127,7 +174,7 @@ static void nbd_parse_filename(const char *filename, QDict 
*options,
                                Error **errp)
 {
     char *file;
-    char *export_name;
+    char *opt_str;
     const char *host_spec;
     const char *unixpath;
 
@@ -150,17 +197,6 @@ static void nbd_parse_filename(const char *filename, QDict 
*options,
 
     file = g_strdup(filename);
 
-    export_name = strstr(file, EN_OPTSTR);
-    if (export_name) {
-        if (export_name[strlen(EN_OPTSTR)] == 0) {
-            goto out;
-        }
-        export_name[0] = 0; /* truncate 'file' */
-        export_name += strlen(EN_OPTSTR);
-
-        qdict_put(options, "export", qstring_from_str(export_name));
-    }
-
     /* extract the host_spec - fail if it's not nbd:... */
     if (!strstart(file, "nbd:", &host_spec)) {
         error_setg(errp, "File name string for NBD must start with 'nbd:'");
@@ -173,8 +209,40 @@ static void nbd_parse_filename(const char *filename, QDict 
*options,
 
     /* are we a UNIX or TCP socket? */
     if (strstart(host_spec, "unix:", &unixpath)) {
+        opt_str = (char *) unixpath;
+
+        /* do we have any options? */
+        /* unixpath could be unix: or unix:something:options */
+        opt_str = strchr(opt_str, ':');
+
+        /* if we have any options then "divide" */
+        /* the path and the options by replacing the last colon with "\0" */
+        if (opt_str != NULL) {
+            /* truncate 'unixpath' replacing the last ":" */
+            char *colon_pos = opt_str;
+            colon_pos[0] = '\0';
+            opt_str++;
+        }
         qdict_put(options, "path", qstring_from_str(unixpath));
     } else {
+        /* host_spec could be ip:port or ip:port:options */
+        int i;
+        opt_str = (char *)host_spec;
+        for (i = 0; i < 2; i++) {
+            opt_str = strchr(opt_str, ':');
+            if (opt_str == NULL) {
+                break;
+            }
+            opt_str++;
+        }
+
+        /* the same idea with dividing as above */
+        if (opt_str != NULL) {
+            /* truncate 'host_name' replacing the last ":" */
+            char *second_colon_pos = opt_str - 1;
+            second_colon_pos[0] = '\0';
+        }
+
         InetSocketAddress *addr = NULL;
 
         addr = inet_parse(host_spec, errp);
@@ -187,6 +255,43 @@ static void nbd_parse_filename(const char *filename, QDict 
*options,
         qapi_free_InetSocketAddress(addr);
     }
 
+    /* opt_str == NULL means no options given */
+    if (opt_str != NULL) {
+        static QemuOptsList file_opts = {
+            .name = "file_opts",
+            .head = QTAILQ_HEAD_INITIALIZER(file_opts.head),
+            .desc = {
+                {
+                    .name = EN_OPTSTR,
+                    .type = QEMU_OPT_STRING,
+                    .help = "Name of the NBD export to open",
+                },
+            },
+        };
+
+        QemuOpts *opts = qemu_opts_create(&file_opts, NULL, 0, errp);
+        if (opts == NULL) {
+            error_setg(errp, "Can't parse file options");
+            goto out;
+        }
+
+        Error *local_err = NULL;
+        qemu_opts_do_parse(opts, opt_str, NULL, &local_err);
+        if (local_err) {
+            error_setg(errp, "Can't parse file options");
+            qemu_opts_del(opts);
+            goto out;
+        }
+
+        const char *value;
+        value = qemu_opt_get(opts, EN_OPTSTR);
+        if (value) {
+            qdict_put(options, "export", qstring_from_str(value));
+        }
+
+        qemu_opts_del(opts);
+    }
+
 out:
     g_free(file);
 }
-- 
2.7.4




reply via email to

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