ESX(i) uses UTF-8, but a Windows based GSX server writes
Windows-1252 encoded VMX files.
---
src/esx/esx_util.c | 48 +++++++++++++++++++++++++++++++++++++++++++++---
src/esx/esx_util.h | 2 ++
src/esx/esx_vmx.c | 33 +++++++++++++++++++++++++++++++++
tests/esxutilstest.c | 41 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 121 insertions(+), 3 deletions(-)
diff --git a/src/esx/esx_util.c b/src/esx/esx_util.c
index 5fe72fc..b3c927a 100644
--- a/src/esx/esx_util.c
+++ b/src/esx/esx_util.c
@@ -612,9 +612,9 @@ esxUtil_ReformatUuid(const char *input, char *output)
unsigned char uuid[VIR_UUID_BUFLEN];
if (virUUIDParse(input, uuid) < 0) {
- ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Could not parse UUID from string '%s'"),
- input);
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse UUID from string '%s'"),
+ input);
return -1;
}
@@ -819,3 +819,45 @@ esxUtil_EscapeDatastoreItem(const char *string)
return escaped2;
}
+
+
+
+char *
+esxUtil_ConvertWindows1252ToUTF8(const char *string)
+{
+ char *result = NULL;
+ xmlCharEncodingHandlerPtr handler;
+ xmlBufferPtr windows1252;
+ xmlBufferPtr utf8;
+
+ handler = xmlFindCharEncodingHandler("Windows-1252");
+
+ if (handler == NULL) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("libxml2 doesn't handle Windows-1252 encoding"));
+ return NULL;
+ }
+
+ windows1252 = xmlBufferCreateStatic((char *)string, strlen(string));
+ utf8 = xmlBufferCreate();
+
+ if (xmlCharEncInFunc(handler, utf8, windows1252) < 0) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not convert from Windows-1252 to UTF-8 encoding"));
+ goto cleanup;
+ }
+
+ result = strdup((const char *)xmlBufferContent(utf8));
+
+ if (result == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ cleanup:
+ xmlCharEncCloseFunc(handler);
+ xmlBufferFree(windows1252);
+ xmlBufferFree(utf8);
+
+ return result;
+}
diff --git a/src/esx/esx_util.h b/src/esx/esx_util.h
index 669a4f2..9906459 100644
--- a/src/esx/esx_util.h
+++ b/src/esx/esx_util.h
@@ -89,4 +89,6 @@ void esxUtil_ReplaceSpecialWindowsPathChars(char *string);
char *esxUtil_EscapeDatastoreItem(const char *string);
+char *esxUtil_ConvertWindows1252ToUTF8(const char *string);
+
#endif /* __ESX_UTIL_H__ */
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index 7dc8e60..016cb75 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -868,6 +868,8 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char
*vmx,
{
bool success = false;
virConfPtr conf = NULL;
+ char *encoding = NULL;
+ char *utf8;
virDomainDefPtr def = NULL;
long long config_version = 0;
long long virtualHW_version = 0;
@@ -895,6 +897,36 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char
*vmx,
return NULL;
}
+ /* vmx:.encoding */
+ if (esxUtil_GetConfigString(conf, ".encoding", &encoding, true) < 0)
{
+ goto cleanup;
+ }
+
+ if (encoding == NULL || STRCASEEQ(encoding, "UTF-8")) {
+ /* nothing */
+ } else if (STRCASEEQ(encoding, "Windows-1252")) {
+ virConfFree(conf);
+
+ utf8 = esxUtil_ConvertWindows1252ToUTF8(vmx);
+
+ if (utf8 == NULL) {
+ goto cleanup;
+ }
+
+ conf = virConfReadMem(utf8, strlen(utf8), VIR_CONF_FLAG_VMX_FORMAT);
+
+ VIR_FREE(utf8);
+
+ if (conf == NULL) {
+ goto cleanup;
+ }
+ } else {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("VMX file has unsupported encoding '%s'"),
encoding);
+ goto cleanup;
+ }
+
+ /* Allocate domain def */
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
return NULL;
@@ -1359,6 +1391,7 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char
*vmx,
}
virConfFree(conf);
+ VIR_FREE(encoding);
VIR_FREE(sched_cpu_affinity);
VIR_FREE(guestOS);
diff --git a/tests/esxutilstest.c b/tests/esxutilstest.c
index d4042c2..5f3b6f2 100644
--- a/tests/esxutilstest.c
+++ b/tests/esxutilstest.c
@@ -280,6 +280,46 @@ testEscapeDatastoreItem(const void *data ATTRIBUTE_UNUSED)
+struct testWindows1252ToUTF8 {
+ const char *windows1252;
+ const char *utf8;
+};
+
+static struct testWindows1252ToUTF8 windows1252ToUTF8[] = {
+ { "normal", "normal" },
+ { /* "A€Z" */ "A\200Z", "A\342\202\254Z" },
+ { /* "Aä1ö2ü3ß4#5~6!7§8/9%Z" */
"A\3441\3662\3743\3374#5~6!7\2478/9%Z",
+ "A\303\2441\303\2662\303\2743\303\2374#5~6!7\302\2478/9%Z" },
+ { /* "hÀÁÂÃÄÅH" */ "h\300\301\302\303\304\305H",
+ "h\303\200\303\201\303\202\303\203\303\204\303\205H" },
+};
+
+static int
+testConvertWindows1252ToUTF8(const void *data ATTRIBUTE_UNUSED)
+{
+ int i;
+ char *utf8 = NULL;
+
+ for (i = 0; i < ARRAY_CARDINALITY(windows1252ToUTF8); ++i) {
+ VIR_FREE(utf8);
+
+ utf8 = esxUtil_ConvertWindows1252ToUTF8(windows1252ToUTF8[i].windows1252);
+
+ if (utf8 == NULL) {
+ return -1;
+ }
+
+ if (STRNEQ(windows1252ToUTF8[i].utf8, utf8)) {
+ VIR_FREE(utf8);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+
static int
mymain(int argc, char **argv)
{
@@ -312,6 +352,7 @@ mymain(int argc, char **argv)
DO_TEST(ParseDatastorePath);
DO_TEST(ConvertDateTimeToCalendarTime);
DO_TEST(EscapeDatastoreItem);
+ DO_TEST(ConvertWindows1252ToUTF8);
return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
--
1.7.0.4