mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 06:05:27 +00:00
esx: Replace scanf with STRSKIP and strtok_r
This also fixes a portability problem with the %a format modifier. %a is not portable and made esxDomainDumpXML fail at runtime in MinGW builds.
This commit is contained in:
parent
7ca6a0996d
commit
3a7f2fc3b2
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 (*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 (*parsedHostCpuIdInfo));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user