virSysinfoDef: Exempt BIOS variables

Move all the bios_* fields into a separate struct. Not only this
simplifies the code a bit it also helps us to identify whether BIOS
info is present. We don't have to check all the four variables for
being not-NULL, but we can just check the pointer to the struct.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Michal Privoznik 2015-05-12 12:02:29 +02:00
parent a377408f0b
commit 3f9cae18fe
5 changed files with 173 additions and 81 deletions

View File

@ -11093,6 +11093,65 @@ virDomainShmemDefParseXML(xmlNodePtr node,
return ret; return ret;
} }
static int
virSysinfoBIOSParseXML(xmlNodePtr node,
xmlXPathContextPtr ctxt,
virSysinfoBIOSDefPtr *bios)
{
int ret = -1;
virSysinfoBIOSDefPtr def;
if (!xmlStrEqual(node->name, BAD_CAST "bios")) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("XML does not contain expected 'bios' element"));
return ret;
}
if (VIR_ALLOC(def) < 0)
goto cleanup;
def->vendor = virXPathString("string(entry[@name='vendor'])", ctxt);
def->version = virXPathString("string(entry[@name='version'])", ctxt);
def->date = virXPathString("string(entry[@name='date'])", ctxt);
def->release = virXPathString("string(entry[@name='release'])", ctxt);
if (def->date != NULL) {
char *ptr;
int month, day, year;
/* Validate just the format of the date
* Expect mm/dd/yyyy or mm/dd/yy,
* where yy must be 00->99 and would be assumed to be 19xx
* a yyyy date should be 1900 and beyond
*/
if (virStrToLong_i(def->date, &ptr, 10, &month) < 0 ||
*ptr != '/' ||
virStrToLong_i(ptr + 1, &ptr, 10, &day) < 0 ||
*ptr != '/' ||
virStrToLong_i(ptr + 1, &ptr, 10, &year) < 0 ||
*ptr != '\0' ||
(month < 1 || month > 12) ||
(day < 1 || day > 31) ||
(year < 0 || (year >= 100 && year < 1900))) {
virReportError(VIR_ERR_XML_DETAIL, "%s",
_("Invalid BIOS 'date' format"));
goto cleanup;
}
}
if (!def->vendor && !def->version &&
!def->date && !def->release) {
virSysinfoBIOSDefFree(def);
def = NULL;
}
*bios = def;
def = NULL;
ret = 0;
cleanup:
virSysinfoBIOSDefFree(def);
return ret;
}
static virSysinfoDefPtr static virSysinfoDefPtr
virSysinfoParseXML(xmlNodePtr node, virSysinfoParseXML(xmlNodePtr node,
xmlXPathContextPtr ctxt, xmlXPathContextPtr ctxt,
@ -11100,6 +11159,7 @@ virSysinfoParseXML(xmlNodePtr node,
bool uuid_generated) bool uuid_generated)
{ {
virSysinfoDefPtr def; virSysinfoDefPtr def;
xmlNodePtr oldnode, tmpnode;
char *type; char *type;
char *tmpUUID = NULL; char *tmpUUID = NULL;
@ -11124,39 +11184,16 @@ virSysinfoParseXML(xmlNodePtr node,
goto error; goto error;
} }
/* Extract BIOS related metadata */ /* Extract BIOS related metadata */
def->bios_vendor = if ((tmpnode = virXPathNode("./bios[1]", ctxt)) != NULL) {
virXPathString("string(bios/entry[@name='vendor'])", ctxt); oldnode = ctxt->node;
def->bios_version = ctxt->node = tmpnode;
virXPathString("string(bios/entry[@name='version'])", ctxt); if (virSysinfoBIOSParseXML(tmpnode, ctxt, &def->bios) < 0) {
def->bios_date = ctxt->node = oldnode;
virXPathString("string(bios/entry[@name='date'])", ctxt);
if (def->bios_date != NULL) {
char *ptr;
int month, day, year;
/* Validate just the format of the date
* Expect mm/dd/yyyy or mm/dd/yy,
* where yy must be 00->99 and would be assumed to be 19xx
* a yyyy date should be 1900 and beyond
*/
if (virStrToLong_i(def->bios_date, &ptr, 10, &month) < 0 ||
*ptr != '/' ||
virStrToLong_i(ptr + 1, &ptr, 10, &day) < 0 ||
*ptr != '/' ||
virStrToLong_i(ptr + 1, &ptr, 10, &year) < 0 ||
*ptr != '\0' ||
(month < 1 || month > 12) ||
(day < 1 || day > 31) ||
(year < 0 || (year >= 100 && year < 1900))) {
virReportError(VIR_ERR_XML_DETAIL, "%s",
_("Invalid BIOS 'date' format"));
goto error; goto error;
} }
ctxt->node = oldnode;
} }
def->bios_release =
virXPathString("string(bios/entry[@name='release'])", ctxt);
/* Extract system related metadata */ /* Extract system related metadata */
def->system_manufacturer = def->system_manufacturer =

View File

@ -2182,6 +2182,7 @@ virVasprintfInternal;
# util/virsysinfo.h # util/virsysinfo.h
virSysinfoBIOSDefFree;
virSysinfoDefFree; virSysinfoDefFree;
virSysinfoFormat; virSysinfoFormat;
virSysinfoRead; virSysinfoRead;

View File

@ -6701,28 +6701,27 @@ static char *qemuBuildTPMDevStr(const virDomainDef *def,
} }
static char *qemuBuildSmbiosBiosStr(virSysinfoDefPtr def) static char *qemuBuildSmbiosBiosStr(virSysinfoBIOSDefPtr def)
{ {
virBuffer buf = VIR_BUFFER_INITIALIZER; virBuffer buf = VIR_BUFFER_INITIALIZER;
if ((def->bios_vendor == NULL) && (def->bios_version == NULL) && if (!def)
(def->bios_date == NULL) && (def->bios_release == NULL))
return NULL; return NULL;
virBufferAddLit(&buf, "type=0"); virBufferAddLit(&buf, "type=0");
/* 0:Vendor */ /* 0:Vendor */
if (def->bios_vendor) if (def->vendor)
virBufferAsprintf(&buf, ",vendor=%s", def->bios_vendor); virBufferAsprintf(&buf, ",vendor=%s", def->vendor);
/* 0:BIOS Version */ /* 0:BIOS Version */
if (def->bios_version) if (def->version)
virBufferAsprintf(&buf, ",version=%s", def->bios_version); virBufferAsprintf(&buf, ",version=%s", def->version);
/* 0:BIOS Release Date */ /* 0:BIOS Release Date */
if (def->bios_date) if (def->date)
virBufferAsprintf(&buf, ",date=%s", def->bios_date); virBufferAsprintf(&buf, ",date=%s", def->date);
/* 0:System BIOS Major Release and 0:System BIOS Minor Release */ /* 0:System BIOS Major Release and 0:System BIOS Minor Release */
if (def->bios_release) if (def->release)
virBufferAsprintf(&buf, ",release=%s", def->bios_release); virBufferAsprintf(&buf, ",release=%s", def->release);
if (virBufferCheckError(&buf) < 0) if (virBufferCheckError(&buf) < 0)
goto error; goto error;
@ -9047,7 +9046,7 @@ qemuBuildCommandLine(virConnectPtr conn,
if (source != NULL) { if (source != NULL) {
char *smbioscmd; char *smbioscmd;
smbioscmd = qemuBuildSmbiosBiosStr(source); smbioscmd = qemuBuildSmbiosBiosStr(source->bios);
if (smbioscmd != NULL) { if (smbioscmd != NULL) {
virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL); virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
VIR_FREE(smbioscmd); VIR_FREE(smbioscmd);

View File

@ -64,6 +64,18 @@ void virSysinfoSetup(const char *dmidecode, const char *sysinfo,
sysinfoCpuinfo = cpuinfo; sysinfoCpuinfo = cpuinfo;
} }
void virSysinfoBIOSDefFree(virSysinfoBIOSDefPtr def)
{
if (def == NULL)
return;
VIR_FREE(def->vendor);
VIR_FREE(def->version);
VIR_FREE(def->date);
VIR_FREE(def->release);
VIR_FREE(def);
}
/** /**
* virSysinfoDefFree: * virSysinfoDefFree:
* @def: a sysinfo structure * @def: a sysinfo structure
@ -78,10 +90,7 @@ void virSysinfoDefFree(virSysinfoDefPtr def)
if (def == NULL) if (def == NULL)
return; return;
VIR_FREE(def->bios_vendor); virSysinfoBIOSDefFree(def->bios);
VIR_FREE(def->bios_version);
VIR_FREE(def->bios_date);
VIR_FREE(def->bios_release);
VIR_FREE(def->system_manufacturer); VIR_FREE(def->system_manufacturer);
VIR_FREE(def->system_product); VIR_FREE(def->system_product);
@ -522,40 +531,56 @@ virSysinfoRead(void)
#else /* !WIN32 && x86 */ #else /* !WIN32 && x86 */
static int static int
virSysinfoParseBIOS(const char *base, virSysinfoDefPtr ret) virSysinfoParseBIOS(const char *base, virSysinfoBIOSDefPtr *bios)
{ {
int ret = -1;
const char *cur, *eol = NULL; const char *cur, *eol = NULL;
virSysinfoBIOSDefPtr def;
if ((cur = strstr(base, "BIOS Information")) == NULL) if ((cur = strstr(base, "BIOS Information")) == NULL)
return 0; return 0;
if (VIR_ALLOC(def) < 0)
return ret;
base = cur; base = cur;
if ((cur = strstr(base, "Vendor: ")) != NULL) { if ((cur = strstr(base, "Vendor: ")) != NULL) {
cur += 8; cur += 8;
eol = strchr(cur, '\n'); eol = strchr(cur, '\n');
if (eol && VIR_STRNDUP(ret->bios_vendor, cur, eol - cur) < 0) if (eol && VIR_STRNDUP(def->vendor, cur, eol - cur) < 0)
return -1; goto cleanup;
} }
if ((cur = strstr(base, "Version: ")) != NULL) { if ((cur = strstr(base, "Version: ")) != NULL) {
cur += 9; cur += 9;
eol = strchr(cur, '\n'); eol = strchr(cur, '\n');
if (eol && VIR_STRNDUP(ret->bios_version, cur, eol - cur) < 0) if (eol && VIR_STRNDUP(def->version, cur, eol - cur) < 0)
return -1; goto cleanup;
} }
if ((cur = strstr(base, "Release Date: ")) != NULL) { if ((cur = strstr(base, "Release Date: ")) != NULL) {
cur += 14; cur += 14;
eol = strchr(cur, '\n'); eol = strchr(cur, '\n');
if (eol && VIR_STRNDUP(ret->bios_date, cur, eol - cur) < 0) if (eol && VIR_STRNDUP(def->date, cur, eol - cur) < 0)
return -1; goto cleanup;
} }
if ((cur = strstr(base, "BIOS Revision: ")) != NULL) { if ((cur = strstr(base, "BIOS Revision: ")) != NULL) {
cur += 15; cur += 15;
eol = strchr(cur, '\n'); eol = strchr(cur, '\n');
if (eol && VIR_STRNDUP(ret->bios_release, cur, eol - cur) < 0) if (eol && VIR_STRNDUP(def->release, cur, eol - cur) < 0)
return -1; goto cleanup;
} }
return 0; if (!def->vendor && !def->version &&
!def->date && !def->release) {
virSysinfoBIOSDefFree(def);
def = NULL;
}
*bios = def;
def = NULL;
ret = 0;
cleanup:
virSysinfoBIOSDefFree(def);
return ret;
} }
static int static int
@ -846,7 +871,7 @@ virSysinfoRead(void)
ret->type = VIR_SYSINFO_SMBIOS; ret->type = VIR_SYSINFO_SMBIOS;
if (virSysinfoParseBIOS(outbuf, ret) < 0) if (virSysinfoParseBIOS(outbuf, &ret->bios) < 0)
goto error; goto error;
if (virSysinfoParseSystem(outbuf, ret) < 0) if (virSysinfoParseSystem(outbuf, ret) < 0)
@ -876,22 +901,21 @@ virSysinfoRead(void)
#endif /* !WIN32 && x86 */ #endif /* !WIN32 && x86 */
static void static void
virSysinfoBIOSFormat(virBufferPtr buf, virSysinfoDefPtr def) virSysinfoBIOSFormat(virBufferPtr buf, virSysinfoBIOSDefPtr def)
{ {
if (!def->bios_vendor && !def->bios_version && if (!def)
!def->bios_date && !def->bios_release)
return; return;
virBufferAddLit(buf, "<bios>\n"); virBufferAddLit(buf, "<bios>\n");
virBufferAdjustIndent(buf, 2); virBufferAdjustIndent(buf, 2);
virBufferEscapeString(buf, "<entry name='vendor'>%s</entry>\n", virBufferEscapeString(buf, "<entry name='vendor'>%s</entry>\n",
def->bios_vendor); def->vendor);
virBufferEscapeString(buf, "<entry name='version'>%s</entry>\n", virBufferEscapeString(buf, "<entry name='version'>%s</entry>\n",
def->bios_version); def->version);
virBufferEscapeString(buf, "<entry name='date'>%s</entry>\n", virBufferEscapeString(buf, "<entry name='date'>%s</entry>\n",
def->bios_date); def->date);
virBufferEscapeString(buf, "<entry name='release'>%s</entry>\n", virBufferEscapeString(buf, "<entry name='release'>%s</entry>\n",
def->bios_release); def->release);
virBufferAdjustIndent(buf, -2); virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</bios>\n"); virBufferAddLit(buf, "</bios>\n");
} }
@ -1055,7 +1079,7 @@ virSysinfoFormat(virBufferPtr buf, virSysinfoDefPtr def)
virBufferAdjustIndent(&childrenBuf, indent + 2); virBufferAdjustIndent(&childrenBuf, indent + 2);
virSysinfoBIOSFormat(&childrenBuf, def); virSysinfoBIOSFormat(&childrenBuf, def->bios);
virSysinfoSystemFormat(&childrenBuf, def); virSysinfoSystemFormat(&childrenBuf, def);
virSysinfoProcessorFormat(&childrenBuf, def); virSysinfoProcessorFormat(&childrenBuf, def);
virSysinfoMemoryFormat(&childrenBuf, def); virSysinfoMemoryFormat(&childrenBuf, def);
@ -1078,6 +1102,41 @@ virSysinfoFormat(virBufferPtr buf, virSysinfoDefPtr def)
return ret; return ret;
} }
#define CHECK_FIELD(name, desc) \
do { \
if (STRNEQ_NULLABLE(src->name, dst->name)) { \
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \
_("Target sysinfo %s %s does not match source %s"), \
desc, NULLSTR(dst->name), NULLSTR(src->name)); \
goto cleanup; \
} \
} while (0)
static bool
virSysinfoBIOSIsEqual(virSysinfoBIOSDefPtr src,
virSysinfoBIOSDefPtr dst)
{
bool identical = false;
if (!src && !dst)
return true;
if ((src && !dst) || (!src && dst)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Target sysinfo does not match source"));
goto cleanup;
}
CHECK_FIELD(vendor, "BIOS vendor");
CHECK_FIELD(version, "BIOS version");
CHECK_FIELD(date, "BIOS date");
CHECK_FIELD(release, "BIOS release");
identical = true;
cleanup:
return identical;
}
bool virSysinfoIsEqual(virSysinfoDefPtr src, bool virSysinfoIsEqual(virSysinfoDefPtr src,
virSysinfoDefPtr dst) virSysinfoDefPtr dst)
{ {
@ -1100,19 +1159,8 @@ bool virSysinfoIsEqual(virSysinfoDefPtr src,
goto cleanup; goto cleanup;
} }
#define CHECK_FIELD(name, desc) \ if (!virSysinfoBIOSIsEqual(src->bios, dst->bios))
do { \ goto cleanup;
if (STRNEQ_NULLABLE(src->name, dst->name)) { \
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \
_("Target sysinfo %s %s does not match source %s"), \
desc, NULLSTR(src->name), NULLSTR(dst->name)); \
} \
} while (0)
CHECK_FIELD(bios_vendor, "BIOS vendor");
CHECK_FIELD(bios_version, "BIOS version");
CHECK_FIELD(bios_date, "BIOS date");
CHECK_FIELD(bios_release, "BIOS release");
CHECK_FIELD(system_manufacturer, "system vendor"); CHECK_FIELD(system_manufacturer, "system vendor");
CHECK_FIELD(system_product, "system product"); CHECK_FIELD(system_product, "system product");

View File

@ -65,15 +65,21 @@ struct _virSysinfoMemoryDef {
char *memory_part_number; char *memory_part_number;
}; };
typedef struct _virSysinfoBIOSDef virSysinfoBIOSDef;
typedef virSysinfoBIOSDef *virSysinfoBIOSDefPtr;
struct _virSysinfoBIOSDef {
char *vendor;
char *version;
char *date;
char *release;
};
typedef struct _virSysinfoDef virSysinfoDef; typedef struct _virSysinfoDef virSysinfoDef;
typedef virSysinfoDef *virSysinfoDefPtr; typedef virSysinfoDef *virSysinfoDefPtr;
struct _virSysinfoDef { struct _virSysinfoDef {
int type; int type;
char *bios_vendor; virSysinfoBIOSDefPtr bios;
char *bios_version;
char *bios_date;
char *bios_release;
char *system_manufacturer; char *system_manufacturer;
char *system_product; char *system_product;
@ -92,6 +98,7 @@ struct _virSysinfoDef {
virSysinfoDefPtr virSysinfoRead(void); virSysinfoDefPtr virSysinfoRead(void);
void virSysinfoBIOSDefFree(virSysinfoBIOSDefPtr def);
void virSysinfoDefFree(virSysinfoDefPtr def); void virSysinfoDefFree(virSysinfoDefPtr def);
int virSysinfoFormat(virBufferPtr buf, virSysinfoDefPtr def) int virSysinfoFormat(virBufferPtr buf, virSysinfoDefPtr def)