}
+static void
+qemuMonitorChardevInfoFree(void *data,
+ const void *name ATTRIBUTE_UNUSED)
+{
+ qemuMonitorChardevInfoPtr info = data;
+
+ VIR_FREE(info->ptyPath);
+ VIR_FREE(info);
+}
+
+
int
qemuMonitorGetChardevInfo(qemuMonitorPtr mon,
virHashTablePtr *retinfo)
goto error;
}
- if (!(info = virHashCreate(10, virHashValueFree)))
+ if (!(info = virHashCreate(10, qemuMonitorChardevInfoFree)))
goto error;
if (mon->json)
int qemuMonitorQueryRxFilter(qemuMonitorPtr mon, const char *alias,
virNetDevRxFilterPtr *filter);
+typedef struct _qemuMonitorChardevInfo qemuMonitorChardevInfo;
+typedef qemuMonitorChardevInfo *qemuMonitorChardevInfoPtr;
+struct _qemuMonitorChardevInfo {
+ char *ptyPath;
+ virDomainChrDeviceState state;
+};
int qemuMonitorGetChardevInfo(qemuMonitorPtr mon,
virHashTablePtr *retinfo);
*
* {"return": [
* {"filename": "stdio", "label": "monitor"},
- * {"filename": "pty:/dev/pts/6", "label": "serial0"},
+ * {"filename": "pty:/dev/pts/6", "label": "serial0", "frontend-open": true},
* {"filename": "pty:/dev/pts/7", "label": "parallel0"}
* ]}
*
virJSONValuePtr data;
int ret = -1;
size_t i;
+ qemuMonitorChardevInfoPtr entry = NULL;
if (!(data = virJSONValueObjectGet(reply, "return"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
}
for (i = 0; i < virJSONValueArraySize(data); i++) {
- virJSONValuePtr entry = virJSONValueArrayGet(data, i);
+ virJSONValuePtr chardev = virJSONValueArrayGet(data, i);
const char *type;
- const char *id;
- if (!entry) {
+ const char *alias;
+ bool connected;
+
+ if (!chardev) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("character device information was missing array element"));
goto cleanup;
}
- if (!(type = virJSONValueObjectGetString(entry, "filename"))) {
+ if (!(alias = virJSONValueObjectGetString(chardev, "label"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("character device information was missing filename"));
+ _("character device information was missing label"));
goto cleanup;
}
- if (!(id = virJSONValueObjectGetString(entry, "label"))) {
+ if (!(type = virJSONValueObjectGetString(chardev, "filename"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("character device information was missing filename"));
goto cleanup;
}
- if (STRPREFIX(type, "pty:")) {
- char *path;
- if (VIR_STRDUP(path, type + strlen("pty:")) < 0)
- goto cleanup;
+ if (VIR_ALLOC(entry) < 0)
+ goto cleanup;
- if (virHashAddEntry(info, id, path) < 0) {
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("failed to save chardev path '%s'"), path);
- VIR_FREE(path);
- goto cleanup;
- }
+ if (STRPREFIX(type, "pty:") &&
+ VIR_STRDUP(entry->ptyPath, type + strlen("pty:")) < 0)
+ goto cleanup;
+
+ if (virJSONValueObjectGetBoolean(chardev, "frontend-open", &connected) == 0) {
+ if (connected)
+ entry->state = VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED;
+ else
+ entry->state = VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED;
+ }
+
+ if (virHashAddEntry(info, alias, entry) < 0) {
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("failed to add chardev '%s' info"), alias);
+ goto cleanup;
}
+
+ entry = NULL;
}
ret = 0;
cleanup:
+ if (entry) {
+ VIR_FREE(entry->ptyPath);
+ VIR_FREE(entry);
+ }
+
return ret;
}
virHashTablePtr info)
{
char *reply = NULL;
+ qemuMonitorChardevInfoPtr entry = NULL;
int ret = -1;
if (qemuMonitorHMPCommand(mon, "info chardev", &reply) < 0)
/* Path is everything after needle to the end of the line */
*eol = '\0';
- char *path;
- if (VIR_STRDUP(path, needle + strlen(NEEDLE)) < 0)
+
+ if (VIR_ALLOC(entry) < 0)
+ goto cleanup;
+
+ if (VIR_STRDUP(entry->ptyPath, needle + strlen(NEEDLE)) < 0)
goto cleanup;
- if (virHashAddEntry(info, id, path) < 0) {
+ if (virHashAddEntry(info, id, entry) < 0) {
virReportError(VIR_ERR_OPERATION_FAILED,
_("failed to save chardev path '%s'"),
- path);
- VIR_FREE(path);
+ entry->ptyPath);
+ VIR_FREE(entry->ptyPath);
goto cleanup;
}
+
+ entry = NULL;
#undef NEEDLE
}
cleanup:
VIR_FREE(reply);
+ VIR_FREE(entry);
return ret;
}
if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) {
char id[32];
- const char *path;
+ qemuMonitorChardevInfoPtr entry;
if (snprintf(id, sizeof(id), "%s%s",
chardevfmt ? "char" : "",
return -1;
}
- path = (const char *) virHashLookup(info, id);
- if (path == NULL) {
+ entry = virHashLookup(info, id);
+ if (!entry || !entry->ptyPath) {
if (chr->source.data.file.path == NULL) {
/* neither the log output nor 'info chardev' had a
* pty path for this chardev, report an error
}
VIR_FREE(chr->source.data.file.path);
- if (VIR_STRDUP(chr->source.data.file.path, path) < 0)
+ if (VIR_STRDUP(chr->source.data.file.path, entry->ptyPath) < 0)
return -1;
}
}
}
static int
-testHashEqualString(const void *value1, const void *value2)
+testHashEqualChardevInfo(const void *value1, const void *value2)
{
- return strcmp(value1, value2);
+ const qemuMonitorChardevInfo *info1 = value1;
+ const qemuMonitorChardevInfo *info2 = value2;
+
+ if (info1->state != info2->state)
+ goto error;
+
+ if (STRNEQ_NULLABLE(info1->ptyPath, info2->ptyPath))
+ goto error;
+
+ return 0;
+
+ error:
+ fprintf(stderr, "\n"
+ "info1->state: %d info2->state: %d\n"
+ "info1->ptyPath: %s info2->ptyPath: %s\n",
+ info1->state, info2->state, info1->ptyPath, info2->ptyPath);
+ return -1;
}
+
static int
testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
{
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
int ret = -1;
virHashTablePtr info = NULL, expectedInfo = NULL;
+ qemuMonitorChardevInfo info0 = { NULL, VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT };
+ qemuMonitorChardevInfo info1 = { (char *) "/dev/pts/21", VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED };
+ qemuMonitorChardevInfo info2 = { (char *) "/dev/pts/20", VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT };
+ qemuMonitorChardevInfo info3 = { NULL, VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED };
if (!test)
return -1;
!(expectedInfo = virHashCreate(32, NULL)))
goto cleanup;
- if (virHashAddEntry(expectedInfo, "charserial1", (void *) "/dev/pts/21") < 0 ||
- virHashAddEntry(expectedInfo, "charserial0", (void *) "/dev/pts/20") < 0) {
+ if (virHashAddEntry(expectedInfo, "charserial1", &info1) < 0 ||
+ virHashAddEntry(expectedInfo, "charserial0", &info2) < 0 ||
+ virHashAddEntry(expectedInfo, "charmonitor", &info0) < 0 ||
+ virHashAddEntry(expectedInfo, "charserial2", &info3) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
"Unable to create expectedInfo hash table");
goto cleanup;
" \"return\": ["
" {"
" \"filename\": \"pty:/dev/pts/21\","
- " \"label\": \"charserial1\""
+ " \"label\": \"charserial1\","
+ " \"frontend-open\": true"
" },"
" {"
" \"filename\": \"pty:/dev/pts/20\","
" {"
" \"filename\": \"unix:/var/lib/libvirt/qemu/gentoo.monitor,server\","
" \"label\": \"charmonitor\""
+ " },"
+ " {"
+ " \"filename\": \"unix:/path/to/socket,server\","
+ " \"label\": \"charserial2\","
+ " \"frontend-open\": false"
" }"
" ],"
" \"id\": \"libvirt-15\""
info) < 0)
goto cleanup;
- if (!virHashEqual(info, expectedInfo, testHashEqualString)) {
+ if (!virHashEqual(info, expectedInfo, testHashEqualChardevInfo)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
"Hashtable is different to the expected one");
goto cleanup;