From 8ce1afff882e09575f9f5cb499e806d5cefde47d Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 1 Jul 2011 07:23:02 -0600 Subject: util: choose whether to require micro in version strings To avoid regressions, we let callers specify whether to require a minor and micro version. Callers that were parsing uname() output benefit from defaulting to 0, whereas callers that were parsing version strings from other sources should not change in behavior. * src/util/util.c (virParseVersionString): Allow caller to choose whether to fail if minor or micro is missing. * src/util/util.h (virParseVersionString): Update signature. * src/esx/esx_driver.c (esxGetVersion): Update callers. * src/lxc/lxc_driver.c (lxcVersion): Likewise. * src/openvz/openvz_conf.c (openvzExtractVersionInfo): Likewise. * src/uml/uml_driver.c (umlGetVersion): Likewise. * src/vbox/vbox_MSCOMGlue.c (vboxLookupVersionInRegistry): Likewise. * src/vbox/vbox_tmpl.c (vboxExtractVersion): Likewise. * src/vmware/vmware_conf.c (vmwareExtractVersion): Likewise. * src/xenapi/xenapi_driver.c (xenapiGetVersion): Likewise. Reported by Matthias Bolte. --- src/esx/esx_driver.c | 2 +- src/lxc/lxc_driver.c | 2 +- src/openvz/openvz_conf.c | 2 +- src/uml/uml_driver.c | 2 +- src/util/util.c | 14 +++++++++++++- src/util/util.h | 3 ++- src/vbox/vbox_MSCOMGlue.c | 2 +- src/vbox/vbox_tmpl.c | 2 +- src/vmware/vmware_conf.c | 2 +- src/xenapi/xenapi_driver.c | 2 +- 10 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 3a140e96c..a6e47a40a 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -1202,7 +1202,7 @@ esxGetVersion(virConnectPtr conn, unsigned long *version) esxPrivate *priv = conn->privateData; if (virParseVersionString(priv->primary->service->about->version, - version) < 0) { + version, false) < 0) { ESX_ERROR(VIR_ERR_INTERNAL_ERROR, _("Could not parse version number from '%s'"), priv->primary->service->about->version); diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index d0f715860..7220a9b64 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2249,7 +2249,7 @@ static int lxcVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *versio uname(&ver); - if (virParseVersionString(ver.release, version) < 0) { + if (virParseVersionString(ver.release, version, true) < 0) { lxcError(VIR_ERR_INTERNAL_ERROR, _("Unknown release: %s"), ver.release); return -1; } diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c index 189279dbe..561cc990d 100644 --- a/src/openvz/openvz_conf.c +++ b/src/openvz/openvz_conf.c @@ -99,7 +99,7 @@ openvzExtractVersionInfo(const char *cmdstr, int *retversion) if ((tmp = STRSKIP(tmp, "vzctl version ")) == NULL) goto cleanup; - if (virParseVersionString(tmp, &version) < 0) + if (virParseVersionString(tmp, &version, false) < 0) goto cleanup; if (retversion) diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index e557fe89c..a71ea2174 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -1227,7 +1227,7 @@ static int umlGetVersion(virConnectPtr conn, unsigned long *version) { if (driver->umlVersion == 0) { uname(&ut); - if (virParseVersionString(ut.release, &driver->umlVersion) < 0) { + if (virParseVersionString(ut.release, &driver->umlVersion, true) < 0) { umlReportError(VIR_ERR_INTERNAL_ERROR, _("cannot parse version %s"), ut.release); goto cleanup; diff --git a/src/util/util.c b/src/util/util.c index da2485998..13973c359 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -1585,6 +1585,8 @@ virParseNumber(const char **str) * virParseVersionString: * @str: const char pointer to the version string * @version: unsigned long pointer to output the version number + * @allowMissing: true to treat 3 like 3.0.0, false to error out on + * missing minor or micro * * Parse an unsigned version number from a version string. Expecting * 'major.minor.micro' format, ignoring an optional suffix. @@ -1596,7 +1598,8 @@ virParseNumber(const char **str) * Returns the 0 for success, -1 for error. */ int -virParseVersionString(const char *str, unsigned long *version) +virParseVersionString(const char *str, unsigned long *version, + bool allowMissing) { unsigned int major, minor = 0, micro = 0; char *tmp; @@ -1604,12 +1607,21 @@ virParseVersionString(const char *str, unsigned long *version) if (virStrToLong_ui(str, &tmp, 10, &major) < 0) return -1; + if (!allowMissing && *tmp != '.') + return -1; + if ((*tmp == '.') && virStrToLong_ui(tmp + 1, &tmp, 10, &minor) < 0) return -1; + if (!allowMissing && *tmp != '.') + return -1; + if ((*tmp == '.') && virStrToLong_ui(tmp + 1, &tmp, 10, µ) < 0) return -1; + if (major > UINT_MAX / 1000000 || minor > 999 || micro > 999) + return -1; + *version = 1000000 * major + 1000 * minor + micro; return 0; diff --git a/src/util/util.h b/src/util/util.h index 0c43f7a77..155565364 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -168,7 +168,8 @@ int virMacAddrCompare (const char *mac1, const char *mac2); void virSkipSpaces(const char **str); int virParseNumber(const char **str); -int virParseVersionString(const char *str, unsigned long *version); +int virParseVersionString(const char *str, unsigned long *version, + bool allowMissing); int virAsprintf(char **strp, const char *fmt, ...) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_FMT_PRINTF(2, 3); int virVasprintf(char **strp, const char *fmt, va_list list) diff --git a/src/vbox/vbox_MSCOMGlue.c b/src/vbox/vbox_MSCOMGlue.c index 8aef2660c..31e14a14c 100644 --- a/src/vbox/vbox_MSCOMGlue.c +++ b/src/vbox/vbox_MSCOMGlue.c @@ -430,7 +430,7 @@ vboxLookupVersionInRegistry(void) } } - if (virParseVersionString(value, &vboxVersion) < 0) { + if (virParseVersionString(value, &vboxVersion, false) < 0) { VIR_ERROR(_("Could not parse version number from '%s'"), value); goto cleanup; } diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 7fd120078..37fe248f3 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -929,7 +929,7 @@ static int vboxExtractVersion(vboxGlobalData *data) { VBOX_UTF16_TO_UTF8(versionUtf16, &vboxVersion); - if (virParseVersionString(vboxVersion, &data->version) >= 0) + if (virParseVersionString(vboxVersion, &data->version, false) >= 0) ret = 0; VBOX_UTF8_FREE(vboxVersion); diff --git a/src/vmware/vmware_conf.c b/src/vmware/vmware_conf.c index 4ec33aebd..044784ef6 100644 --- a/src/vmware/vmware_conf.c +++ b/src/vmware/vmware_conf.c @@ -248,7 +248,7 @@ vmwareExtractVersion(struct vmware_driver *driver) goto cleanup; } - if (virParseVersionString(tmp, &version) < 0) { + if (virParseVersionString(tmp, &version, false) < 0) { vmwareError(VIR_ERR_INTERNAL_ERROR, "%s", _("version parsing error")); goto cleanup; diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 77d17ee96..0a618ab3b 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -302,7 +302,7 @@ xenapiGetVersion (virConnectPtr conn, unsigned long *hvVer) } } if (version) { - if (virParseVersionString(version, hvVer) < 0) + if (virParseVersionString(version, hvVer, false) < 0) xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, _("Couldn't parse version info")); else -- cgit v1.2.3-65-gdbad