return out;
}
+char *qemuMonitorUnescapeArg(const char *in)
+{
+ int i, j;
+ char *out;
+ int len = strlen(in) + 1;
+ char next;
+
+ if (VIR_ALLOC_N(out, len) < 0)
+ return NULL;
+
+ for (i = j = 0; i < len; ++i) {
+ next = in[i];
+ if (in[i] == '\\') {
+ if (len < i + 1) {
+ /* trailing backslash shouldn't be possible */
+ VIR_FREE(out);
+ return NULL;
+ }
+ ++i;
+ switch(in[i]) {
+ case 'r':
+ next = '\r';
+ break;
+ case 'n':
+ next = '\n';
+ break;
+ case '"':
+ case '\\':
+ next = in[i];
+ break;
+ default:
+ /* invalid input */
+ VIR_FREE(out);
+ return NULL;
+ }
+ }
+ out[j++] = next;
+ }
+ out[j] = '\0';
+
+ return out;
+}
+
#if DEBUG_RAW_IO
# include <c-ctype.h>
static char * qemuMonitorEscapeNonPrintable(const char *text)
int scm_fd,
char **reply)
{
- if (mon->json)
- return qemuMonitorJSONHumanCommandWithFd(mon, cmd, scm_fd, reply);
- else
- return qemuMonitorTextCommandWithFd(mon, cmd, scm_fd, reply);
+ char *json_cmd = NULL;
+ int ret = -1;
+
+ if (mon->json) {
+ /* hack to avoid complicating each call to text monitor functions */
+ json_cmd = qemuMonitorUnescapeArg(cmd);
+ if (!json_cmd) {
+ VIR_DEBUG("Could not unescape command: %s", cmd);
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to unescape command"));
+ goto cleanup;
+ }
+ ret = qemuMonitorJSONHumanCommandWithFd(mon, json_cmd, scm_fd, reply);
+ } else {
+ ret = qemuMonitorTextCommandWithFd(mon, cmd, scm_fd, reply);
+ }
+
+cleanup:
+ VIR_FREE(json_cmd);
+ return ret;
}
/* Ensure proper locking around callbacks. */
nwfilterxml2xmlout \
oomtrace.pl \
qemuhelpdata \
+ qemumonitortest \
qemuxml2argvdata \
qemuxml2xmloutdata \
qemuxmlnsdata \
endif
if WITH_QEMU
check_PROGRAMS += qemuxml2argvtest qemuxml2xmltest qemuxmlnstest \
- qemuargv2xmltest qemuhelptest domainsnapshotxml2xmltest
+ qemuargv2xmltest qemuhelptest domainsnapshotxml2xmltest \
+ qemumonitortest
endif
if WITH_OPENVZ
if WITH_QEMU
TESTS += qemuxml2argvtest qemuxml2xmltest qemuxmlnstest qemuargv2xmltest \
- qemuhelptest domainsnapshotxml2xmltest nwfilterxml2xmltest
+ qemuhelptest domainsnapshotxml2xmltest nwfilterxml2xmltest \
+ qemumonitortest
endif
if WITH_OPENVZ
qemuhelptest_SOURCES = qemuhelptest.c testutils.c testutils.h
qemuhelptest_LDADD = $(qemu_LDADDS) $(LDADDS)
+qemumonitortest_SOURCES = qemumonitortest.c testutils.c testutils.h
+qemumonitortest_LDADD = $(qemu_LDADDS) $(LDADDS)
+
domainsnapshotxml2xmltest_SOURCES = \
domainsnapshotxml2xmltest.c testutilsqemu.c testutilsqemu.h \
testutils.c testutils.h
else
EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c qemuargv2xmltest.c \
qemuxmlnstest.c qemuhelptest.c domainsnapshotxml2xmltest.c \
- testutilsqemu.c testutilsqemu.h
+ qemumonitortest.c testutilsqemu.c testutilsqemu.h
endif
if WITH_OPENVZ
--- /dev/null
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef WITH_QEMU
+
+# include "internal.h"
+# include "memory.h"
+# include "testutils.h"
+# include "util.h"
+# include "qemu/qemu_monitor.h"
+
+struct testEscapeString
+{
+ const char *unescaped;
+ const char *escaped;
+};
+
+static struct testEscapeString escapeStrings[] = {
+ { "", "" },
+ { " ", " " },
+ { "\\", "\\\\" },
+ { "\n", "\\n" },
+ { "\r", "\\r" },
+ { "\"", "\\\"" },
+ { "\"\"\"\\\\\n\r\\\\\n\r\"\"\"", "\\\"\\\"\\\"\\\\\\\\\\n\\r\\\\\\\\\\n\\r\\\"\\\"\\\"" },
+ { "drive_add dummy file=foo\\", "drive_add dummy file=foo\\\\" },
+ { "block info", "block info" },
+ { "set_password \":\\\"\"", "set_password \\\":\\\\\\\"\\\"" },
+};
+
+static int testEscapeArg(const void *data ATTRIBUTE_UNUSED)
+{
+ int i;
+ char *escaped = NULL;
+ for (i = 0; i < ARRAY_CARDINALITY(escapeStrings); ++i) {
+ escaped = qemuMonitorEscapeArg(escapeStrings[i].unescaped);
+ if (!escaped) {
+ if (virTestGetDebug() > 0) {
+ fprintf(stderr, "\nUnescaped string [%s]\n",
+ escapeStrings[i].unescaped);
+ fprintf(stderr, "Expect result [%s]\n",
+ escapeStrings[i].escaped);
+ fprintf(stderr, "Actual result [(null)]\n");
+ }
+ return -1;
+ }
+ if (STRNEQ(escapeStrings[i].escaped, escaped)) {
+ virtTestDifference(stderr, escapeStrings[i].escaped, escaped);
+ VIR_FREE(escaped);
+ return -1;
+ }
+ VIR_FREE(escaped);
+ }
+
+ return 0;
+}
+
+static int testUnescapeArg(const void *data ATTRIBUTE_UNUSED)
+{
+ int i;
+ char *unescaped = NULL;
+ for (i = 0; i < ARRAY_CARDINALITY(escapeStrings); ++i) {
+ unescaped = qemuMonitorUnescapeArg(escapeStrings[i].escaped);
+ if (!unescaped) {
+ if (virTestGetDebug() > 0) {
+ fprintf(stderr, "\nEscaped string [%s]\n",
+ escapeStrings[i].escaped);
+ fprintf(stderr, "Expect result [%s]\n",
+ escapeStrings[i].unescaped);
+ fprintf(stderr, "Actual result [(null)]\n");
+ }
+ return -1;
+ }
+ if (STRNEQ(escapeStrings[i].unescaped, unescaped)) {
+ virtTestDifference(stderr, escapeStrings[i].unescaped, unescaped);
+ VIR_FREE(unescaped);
+ return -1;
+ }
+ VIR_FREE(unescaped);
+ }
+
+ return 0;
+}
+
+static int
+mymain(void)
+{
+ int result = 0;
+
+# define DO_TEST(_name) \
+ do { \
+ if (virtTestRun("qemu monitor "#_name, 1, test##_name, \
+ NULL) < 0) { \
+ result = -1; \
+ } \
+ } while (0)
+
+ DO_TEST(EscapeArg);
+ DO_TEST(UnescapeArg);
+
+ return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+VIRT_TEST_MAIN(mymain)
+
+#else
+# include "testutils.h"
+
+int main(void)
+{
+ return EXIT_AM_SKIP;
+}
+
+#endif /* WITH_QEMU */