[PATCH v2 13/19] Refactoring virDomainChrSourceDefParseXML() to use XPath

Kristina Hanicova khanicov at redhat.com
Tue May 4 11:40:07 UTC 2021


Signed-off-by: Kristina Hanicova <khanicov at redhat.com>
---
 src/conf/domain_conf.c | 190 ++++++++++++++++++++---------------------
 1 file changed, 94 insertions(+), 96 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5ac15fe9e8..c5b13783f3 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -11350,112 +11350,112 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDef *def,
                               virDomainChrDef *chr_def,
                               xmlXPathContextPtr ctxt)
 {
-    bool logParsed = false;
-    bool protocolParsed = false;
-    int sourceParsed = 0;
+    xmlNodePtr log = NULL;
+    xmlNodePtr protocol = NULL;
+    g_autofree xmlNodePtr *source = NULL;
+    int n = 0;
+    VIR_XPATH_NODE_AUTORESTORE(ctxt)
 
-    for (; cur; cur = cur->next) {
-        if (cur->type != XML_ELEMENT_NODE)
-            continue;
+    ctxt->node = cur;
 
-        if (virXMLNodeNameEqual(cur, "source")) {
-            /* Parse only the first source element since only one is used
-             * for chardev devices, the only exception is UDP type, where
-             * user can specify two source elements. */
-            if (sourceParsed >= 1 && def->type != VIR_DOMAIN_CHR_TYPE_UDP) {
-                virReportError(VIR_ERR_XML_ERROR, "%s",
-                               _("only one source element is allowed for "
-                                 "character device"));
-                goto error;
-            } else if (sourceParsed >= 2) {
-                virReportError(VIR_ERR_XML_ERROR, "%s",
-                               _("only two source elements are allowed for "
-                                 "character device"));
-                goto error;
-            }
-            sourceParsed++;
+    if ((n = virXPathNodeSet("./source", ctxt, &source)) > 0) {
+        /* Parse only the first source element since only one is used
+         * for chardev devices, the only exception is UDP type, where
+         * user can specify two source elements. */
+        if (n > 1 && def->type != VIR_DOMAIN_CHR_TYPE_UDP) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("only one source element is allowed for "
+                             "character device"));
+            goto error;
+        } else if (n > 2) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("only two source elements are allowed for "
+                             "character device"));
+            goto error;
+        }
 
-            switch ((virDomainChrType) def->type) {
-            case VIR_DOMAIN_CHR_TYPE_FILE:
-                if (virDomainChrSourceDefParseFile(def, cur) < 0)
-                    goto error;
-                break;
+        switch ((virDomainChrType) def->type) {
+        case VIR_DOMAIN_CHR_TYPE_FILE:
+            if (virDomainChrSourceDefParseFile(def, source[0]) < 0)
+                goto error;
+            break;
 
-            case VIR_DOMAIN_CHR_TYPE_PTY:
-                /* PTY path is only parsed from live xml.  */
-                if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))
-                    def->data.file.path = virXMLPropString(cur, "path");
-                break;
+        case VIR_DOMAIN_CHR_TYPE_PTY:
+            /* PTY path is only parsed from live xml.  */
+            if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))
+                def->data.file.path = virXPathString("string(./source/@path)", ctxt);
+            break;
 
-            case VIR_DOMAIN_CHR_TYPE_DEV:
-            case VIR_DOMAIN_CHR_TYPE_PIPE:
-                def->data.file.path = virXMLPropString(cur, "path");
-                break;
+        case VIR_DOMAIN_CHR_TYPE_DEV:
+        case VIR_DOMAIN_CHR_TYPE_PIPE:
+            def->data.file.path = virXPathString("string(./source/@path)", ctxt);
+            break;
 
-            case VIR_DOMAIN_CHR_TYPE_UNIX:
-                if (virDomainChrSourceDefParseUnix(def, cur, ctxt) < 0)
-                    goto error;
-                break;
+        case VIR_DOMAIN_CHR_TYPE_UNIX:
+            if (virDomainChrSourceDefParseUnix(def, source[0], ctxt) < 0)
+                goto error;
+            break;
 
-            case VIR_DOMAIN_CHR_TYPE_UDP:
-                if (virDomainChrSourceDefParseUDP(def, cur) < 0)
+        case VIR_DOMAIN_CHR_TYPE_UDP:
+            if ((virDomainChrSourceDefParseUDP(def, source[0]) < 0) ||
+                (source[1] && virDomainChrSourceDefParseUDP(def, source[1]) < 0))
                     goto error;
-                break;
+            break;
 
-            case VIR_DOMAIN_CHR_TYPE_TCP:
-                if (virDomainChrSourceDefParseTCP(def, cur, ctxt, flags) < 0)
-                    goto error;
-                break;
+        case VIR_DOMAIN_CHR_TYPE_TCP:
+            if (virDomainChrSourceDefParseTCP(def, source[0], ctxt, flags) < 0)
+                goto error;
+            break;
 
-            case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
-                def->data.spiceport.channel = virXMLPropString(cur, "channel");
-                break;
+        case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
+            def->data.spiceport.channel = virXPathString("string(./source/@channel)", ctxt);
+            break;
 
-            case VIR_DOMAIN_CHR_TYPE_NMDM:
-                def->data.nmdm.master = virXMLPropString(cur, "master");
-                def->data.nmdm.slave = virXMLPropString(cur, "slave");
-                break;
+        case VIR_DOMAIN_CHR_TYPE_NMDM:
+            def->data.nmdm.master = virXPathString("string(./source/@master)", ctxt);
+            def->data.nmdm.slave = virXPathString("string(./source/@slave)", ctxt);
+            break;
 
-            case VIR_DOMAIN_CHR_TYPE_LAST:
-            case VIR_DOMAIN_CHR_TYPE_NULL:
-            case VIR_DOMAIN_CHR_TYPE_VC:
-            case VIR_DOMAIN_CHR_TYPE_STDIO:
-            case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
-                break;
-            }
+        case VIR_DOMAIN_CHR_TYPE_LAST:
+        case VIR_DOMAIN_CHR_TYPE_NULL:
+        case VIR_DOMAIN_CHR_TYPE_VC:
+        case VIR_DOMAIN_CHR_TYPE_STDIO:
+        case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
+            break;
+        }
 
-            /* Check for an optional seclabel override in <source/>. */
-            if (chr_def) {
-                VIR_XPATH_NODE_AUTORESTORE(ctxt)
-                ctxt->node = cur;
-                if (virSecurityDeviceLabelDefParseXML(&def->seclabels,
-                                                      &def->nseclabels,
-                                                      ctxt,
-                                                      flags) < 0) {
-                    goto error;
-                }
-            }
-        } else if (virXMLNodeNameEqual(cur, "log")) {
-            if (logParsed) {
-                virReportError(VIR_ERR_XML_ERROR, "%s",
-                               _("only one protocol element is allowed for "
-                                 "character device"));
-                goto error;
-            }
-            logParsed = true;
-            if (virDomainChrSourceDefParseLog(def, cur) < 0)
-                goto error;
-        } else if (virXMLNodeNameEqual(cur, "protocol")) {
-            if (protocolParsed) {
-                virReportError(VIR_ERR_XML_ERROR, "%s",
-                               _("only one log element is allowed for "
-                                 "character device"));
+        /* Check for an optional seclabel override in <source/>. */
+        if (chr_def) {
+            xmlNodePtr tmp = ctxt->node;
+            ctxt->node = source[0];
+            if (virSecurityDeviceLabelDefParseXML(&def->seclabels, &def->nseclabels,
+                                                  ctxt, flags) < 0) {
                 goto error;
             }
-            protocolParsed = true;
-            if (virDomainChrSourceDefParseProtocol(def, cur) < 0)
-                goto error;
+            ctxt->node = tmp;
+        }
+    }
+
+    if ((log = virXPathNode("./log", ctxt))) {
+        if (virXPathBoolean("boolean(count(./log) > 1)", ctxt)) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("only one log element is allowed for "
+                             "character device"));
+            goto error;
+        }
+        if (virDomainChrSourceDefParseLog(def, log) < 0)
+            goto error;
+    }
+
+    if ((protocol = virXPathNode("./protocol", ctxt))) {
+        if (virXPathBoolean("boolean(count(./protocol) > 1)", ctxt)) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("only one protocol element is allowed for "
+                             "character device"));
+            goto error;
         }
+        if (virDomainChrSourceDefParseProtocol(def, protocol) < 0)
+            goto error;
     }
 
     return 0;
@@ -11609,7 +11609,7 @@ virDomainChrDefParseXML(virDomainXMLOption *xmlopt,
         ((def->targetType = virDomainChrDefaultTargetType(def->deviceType)) < 0))
         goto error;
 
-    if (virDomainChrSourceDefParseXML(def->source, node->children, flags, def,
+    if (virDomainChrSourceDefParseXML(def->source, node, flags, def,
                                       ctxt) < 0)
         goto error;
 
@@ -11733,7 +11733,7 @@ virDomainSmartcardDefParseXML(virDomainXMLOption *xmlopt,
         }
 
         cur = node->children;
-        if (virDomainChrSourceDefParseXML(def->data.passthru, cur, flags,
+        if (virDomainChrSourceDefParseXML(def->data.passthru, node, flags,
                                           NULL, ctxt) < 0)
             return NULL;
 
@@ -13686,7 +13686,7 @@ virDomainRNGDefParseXML(virDomainXMLOption *xmlopt,
         }
 
         if (virDomainChrSourceDefParseXML(def->source.chardev,
-                                          backends[0]->children, flags,
+                                          backends[0], flags,
                                           NULL, ctxt) < 0)
             goto error;
         break;
@@ -14693,7 +14693,6 @@ virDomainRedirdevDefParseXML(virDomainXMLOption *xmlopt,
                              xmlXPathContextPtr ctxt,
                              unsigned int flags)
 {
-    xmlNodePtr cur;
     virDomainRedirdevDef *def;
     g_autofree char *bus = NULL;
     g_autofree char *type = NULL;
@@ -14727,10 +14726,9 @@ virDomainRedirdevDefParseXML(virDomainXMLOption *xmlopt,
         goto error;
     }
 
-    cur = node->children;
     /* boot gets parsed in virDomainDeviceInfoParseXML
      * source gets parsed in virDomainChrSourceDefParseXML */
-    if (virDomainChrSourceDefParseXML(def->source, cur, flags,
+    if (virDomainChrSourceDefParseXML(def->source, node, flags,
                                       NULL, ctxt) < 0)
         goto error;
 
-- 
2.30.2




More information about the libvir-list mailing list