[libvirt] [PATCH] 2/4 Add conf parsing and freeing

Daniel Veillard veillard at redhat.com
Thu Oct 21 20:16:00 UTC 2010


 This lacks the saving of the smbios data, should not be hard really,
and the parsing is rather trivial, the data structures follow the XML
format:

Daniel

diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 5499f28..9dff0f7 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -606,6 +606,29 @@ struct _virDomainMemballoonDef {
 };
 
 
+
+typedef struct _virSmbiosEntry virSmbiosEntry;
+typedef virSmbiosEntry *virSmbiosEntryPtr;
+struct _virSmbiosEntry {
+    virSmbiosEntryPtr next;
+    char *name;
+    char *value;
+};
+
+typedef struct _virSmbiosBlock virSmbiosBlock;
+typedef virSmbiosBlock *virSmbiosBlockPtr;
+struct _virSmbiosBlock {
+    unsigned int type;
+    virSmbiosEntryPtr entries;
+};
+
+typedef struct _virSmbiosDef virSmbiosDef;
+typedef virSmbiosDef *virSmbiosDefPtr;
+struct _virSmbiosDef {
+    unsigned int nbblocks;
+    virSmbiosBlockPtr *blocks;
+};
+
 /* Flags for the 'type' field in next struct */
 enum virDomainDeviceType {
     VIR_DOMAIN_DEVICE_DISK,
@@ -943,6 +966,7 @@ struct _virDomainDef {
     virDomainWatchdogDefPtr watchdog;
     virDomainMemballoonDefPtr memballoon;
     virCPUDefPtr cpu;
+    virSmbiosDefPtr smbios;
 
     void *namespaceData;
     virDomainXMLNamespace ns;
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a997e06..fd85398 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -712,6 +712,48 @@ virDomainClockDefClear(virDomainClockDefPtr def)
     VIR_FREE(def->timers);
 }
 
+static void virSmbiosEntriesFree(virSmbiosEntryPtr cur)
+{
+    virSmbiosEntryPtr next;
+
+    if (cur == NULL)
+        return;
+
+    while (cur != NULL) {
+        next = cur->next;
+
+        VIR_FREE(cur->name);
+        VIR_FREE(cur->value);
+        VIR_FREE(cur);
+
+        cur = next;
+    }
+}
+
+static void virSmbiosBlockFree(virSmbiosBlockPtr block)
+{
+    if (block == NULL)
+        return;
+
+    virSmbiosEntriesFree(block->entries);
+    VIR_FREE(block);
+}
+
+static void virSmbiosDefFree(virSmbiosDefPtr def)
+{
+    unsigned int i;
+
+    if (def == NULL)
+        return;
+
+    if (def->blocks != NULL) {
+        for (i = 0;i < def->nbblocks;i++)
+            virSmbiosBlockFree(def->blocks[i]);
+        VIR_FREE(def->blocks);
+    }
+    VIR_FREE(def);
+}
+
 void virDomainDefFree(virDomainDefPtr def)
 {
     unsigned int i;
@@ -796,6 +838,8 @@ void virDomainDefFree(virDomainDefPtr def)
 
     virCPUDefFree(def->cpu);
 
+    virSmbiosDefFree(def->smbios);
+
     if (def->namespaceData && def->ns.free)
         (def->ns.free)(def->namespaceData);
 
@@ -3341,6 +3385,150 @@ error:
     goto cleanup;
 }
 
+static virSmbiosEntryPtr
+virSmbiosEntryParseXML(xmlXPathContextPtr ctxt)
+{
+    char *name, *value;
+    virSmbiosEntryPtr def;
+
+    name = virXPathString("string(./@name)", ctxt);
+    if (name == NULL) {
+        virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+                  _("XML element 'entry' requires a 'name' attrbute"));
+        return(NULL);
+    }
+    value = virXPathString("string(.)", ctxt);
+    if (value == NULL) {
+        virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+                  _("failed to get content of element 'entry'"));
+        VIR_FREE(name);
+        return(NULL);
+    }
+
+    if (VIR_ALLOC(def) < 0) {
+        virReportOOMError();
+        VIR_FREE(name);
+        VIR_FREE(value);
+        return(NULL);
+    }
+    def->name = name;
+    def->value = value;
+    def->next = NULL;
+
+    return(def);
+}
+
+static virSmbiosBlockPtr
+virSmbiosBlockParseXML(xmlXPathContextPtr ctxt)
+{
+    virSmbiosBlockPtr def;
+    virSmbiosEntryPtr cur, next;
+    xmlNodePtr *nodes = NULL;
+    int n;
+    unsigned int i;
+    long type;
+
+    if (virXPathLong("string(./@type)", ctxt, &type) < 0) {
+        virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+                  _("XML element 'table' requires a numeric 'type' attrbute"));
+        return(NULL);
+    }
+    if ((type < 0) || (type > 32)) {
+        virDomainReportError(VIR_ERR_XML_ERROR,
+              _("XML 'type' attribute on 'table' out of 0..32 range got %ld"),
+                type);
+        return(NULL);
+    }
+    n = virXPathNodeSet("./entry", ctxt, &nodes);
+    if (n <= 0)
+        return(NULL);
+
+    if (VIR_ALLOC(def) < 0) {
+        virReportOOMError();
+        goto error;
+    }
+    def->type = (unsigned int) type;
+    def->entries = NULL;
+    cur = NULL;
+
+    for (i = 0;i < n;i++) {
+        if (nodes[i] != NULL) {
+            ctxt->node = nodes[i];
+            next = virSmbiosEntryParseXML(ctxt);
+            if (next == NULL)
+                goto error;
+            if (cur == NULL) {
+                def->entries = next;
+                cur = next;
+            } else {
+                cur->next = next;
+                cur = next;
+            }
+            cur->next = NULL;
+        }
+    }
+
+cleanup:
+    xmlFree(nodes);
+    return(def);
+
+error:
+    virSmbiosBlockFree(def);
+    def = NULL;
+    goto cleanup;
+}
+
+static virSmbiosDefPtr
+virSmbiosParseXML(const xmlNodePtr node,
+                  xmlXPathContextPtr ctxt)
+{
+    virSmbiosDefPtr def;
+    virSmbiosBlockPtr block;
+    xmlNodePtr *nodes = NULL;
+    int n;
+    unsigned int i, j;
+
+    if (!xmlStrEqual(node->name, BAD_CAST "smbios")) {
+        virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+                          _("XML does not contain expected 'smbios' element"));
+        return(NULL);
+    }
+
+    n = virXPathNodeSet("./table", ctxt, &nodes);
+    if (n <= 0)
+        return(NULL);
+
+    if (VIR_ALLOC(def) < 0) {
+        virReportOOMError();
+        goto error;
+    }
+    if (VIR_ALLOC_N(def->blocks, n) < 0) {
+        virReportOOMError();
+        goto error;
+    }
+
+    for (i = 0, j = 0;i < n;i++) {
+        if (nodes[i] != NULL) {
+            ctxt->node = nodes[i];
+            block = virSmbiosBlockParseXML(ctxt);
+            if (block != NULL)
+                def->blocks[j++] = block;
+            else
+                goto error;
+            def->nbblocks = j;
+        }
+    }
+
+
+cleanup:
+    xmlFree(nodes);
+    return(def);
+
+error:
+    virSmbiosDefFree(def);
+    def = NULL;
+    goto cleanup;
+}
 
 int
 virDomainVideoDefaultRAM(virDomainDefPtr def,
@@ -4970,6 +5158,16 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
             goto error;
     }
 
+    if ((node = virXPathNode("./smbios[1]", ctxt)) != NULL) {
+        xmlNodePtr oldnode = ctxt->node;
+        ctxt->node = node;
+        def->smbios = virSmbiosParseXML(node, ctxt);
+        ctxt->node = oldnode;
+
+        if (def->smbios == NULL)
+            goto error;
+    }
+
     /* we have to make a copy of all of the callback pointers here since
      * we won't have the virCaps structure available during free
      */

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list