For now, only these three helpers are needed:
virDomainChrFind - to find a duplicate chardev within VM def
virDomainChrInsert - wrapper for inserting a new chardev into VM def
virDomainChrRemove - wrapper for removing chardev from VM def
There is, however, one internal helper as well:
virDomainChrGetDomainPtrs which sets given pointers to one of
vmdef->{parallels,serials,consoles,channels} based on passed
chardev type.
---
src/conf/domain_conf.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 15 ++++++
src/libvirt_private.syms | 4 ++
3 files changed, 154 insertions(+)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 21ffc8f..f82ee62 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -10084,6 +10084,141 @@ virDomainLeaseRemove(virDomainDefPtr def,
return virDomainLeaseRemoveAt(def, i);
}
+static bool
+virDomainChrEquals(virDomainChrDefPtr src,
+ virDomainChrDefPtr tgt)
+{
+ if (!src || !tgt)
+ return src == tgt;
+
+ if (src->deviceType != tgt->deviceType ||
+ !virDomainChrSourceDefIsEqual(&src->source, &tgt->source))
+ return false;
+
+ switch ((enum virDomainChrDeviceType) src->deviceType) {
+ case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
+ if (src->targetType != tgt->targetType)
+ return false;
+ switch ((enum virDomainChrChannelTargetType) src->targetType) {
+ case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
+ return STREQ_NULLABLE(src->target.name, tgt->target.name);
+ break;
+ case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
+ if (!src->target.addr || !tgt->target.addr)
+ return src->target.addr == tgt->target.addr;
+ return memcmp(src->target.addr, tgt->target.addr,
+ sizeof(*src->target.addr)) == 0;
+ break;
+
+ case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_NONE:
+ case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST:
+ /* shouldn't happen */
+ break;
+ }
+ break;
+
+ case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
+ if (src->targetTypeAttr != tgt->targetTypeAttr)
+ return false;
+ case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
+ case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
+ return src->target.port == tgt->target.port;
+ break;
+ case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST:
+ /* shouldn't happen */
+ break;
+ }
+ return false;
+}
+
+virDomainChrDefPtr
+virDomainChrFind(virDomainDefPtr def,
+ virDomainChrDefPtr target)
+{
+ virDomainChrDefPtr chr, **arrPtr;
+ size_t i, *cntPtr;
+
+ virDomainChrGetDomainPtrs(def, target, &arrPtr, &cntPtr);
+
+ for (i = 0; i < *cntPtr; i++) {
+ chr = (*arrPtr)[i];
+ if (virDomainChrEquals(chr, target))
+ return chr;
+ }
+ return NULL;
+}
+
+void
+virDomainChrGetDomainPtrs(virDomainDefPtr vmdef,
+ virDomainChrDefPtr chr,
+ virDomainChrDefPtr ***arrPtr,
+ size_t **cntPtr)
+{
+ switch ((enum virDomainChrDeviceType) chr->deviceType) {
+ case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
+ *arrPtr = &vmdef->parallels;
+ *cntPtr = &vmdef->nparallels;
+ break;
+
+ case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
+ *arrPtr = &vmdef->serials;
+ *cntPtr = &vmdef->nserials;
+ break;
+
+ case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
+ *arrPtr = &vmdef->consoles;
+ *cntPtr = &vmdef->nconsoles;
+ break;
+
+ case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
+ *arrPtr = &vmdef->channels;
+ *cntPtr = &vmdef->nchannels;
+ break;
+
+ case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST:
+ break;
+ }
+}
+
+int
+virDomainChrInsert(virDomainDefPtr vmdef,
+ virDomainChrDefPtr chr)
+{
+ virDomainChrDefPtr **arrPtr;
+ size_t *cntPtr;
+
+ virDomainChrGetDomainPtrs(vmdef, chr, &arrPtr, &cntPtr);
+
+ if (VIR_APPEND_ELEMENT(*arrPtr, *cntPtr, chr) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ return 0;
+}
+
+virDomainChrDefPtr
+virDomainChrRemove(virDomainDefPtr vmdef,
+ virDomainChrDefPtr chr)
+{
+ virDomainChrDefPtr ret, **arrPtr;
+ size_t i, *cntPtr;
+
+ virDomainChrGetDomainPtrs(vmdef, chr, &arrPtr, &cntPtr);
+
+ for (i = 0; i < *cntPtr; i++) {
+ ret = (*arrPtr)[i];
+
+ if (virDomainChrEquals(ret, chr))
+ break;
+ }
+
+ if (i == *cntPtr)
+ return NULL;
+
+ VIR_DELETE_ELEMENT(*arrPtr, i, *cntPtr);
+ return ret;
+}
char *
virDomainDefGetDefaultEmulator(virDomainDefPtr def,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 2b55de5..b0d7a6a 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2386,6 +2386,21 @@ virDomainLeaseDefPtr
virDomainLeaseRemove(virDomainDefPtr def,
virDomainLeaseDefPtr lease);
+void
+virDomainChrGetDomainPtrs(virDomainDefPtr vmdef,
+ virDomainChrDefPtr chr,
+ virDomainChrDefPtr ***arrPtr,
+ size_t **cntPtr);
+virDomainChrDefPtr
+virDomainChrFind(virDomainDefPtr def,
+ virDomainChrDefPtr target);
+int
+virDomainChrInsert(virDomainDefPtr vmdef,
+ virDomainChrDefPtr chr);
+virDomainChrDefPtr
+virDomainChrRemove(virDomainDefPtr vmdef,
+ virDomainChrDefPtr chr);
+
int virDomainSaveXML(const char *configDir,
virDomainDefPtr def,
const char *xml);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 281478f..266329c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -114,6 +114,10 @@ virDomainChrConsoleTargetTypeToString;
virDomainChrDefForeach;
virDomainChrDefFree;
virDomainChrDefNew;
+virDomainChrFind;
+virDomainChrGetDomainPtrs;
+virDomainChrInsert;
+virDomainChrRemove;
virDomainChrSerialTargetTypeFromString;
virDomainChrSerialTargetTypeToString;
virDomainChrSourceDefCopy;
--
1.8.1.5