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@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list