This also fixes a portability problem with the %a format modifier.
%a is not portable and made esxDomainDumpXML fail at runtime in
MinGW builds.
Pull in strtok_r from gnulib, because MinGW lacks it.
---
bootstrap.conf | 1 +
src/esx/esx_driver.c | 19 +++--------------
src/esx/esx_util.c | 53 +++++++++++++++++++++++++------------------------
src/esx/esx_vi.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++
src/esx/esx_vi.h | 12 +++++++++++
src/esx/esx_vmx.c | 16 +++++++++++---
6 files changed, 106 insertions(+), 45 deletions(-)
diff --git a/bootstrap.conf b/bootstrap.conf
index d807e40..785489b 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -54,6 +54,7 @@ strndup
strerror
strptime
strsep
+strtok_r
sys_stat
time_r
timegm
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index a2fc85c..f22634e 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -60,8 +60,8 @@ esxSupportsLongMode(esxPrivate *priv)
esxVI_DynamicProperty *dynamicProperty = NULL;
esxVI_HostCpuIdInfo *hostCpuIdInfoList = NULL;
esxVI_HostCpuIdInfo *hostCpuIdInfo = NULL;
+ esxVI_ParsedHostCpuIdInfo parsedHostCpuIdInfo;
char edxLongModeBit = '?';
- char edxFirstBit = '?';
if (priv->supportsLongMode != esxVI_Boolean_Undefined) {
return priv->supportsLongMode;
@@ -96,23 +96,12 @@ esxSupportsLongMode(esxPrivate *priv)
for (hostCpuIdInfo = hostCpuIdInfoList; hostCpuIdInfo != NULL;
hostCpuIdInfo = hostCpuIdInfo->_next) {
if (hostCpuIdInfo->level->value == -2147483647) { /* 0x80000001 */
-#define _SKIP4 "%*c%*c%*c%*c"
-#define _SKIP12 _SKIP4":"_SKIP4":"_SKIP4
-
- /* Expected format:
"--X-:----:----:----:----:----:----:----" */
- if (sscanf(hostCpuIdInfo->edx,
-
"%*c%*c%c%*c:"_SKIP12":"_SKIP12":%*c%*c%*c%c",
- &edxLongModeBit, &edxFirstBit) != 2) {
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("HostSystem property
'hardware.cpuFeature[].edx' "
- "with value '%s' doesn't have
expected format "
-
"'----:----:----:----:----:----:----:----'"),
- hostCpuIdInfo->edx);
+ if (esxVI_ParseHostCpuIdInfo(&parsedHostCpuIdInfo,
+ hostCpuIdInfo) < 0) {
goto failure;
}
-#undef _SKIP4
-#undef _SKIP12
+ edxLongModeBit = parsedHostCpuIdInfo.edx[29];
if (edxLongModeBit == '1') {
priv->supportsLongMode = esxVI_Boolean_True;
diff --git a/src/esx/esx_util.c b/src/esx/esx_util.c
index 963f52e..91d19e9 100644
--- a/src/esx/esx_util.c
+++ b/src/esx/esx_util.c
@@ -203,6 +203,10 @@ esxUtil_ParseDatastoreRelatedPath(const char *datastoreRelatedPath,
char **directoryName, char **fileName)
{
int result = 0;
+ char *copyOfDatastoreRelatedPath = NULL;
+ char *tmp = NULL;
+ char *saveptr = NULL;
+ char *preliminaryDatastoreName = NULL;
char *directoryAndFileName = NULL;
char *separator = NULL;
@@ -213,37 +217,34 @@ esxUtil_ParseDatastoreRelatedPath(const char *datastoreRelatedPath,
return -1;
}
- /*
- * Parse string as '[<datastore>] <path>'. '%as' is
similar to '%s', but
- * sscanf() will allocate the memory for the string, so the caller doesn't
- * need to preallocate a buffer that's large enough.
- *
- * The s in '%as' can be replaced with a character set, e.g. [a-z].
- *
- * '%a[^]%]' matches <datastore>. '[^]%]' excludes ']'
from the accepted
- * characters, otherwise sscanf() wont match what it should.
- *
- * '%a[^\n]' matches <path>. '[^\n]' excludes '\n' from
the accepted
- * characters, otherwise sscanf() would only match up to the first space,
- * but spaces are valid in <path>.
- */
- if (sscanf(datastoreRelatedPath, "[%a[^]%]] %a[^\n]", datastoreName,
- &directoryAndFileName) != 2) {
+ if (esxVI_String_DeepCopyValue(©OfDatastoreRelatedPath,
+ datastoreRelatedPath) < 0) {
+ goto failure;
+ }
+
+ /* Expected format: '[<datastore>] <path>' */
+ if ((tmp = STRSKIP(copyOfDatastoreRelatedPath, "[")) == NULL ||
+ (preliminaryDatastoreName = strtok_r(tmp, "]", &saveptr)) == NULL
||
+ (directoryAndFileName = strtok_r(NULL, "", &saveptr)) == NULL) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Datastore related path '%s' doesn't have expected
format "
"'[<datastore>] <path>'"),
datastoreRelatedPath);
goto failure;
}
+ if (esxVI_String_DeepCopyValue(datastoreName,
+ preliminaryDatastoreName) < 0) {
+ goto failure;
+ }
+
+ directoryAndFileName += strspn(directoryAndFileName, " ");
+
/* Split <path> into <directory>/<file>, where <directory> is
optional */
separator = strrchr(directoryAndFileName, '/');
if (separator != NULL) {
*separator++ = '\0';
- *directoryName = directoryAndFileName;
- directoryAndFileName = NULL;
-
if (*separator == '\0') {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Datastore related path '%s' doesn't reference a
file"),
@@ -251,19 +252,19 @@ esxUtil_ParseDatastoreRelatedPath(const char *datastoreRelatedPath,
goto failure;
}
- *fileName = strdup(separator);
-
- if (*fileName == NULL) {
- virReportOOMError();
+ if (esxVI_String_DeepCopyValue(directoryName,
+ directoryAndFileName) < 0 ||
+ esxVI_String_DeepCopyValue(fileName, separator) < 0) {
goto failure;
}
} else {
- *fileName = directoryAndFileName;
- directoryAndFileName = NULL;
+ if (esxVI_String_DeepCopyValue(fileName, directoryAndFileName) < 0) {
+ goto failure;
+ }
}
cleanup:
- VIR_FREE(directoryAndFileName);
+ VIR_FREE(copyOfDatastoreRelatedPath);
return result;
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 4318ff1..db8c927 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -2886,3 +2886,53 @@ esxVI_WaitForTaskCompletion(esxVI_Context *ctx,
goto cleanup;
}
+
+
+
+int
+esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo *parsedhostCpuIdInfo,
+ esxVI_HostCpuIdInfo *hostCpuIdInfo)
+{
+ int expectedLength = 39; /* =
strlen("----:----:----:----:----:----:----:----"); */
+ char *input[4] = { hostCpuIdInfo->eax, hostCpuIdInfo->ebx,
+ hostCpuIdInfo->ecx, hostCpuIdInfo->edx };
+ char *output[4] = { parsedhostCpuIdInfo->eax, parsedhostCpuIdInfo->ebx,
+ parsedhostCpuIdInfo->ecx, parsedhostCpuIdInfo->edx };
+ const char *name[4] = { "eax", "ebx", "ecx",
"edx" };
+ int r, i, o;
+
+ memset(parsedhostCpuIdInfo, 0, sizeof (esxVI_ParsedHostCpuIdInfo));
+
+ parsedhostCpuIdInfo->level = hostCpuIdInfo->level->value;
+
+ for (r = 0; r < 4; ++r) {
+ if (strlen(input[r]) != expectedLength) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("HostCpuIdInfo register '%s' has an unexpected
length"),
+ name[r]);
+ goto failure;
+ }
+
+ /* Strip the ':' and invert the "bit" order from 31..0 to 0..31
*/
+ for (i = 0, o = 31; i < expectedLength; i += 5, o -= 4) {
+ output[r][o] = input[r][i];
+ output[r][o - 1] = input[r][i + 1];
+ output[r][o - 2] = input[r][i + 2];
+ output[r][o - 3] = input[r][i + 3];
+
+ if (i + 4 < expectedLength && input[r][i + 4] != ':') {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("HostCpuIdInfo register '%s' has an
unexpected format"),
+ name[r]);
+ goto failure;
+ }
+ }
+ }
+
+ return 0;
+
+ failure:
+ memset(parsedhostCpuIdInfo, 0, sizeof (esxVI_ParsedHostCpuIdInfo));
+
+ return -1;
+}
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index a8d4cc3..45b83f5 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -43,6 +43,7 @@
typedef enum _esxVI_APIVersion esxVI_APIVersion;
typedef enum _esxVI_ProductVersion esxVI_ProductVersion;
typedef enum _esxVI_Occurrence esxVI_Occurrence;
+typedef struct _esxVI_ParsedHostCpuIdInfo esxVI_ParsedHostCpuIdInfo;
typedef struct _esxVI_Context esxVI_Context;
typedef struct _esxVI_Response esxVI_Response;
typedef struct _esxVI_Enumeration esxVI_Enumeration;
@@ -76,6 +77,14 @@ enum _esxVI_Occurrence {
esxVI_Occurrence_None
};
+struct _esxVI_ParsedHostCpuIdInfo {
+ int level;
+ char eax[32];
+ char ebx[32];
+ char ecx[32];
+ char edx[32];
+};
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -313,4 +322,7 @@ int esxVI_WaitForTaskCompletion(esxVI_Context *ctx,
esxVI_Boolean autoAnswer,
esxVI_TaskInfoState *finalState);
+int esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo *parsedhostCpuIdInfo,
+ esxVI_HostCpuIdInfo *hostCpuIdInfo);
+
#endif /* __ESX_VI_H__ */
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index c965e00..c2e9be6 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -589,6 +589,9 @@ char *
esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,
const char *absolutePath)
{
+ char *copyOfAbsolutePath = NULL;
+ char *tmp = NULL;
+ char *saveptr = NULL;
char *datastoreRelatedPath = NULL;
char *preliminaryDatastoreName = NULL;
char *directoryAndFileName = NULL;
@@ -596,8 +599,14 @@ esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,
esxVI_ObjectContent *datastore = NULL;
const char *datastoreName = NULL;
- if (sscanf(absolutePath, "/vmfs/volumes/%a[^/]/%a[^\n]",
- &preliminaryDatastoreName, &directoryAndFileName) != 2) {
+ if (esxVI_String_DeepCopyValue(©OfAbsolutePath, absolutePath) < 0) {
+ goto failure;
+ }
+
+ /* Expected format: '/vmfs/volumes/<datastore>/<path>' */
+ if ((tmp = STRSKIP(copyOfAbsolutePath, "/vmfs/volumes/")) == NULL ||
+ (preliminaryDatastoreName = strtok_r(tmp, "/", &saveptr)) == NULL
||
+ (directoryAndFileName = strtok_r(NULL, "", &saveptr)) == NULL) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Absolute path '%s' doesn't have expected format
"
"'/vmfs/volumes/<datastore>/<path>'"),
absolutePath);
@@ -652,8 +661,7 @@ esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,
/* FIXME: Check if referenced path/file really exists */
cleanup:
- VIR_FREE(preliminaryDatastoreName);
- VIR_FREE(directoryAndFileName);
+ VIR_FREE(copyOfAbsolutePath);
esxVI_ObjectContent_Free(&datastore);
return datastoreRelatedPath;
--
1.6.3.3