mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-10 05:17:59 +03:00
Refactor major.minor.micro version parsing into a function
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.
This commit is contained in:
parent
ea54570efb
commit
56bac4a221
@ -684,34 +684,17 @@ static int
|
||||
esxGetVersion(virConnectPtr conn, unsigned long *version)
|
||||
{
|
||||
esxPrivate *priv = conn->privateData;
|
||||
char *temp;
|
||||
unsigned int major, minor, release;
|
||||
|
||||
temp = (char *)priv->host->service->about->version;
|
||||
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);
|
||||
|
||||
/* Expecting 'major.minor.release' format */
|
||||
if (virStrToLong_ui(temp, &temp, 10, &major) < 0 || *temp != '.') {
|
||||
goto failure;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virStrToLong_ui(temp + 1, &temp, 10, &minor) < 0 || *temp != '.') {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (virStrToLong_ui(temp + 1, NULL, 10, &release) < 0) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
*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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -57,6 +57,7 @@
|
||||
# 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))))
|
||||
|
@ -648,6 +648,7 @@ virFilePid;
|
||||
virFileReadPid;
|
||||
virFileLinkPointsTo;
|
||||
virParseNumber;
|
||||
virParseVersionString;
|
||||
virPipeReadUntilEOF;
|
||||
virAsprintf;
|
||||
virRun;
|
||||
|
@ -1951,20 +1951,14 @@ lxcActive(void) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -78,8 +78,8 @@ openvzExtractVersionInfo(const char *cmd, int *retversion)
|
||||
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;
|
||||
@ -93,12 +93,14 @@ openvzExtractVersionInfo(const char *cmd, int *retversion)
|
||||
if (len < 0)
|
||||
goto cleanup2;
|
||||
|
||||
if (sscanf(help, "vzctl version %u.%u.%u",
|
||||
&major, &minor, µ) != 3) {
|
||||
goto cleanup2;
|
||||
}
|
||||
tmp = help;
|
||||
|
||||
version = (major * 1000 * 1000) + (minor * 1000) + micro;
|
||||
/* expected format: vzctl version <major>.<minor>.<micro> */
|
||||
if ((tmp = STRSKIP(tmp, "vzctl version ")) == NULL)
|
||||
goto cleanup2;
|
||||
|
||||
if (virParseVersionString(tmp, &version) < 0)
|
||||
goto cleanup2;
|
||||
|
||||
if (retversion)
|
||||
*retversion = version;
|
||||
|
@ -44,7 +44,7 @@ struct uml_driver {
|
||||
|
||||
int privileged;
|
||||
|
||||
unsigned int umlVersion;
|
||||
unsigned long umlVersion;
|
||||
int nextvmid;
|
||||
|
||||
virDomainObjList domains;
|
||||
|
@ -1225,17 +1225,18 @@ cleanup:
|
||||
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;
|
||||
|
@ -2074,6 +2074,41 @@ virParseNumber(const char **str)
|
||||
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
|
||||
*
|
||||
|
@ -189,6 +189,7 @@ 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 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;
|
||||
|
@ -157,7 +157,7 @@ if (strUtf16) {\
|
||||
|
||||
typedef struct {
|
||||
virMutex lock;
|
||||
int version;
|
||||
unsigned long version;
|
||||
|
||||
virCapsPtr caps;
|
||||
|
||||
@ -713,10 +713,7 @@ cleanup:
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@ -729,20 +726,17 @@ static int vboxExtractVersion(virConnectPtr conn, vboxGlobalData *data) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -253,9 +253,8 @@ xenapiGetVersion (virConnectPtr conn, unsigned long *hvVer)
|
||||
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;
|
||||
@ -278,18 +277,17 @@ xenapiGetVersion (virConnectPtr conn, unsigned long *hvVer)
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user