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 | 152 +++++++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 11 ++++
src/libvirt_private.syms | 4 ++
3 files changed, 167 insertions(+)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index fe97c02..63f4daf 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -9650,6 +9650,158 @@ virDomainLeaseRemove(virDomainDefPtr def,
return virDomainLeaseRemoveAt(def, i);
}
+static bool
+virDomainChrEquals(virDomainChrDefPtr src,
+ virDomainChrDefPtr tgt)
+{
+ if (!src || !tgt)
+ return src == tgt;
+
+ if (!virDomainChrSourceDefIsEqual(&src->source, &tgt->source))
+ 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:
+ 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:
+ default:
+ return true;
+ }
+}
+
+virDomainChrDefPtr
+virDomainChrFind(virDomainDefPtr def,
+ virDomainChrDefPtr target)
+{
+ size_t i;
+
+ for (i = 0; i < def->nparallels; i++) {
+ virDomainChrDefPtr chr = def->parallels[i];
+
+ if (virDomainChrEquals(chr, target))
+ return chr;
+ }
+
+ for (i = 0; i < def->nserials; i++) {
+ virDomainChrDefPtr chr = def->serials[i];
+
+ if (virDomainChrEquals(chr, target))
+ return chr;
+ }
+
+
+ for (i = 0; i < def->nconsoles; i++) {
+ virDomainChrDefPtr chr = def->consoles[i];
+
+ if (virDomainChrEquals(chr, target))
+ return chr;
+ }
+
+ for (i = 0; i < def->nchannels; i++) {
+ virDomainChrDefPtr chr = def->channels[i];
+
+ if (virDomainChrEquals(chr, target))
+ return chr;
+ }
+
+ return NULL;
+}
+
+int
+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;
+
+ default:
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("Unsupported device type '%d'"),
+ chr->deviceType);
+ return -1;
+ }
+ return 0;
+}
+
+int virDomainChrInsert(virDomainDefPtr vmdef,
+ virDomainChrDefPtr chr)
+{
+ virDomainChrDefPtr **arrPtr;
+ size_t *cntPtr;
+
+ if (virDomainChrGetDomainPtrs(vmdef, chr, &arrPtr, &cntPtr) < 0)
+ return -1;
+
+ if (VIR_REALLOC_N(*arrPtr, *cntPtr + 1) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ (*arrPtr)[*cntPtr] = chr;
+ (*cntPtr)++;
+
+ return 0;
+}
+
+int virDomainChrRemove(virDomainDefPtr vmdef,
+ virDomainChrDefPtr chr)
+{
+ virDomainChrDefPtr **arrPtr;
+ size_t i, *cntPtr;
+
+ if (virDomainChrGetDomainPtrs(vmdef, chr, &arrPtr, &cntPtr) < 0)
+ return -1;
+
+ for (i = 0; i < *cntPtr; i++) {
+ virDomainChrDefPtr tmp = (*arrPtr)[i];
+
+ if (virDomainChrEquals(tmp, chr))
+ break;
+ }
+
+ if (i == *cntPtr)
+ return -1;
+
+ virDomainChrDefFree((*arrPtr)[i]);
+ if (*cntPtr > 1) {
+ memmove(*arrPtr + i,
+ *arrPtr + i + 1,
+ sizeof(**arrPtr) * (*cntPtr - (i + 1)));
+ ignore_value(VIR_REALLOC_N(*arrPtr, *cntPtr - 1));
+ } else {
+ VIR_FREE(*arrPtr);
+ }
+ (*cntPtr)--;
+
+ return 0;
+}
char *
virDomainDefGetDefaultEmulator(virDomainDefPtr def,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 21f7ce2..3325fcf 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2315,6 +2315,17 @@ virDomainLeaseDefPtr
virDomainLeaseRemove(virDomainDefPtr def,
virDomainLeaseDefPtr lease);
+int virDomainChrGetDomainPtrs(virDomainDefPtr vmdef,
+ virDomainChrDefPtr chr,
+ virDomainChrDefPtr ***arrPtr,
+ size_t **cntPtr);
+virDomainChrDefPtr virDomainChrFind(virDomainDefPtr def,
+ virDomainChrDefPtr target);
+int virDomainChrInsert(virDomainDefPtr vmdef,
+ virDomainChrDefPtr chr);
+int 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 d4cb4a3..6abba6e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -77,6 +77,10 @@ virDomainChrConsoleTargetTypeToString;
virDomainChrDefForeach;
virDomainChrDefFree;
virDomainChrDefNew;
+virDomainChrFind;
+virDomainChrGetDomainPtrs;
+virDomainChrInsert;
+virDomainChrRemove;
virDomainChrSerialTargetTypeFromString;
virDomainChrSerialTargetTypeToString;
virDomainChrSourceDefCopy;
--
1.8.1.5