virParseVersionString uses virStrToLong_ui instead of sscanf.
This also fixes a bug in the UML driver, that always returned 0
as version number.
Introduce STRSKIP to check if a string has a certain prefix and
to skip this prefix.
esxGetVersion(virConnectPtr conn, unsigned long *version)
{
esxPrivate *priv = conn->privateData;
- char *temp;
- unsigned int major, minor, release;
- temp = (char *)priv->host->service->about->version;
-
- /* Expecting 'major.minor.release' format */
- if (virStrToLong_ui(temp, &temp, 10, &major) < 0 || *temp != '.') {
- goto failure;
- }
-
- if (virStrToLong_ui(temp + 1, &temp, 10, &minor) < 0 || *temp != '.') {
- goto failure;
- }
+ if (virParseVersionString(priv->host->service->about->version,
+ version) < 0) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ "Could not parse version number from '%s'",
+ priv->host->service->about->version);
- if (virStrToLong_ui(temp + 1, NULL, 10, &release) < 0) {
- goto failure;
+ return -1;
}
- *version = 1000000 * major + 1000 * minor + release;
-
return 0;
-
- failure:
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- "Expecting version to match 'major.minor.release', but got '%s'",
- priv->host->service->about->version);
-
- return -1;
}
# define STRNEQLEN(a,b,n) (strncmp(a,b,n) != 0)
# define STRCASENEQLEN(a,b,n) (strncasecmp(a,b,n) != 0)
# define STRPREFIX(a,b) (strncmp(a,b,strlen(b)) == 0)
+# define STRSKIP(a,b) (STRPREFIX(a,b) ? (a) + strlen(b) : NULL)
# define STREQ_NULLABLE(a, b) \
((!(a) && !(b)) || ((a) && (b) && STREQ((a), (b))))
virFileReadPid;
virFileLinkPointsTo;
virParseNumber;
+virParseVersionString;
virPipeReadUntilEOF;
virAsprintf;
virRun;
static int lxcVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *version)
{
struct utsname ver;
- int maj;
- int min;
- int rev;
uname(&ver);
- if (sscanf(ver.release, "%i.%i.%i", &maj, &min, &rev) != 3) {
- lxcError(VIR_ERR_INTERNAL_ERROR,
- _("Unknown release: %s"), ver.release);
+ if (virParseVersionString(ver.release, version) < 0) {
+ lxcError(VIR_ERR_INTERNAL_ERROR, _("Unknown release: %s"), ver.release);
return -1;
}
- *version = (maj * 1000 * 1000) + (min * 1000) + rev;
-
return 0;
}
pid_t child;
int newstdout = -1;
int ret = -1, status;
- unsigned int major, minor, micro;
- unsigned int version;
+ unsigned long version;
+ char *tmp;
if (retversion)
*retversion = 0;
if (len < 0)
goto cleanup2;
- if (sscanf(help, "vzctl version %u.%u.%u",
- &major, &minor, µ) != 3) {
+ tmp = help;
+
+ /* expected format: vzctl version <major>.<minor>.<micro> */
+ if ((tmp = STRSKIP(tmp, "vzctl version ")) == NULL)
goto cleanup2;
- }
- version = (major * 1000 * 1000) + (minor * 1000) + micro;
+ if (virParseVersionString(tmp, &version) < 0)
+ goto cleanup2;
if (retversion)
*retversion = version;
int privileged;
- unsigned int umlVersion;
+ unsigned long umlVersion;
int nextvmid;
virDomainObjList domains;
static int umlGetVersion(virConnectPtr conn, unsigned long *version) {
struct uml_driver *driver = conn->privateData;
struct utsname ut;
- int major, minor, micro;
int ret = -1;
- uname(&ut);
-
umlDriverLock(driver);
- if (sscanf(ut.release, "%u.%u.%u",
- &major, &minor, µ) != 3) {
- umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("cannot parse version %s"), ut.release);
- goto cleanup;
+
+ if (driver->umlVersion == 0) {
+ uname(&ut);
+
+ if (virParseVersionString(ut.release, &driver->umlVersion) < 0) {
+ umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse version %s"), ut.release);
+ goto cleanup;
+ }
}
*version = driver->umlVersion;
return (ret);
}
+
+/**
+ * virParseVersionString:
+ * @str: const char pointer to the version string
+ * @version: unsigned long pointer to output the version number
+ *
+ * Parse an unsigned version number from a version string. Expecting
+ * 'major.minor.micro' format, ignoring an optional suffix.
+ *
+ * The major, minor and micro numbers are encoded into a single version number:
+ *
+ * 1000000 * major + 1000 * minor + micro
+ *
+ * Returns the 0 for success, -1 for error.
+ */
+int
+virParseVersionString(const char *str, unsigned long *version)
+{
+ unsigned int major, minor, micro;
+ char *tmp;
+
+ if (virStrToLong_ui(str, &tmp, 10, &major) < 0 || *tmp != '.')
+ return -1;
+
+ if (virStrToLong_ui(tmp + 1, &tmp, 10, &minor) < 0 || *tmp != '.')
+ return -1;
+
+ if (virStrToLong_ui(tmp + 1, &tmp, 10, µ) < 0)
+ return -1;
+
+ *version = 1000000 * major + 1000 * minor + micro;
+
+ return 0;
+}
+
/**
* virAsprintf
*
void virSkipSpaces(const char **str);
int virParseNumber(const char **str);
+int virParseVersionString(const char *str, unsigned long *version);
int virAsprintf(char **strp, const char *fmt, ...) ATTRIBUTE_FMT_PRINTF(2, 3);
char *virStrncpy(char *dest, const char *src, size_t n, size_t destbytes)
ATTRIBUTE_RETURN_CHECK;
typedef struct {
virMutex lock;
- int version;
+ unsigned long version;
virCapsPtr caps;
}
static int vboxExtractVersion(virConnectPtr conn, vboxGlobalData *data) {
- unsigned int major = 0;
- unsigned int minor = 0;
- unsigned int micro = 0;
- int ret = -1;
+ int ret = -1;
PRUnichar *versionUtf16 = NULL;
nsresult rc;
VBOX_UTF16_TO_UTF8(versionUtf16, &vboxVersion);
- if (sscanf(vboxVersion, "%u.%u.%u", &major, &minor, µ) == 3)
+ if (virParseVersionString(vboxVersion, &data->version) >= 0)
ret = 0;
VBOX_UTF8_FREE(vboxVersion);
VBOX_COM_UNALLOC_MEM(versionUtf16);
- } else {
- ret = -1;
}
- data->version = (major * 1000 * 1000) + (minor * 1000) + micro;
-
if (ret != 0)
vboxError(conn, VIR_ERR_INTERNAL_ERROR,"%s",
"Cound not extract VirtualBox version");
+
return ret;
}
xen_host host;
xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session;
xen_string_string_map *result = NULL;
- int i;
+ int i, ret = -1;
char *version = NULL;
- unsigned long major = 0, minor = 0, release = 0;
if (!(xen_session_get_this_host(session, &host, session))) {
xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
return -1;
}
}
if (version) {
- if (sscanf(version, "%ld.%ld.%ld", &major, &minor, &release) != 3) {
+ if (virParseVersionString(version, hvVer) < 0)
xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR,
- _("Couldn't get version info"));
- xen_string_string_map_free(result);
- VIR_FREE(version);
- return -1;
- }
- *hvVer = major * 1000000 + minor * 1000 + release;
- VIR_FREE(version);
+ _("Couldn't parse version info"));
+ else
+ ret = 0;
xen_string_string_map_free(result);
- return 0;
+ VIR_FREE(version);
+ return ret;
}
+ xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Couldn't get version info"));
}
return -1;
}