diff --git a/src/capabilities.c b/src/capabilities.c index def3fd07c1..afe4d388bb 100644 --- a/src/capabilities.c +++ b/src/capabilities.c @@ -68,6 +68,16 @@ virCapabilitiesFreeHostNUMACell(virCapsHostNUMACellPtr cell) VIR_FREE(cell); } +static void +virCapabilitiesFreeGuestMachine(virCapsGuestMachinePtr machine) +{ + if (machine == NULL) + return; + VIR_FREE(machine->name); + VIR_FREE(machine->canonical); + VIR_FREE(machine); +} + static void virCapabilitiesFreeGuestDomain(virCapsGuestDomainPtr dom) { @@ -78,7 +88,7 @@ virCapabilitiesFreeGuestDomain(virCapsGuestDomainPtr dom) VIR_FREE(dom->info.emulator); VIR_FREE(dom->info.loader); for (i = 0 ; i < dom->info.nmachines ; i++) - VIR_FREE(dom->info.machines[i]); + virCapabilitiesFreeGuestMachine(dom->info.machines[i]); VIR_FREE(dom->info.machines); VIR_FREE(dom->type); @@ -107,7 +117,7 @@ virCapabilitiesFreeGuest(virCapsGuestPtr guest) VIR_FREE(guest->arch.defaultInfo.emulator); VIR_FREE(guest->arch.defaultInfo.loader); for (i = 0 ; i < guest->arch.defaultInfo.nmachines ; i++) - VIR_FREE(guest->arch.defaultInfo.machines[i]); + virCapabilitiesFreeGuestMachine(guest->arch.defaultInfo.machines[i]); VIR_FREE(guest->arch.defaultInfo.machines); for (i = 0 ; i < guest->arch.ndomains ; i++) @@ -252,6 +262,53 @@ virCapabilitiesAddHostNUMACell(virCapsPtr caps, return 0; } +/** + * virCapabilitiesAllocMachines: + * @machines: machine variants for emulator ('pc', or 'isapc', etc) + * @nmachines: number of machine variants for emulator + * + * Allocate a table of virCapsGuestMachinePtr from the supplied table + * of machine names. + */ +virCapsGuestMachinePtr * +virCapabilitiesAllocMachines(const char *const *names, int nnames) +{ + virCapsGuestMachinePtr *machines; + int i; + + if (VIR_ALLOC_N(machines, nnames) < 0) + return NULL; + + for (i = 0; i < nnames; i++) { + if (VIR_ALLOC(machines[i]) < 0 || + !(machines[i]->name = strdup(names[i]))) { + virCapabilitiesFreeMachines(machines, nnames); + return NULL; + } + } + + return machines; +} + +/** + * virCapabilitiesFreeMachines: + * @machines: table of vircapsGuestMachinePtr + * + * Free a table of virCapsGuestMachinePtr + */ +void +virCapabilitiesFreeMachines(virCapsGuestMachinePtr *machines, + int nmachines) +{ + int i; + if (!machines) + return; + for (i = 0; i < nmachines && machines[i]; i++) { + virCapabilitiesFreeGuestMachine(machines[i]); + machines[i] = NULL; + } + VIR_FREE(machines); +} /** * virCapabilitiesAddGuest: @@ -276,10 +333,9 @@ virCapabilitiesAddGuest(virCapsPtr caps, const char *emulator, const char *loader, int nmachines, - const char *const *machines) + virCapsGuestMachinePtr *machines) { virCapsGuestPtr guest; - int i; if (VIR_ALLOC(guest) < 0) goto no_memory; @@ -298,14 +354,8 @@ virCapabilitiesAddGuest(virCapsPtr caps, (guest->arch.defaultInfo.loader = strdup(loader)) == NULL) goto no_memory; if (nmachines) { - if (VIR_ALLOC_N(guest->arch.defaultInfo.machines, - nmachines) < 0) - goto no_memory; - for (i = 0 ; i < nmachines ; i++) { - if ((guest->arch.defaultInfo.machines[i] = strdup(machines[i])) == NULL) - goto no_memory; - guest->arch.defaultInfo.nmachines++; - } + guest->arch.defaultInfo.nmachines = nmachines; + guest->arch.defaultInfo.machines = machines; } if (VIR_REALLOC_N(caps->guests, @@ -340,10 +390,9 @@ virCapabilitiesAddGuestDomain(virCapsGuestPtr guest, const char *emulator, const char *loader, int nmachines, - const char *const *machines) + virCapsGuestMachinePtr *machines) { virCapsGuestDomainPtr dom; - int i; if (VIR_ALLOC(dom) < 0) goto no_memory; @@ -358,13 +407,8 @@ virCapabilitiesAddGuestDomain(virCapsGuestPtr guest, (dom->info.loader = strdup(loader)) == NULL) goto no_memory; if (nmachines) { - if (VIR_ALLOC_N(dom->info.machines, nmachines) < 0) - goto no_memory; - for (i = 0 ; i < nmachines ; i++) { - if ((dom->info.machines[i] = strdup(machines[i])) == NULL) - goto no_memory; - dom->info.nmachines++; - } + dom->info.nmachines = nmachines; + dom->info.machines = machines; } if (VIR_REALLOC_N(guest->arch.domains, @@ -517,7 +561,7 @@ virCapabilitiesDefaultGuestMachine(virCapsPtr caps, if (STREQ(caps->guests[i]->ostype, ostype) && STREQ(caps->guests[i]->arch.name, arch) && caps->guests[i]->arch.defaultInfo.nmachines) - return caps->guests[i]->arch.defaultInfo.machines[0]; + return caps->guests[i]->arch.defaultInfo.machines[0]->name; } return NULL; } @@ -649,7 +693,7 @@ virCapabilitiesFormatXML(virCapsPtr caps) for (j = 0 ; j < caps->guests[i]->arch.defaultInfo.nmachines ; j++) { virBufferVSprintf(&xml, " %s\n", - caps->guests[i]->arch.defaultInfo.machines[j]); + caps->guests[i]->arch.defaultInfo.machines[j]->name); } for (j = 0 ; j < caps->guests[i]->arch.ndomains ; j++) { @@ -664,7 +708,7 @@ virCapabilitiesFormatXML(virCapsPtr caps) for (k = 0 ; k < caps->guests[i]->arch.domains[j]->info.nmachines ; k++) { virBufferVSprintf(&xml, " %s\n", - caps->guests[i]->arch.domains[j]->info.machines[k]); + caps->guests[i]->arch.domains[j]->info.machines[k]->name); } virBufferAddLit(&xml, " \n"); } diff --git a/src/capabilities.h b/src/capabilities.h index c3ca89a6f4..aab084c093 100644 --- a/src/capabilities.h +++ b/src/capabilities.h @@ -35,13 +35,20 @@ struct _virCapsGuestFeature { int toggle; }; +typedef struct _virCapsGuestMachine virCapsGuestMachine; +typedef virCapsGuestMachine *virCapsGuestMachinePtr; +struct _virCapsGuestMachine { + char *name; + char *canonical; +}; + typedef struct _virCapsGuestDomainInfo virCapsGuestDomainInfo; typedef virCapsGuestDomainInfo *virCapsGuestDomainInfoPtr; struct _virCapsGuestDomainInfo { char *emulator; char *loader; int nmachines; - char **machines; + virCapsGuestMachinePtr *machines; }; typedef struct _virCapsGuestDomain virCapsGuestDomain; @@ -152,6 +159,13 @@ virCapabilitiesAddHostNUMACell(virCapsPtr caps, +extern virCapsGuestMachinePtr * +virCapabilitiesAllocMachines(const char *const *names, + int nnames); +extern void +virCapabilitiesFreeMachines(virCapsGuestMachinePtr *machines, + int nmachines); + extern virCapsGuestPtr virCapabilitiesAddGuest(virCapsPtr caps, const char *ostype, @@ -160,7 +174,7 @@ virCapabilitiesAddGuest(virCapsPtr caps, const char *emulator, const char *loader, int nmachines, - const char *const *machines); + virCapsGuestMachinePtr *machines); extern virCapsGuestDomainPtr virCapabilitiesAddGuestDomain(virCapsGuestPtr guest, @@ -168,7 +182,7 @@ virCapabilitiesAddGuestDomain(virCapsGuestPtr guest, const char *emulator, const char *loader, int nmachines, - const char *const *machines); + virCapsGuestMachinePtr *machines); extern virCapsGuestFeaturePtr virCapabilitiesAddGuestFeature(virCapsGuestPtr guest, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 22fb08356b..bd636928a4 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -30,6 +30,8 @@ virCapabilitiesSetMacPrefix; virCapabilitiesGenerateMac; virCapabilitiesSetEmulatorRequired; virCapabilitiesIsEmulatorRequired; +virCapabilitiesAllocMachines; +virCapabilitiesFreeMachines; # conf.h diff --git a/src/qemu_conf.c b/src/qemu_conf.c index f635d7512c..581ac8d4b7 100644 --- a/src/qemu_conf.c +++ b/src/qemu_conf.c @@ -336,17 +336,17 @@ static const struct qemu_arch_info const arch_info_xen[] = { */ static int qemudParseMachineTypesStr(const char *output, - char ***machines, + virCapsGuestMachinePtr **machines, int *nmachines) { const char *p = output; const char *next; - char **list = NULL; - int i, nitems = 0; + virCapsGuestMachinePtr *list = NULL; + int nitems = 0; do { const char *t; - char *machine; + virCapsGuestMachinePtr machine; if ((next = strchr(p, '\n'))) ++next; @@ -357,10 +357,16 @@ qemudParseMachineTypesStr(const char *output, if (!(t = strchr(p, ' ')) || (next && t >= next)) continue; - if (!(machine = strndup(p, t - p))) + if (VIR_ALLOC(machine) < 0) goto error; + if (!(machine->name = strndup(p, t - p))) { + VIR_FREE(machine); + goto error; + } + if (VIR_REALLOC_N(list, nitems + 1) < 0) { + VIR_FREE(machine->name); VIR_FREE(machine); goto error; } @@ -382,15 +388,13 @@ qemudParseMachineTypesStr(const char *output, return 0; error: - for (i = 0; i < nitems; i++) - VIR_FREE(list[i]); - VIR_FREE(list); + virCapabilitiesFreeMachines(list, nitems); return -1; } static int qemudProbeMachineTypes(const char *binary, - char ***machines, + virCapsGuestMachinePtr **machines, int *nmachines) { const char *const qemuarg[] = { binary, "-M", "?", NULL }; @@ -454,7 +458,7 @@ qemudCapsInitGuest(virCapsPtr caps, int haskqemu = 0; const char *kvmbin = NULL; const char *binary = NULL; - char **machines = NULL; + virCapsGuestMachinePtr *machines = NULL; int nmachines = 0; /* Check for existance of base emulator, or alternate base @@ -495,12 +499,18 @@ qemudCapsInitGuest(virCapsPtr caps, return 0; if (info->machine) { - char *machine; + virCapsGuestMachinePtr machine; - if (!(machine = strdup(info->machine))) + if (VIR_ALLOC(machine) < 0) return -1; + if (!(machine->name = strdup(info->machine))) { + VIR_FREE(machine); + return -1; + } + if (VIR_ALLOC_N(machines, nmachines) < 0) { + VIR_FREE(machine->name); VIR_FREE(machine); return -1; } @@ -520,17 +530,15 @@ qemudCapsInitGuest(virCapsPtr caps, binary, NULL, nmachines, - (const char *const *)machines)) == NULL) { - for (i = 0; i < nmachines; i++) + machines)) == NULL) { + for (i = 0; i < nmachines; i++) { + VIR_FREE(machines[i]->name); VIR_FREE(machines[i]); + } VIR_FREE(machines); return -1; } - for (i = 0; i < nmachines; i++) - VIR_FREE(machines[i]); - VIR_FREE(machines); - if (hvm) { if (virCapabilitiesAddGuestDomain(guest, "qemu", diff --git a/src/xen_internal.c b/src/xen_internal.c index cc5a8f9310..37c8736c0e 100644 --- a/src/xen_internal.c +++ b/src/xen_internal.c @@ -2202,7 +2202,11 @@ xenHypervisorBuildCapabilities(virConnectPtr conn, for (i = 0; i < nr_guest_archs; ++i) { virCapsGuestPtr guest; - char const *const machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"}; + char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"}; + virCapsGuestMachinePtr *machines; + + if ((machines = virCapabiltiesAllocMachines(xen_machines, 1)) == NULL) + goto no_memory; if ((guest = virCapabilitiesAddGuest(caps, guest_archs[i].hvm ? "hvm" : "xen", @@ -2215,8 +2219,12 @@ xenHypervisorBuildCapabilities(virConnectPtr conn, "/usr/lib/xen/boot/hvmloader" : NULL), 1, - machines)) == NULL) + machines)) == NULL) { + virCapabilitiesFreeMachines(machines, 1); goto no_memory; + } + + virCapabilitiesFreeMachines(machines, 1); if (virCapabilitiesAddGuestDomain(guest, "xen", diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index 176c533041..58707e1722 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -9,6 +9,8 @@ virCapsPtr testQemuCapsInit(void) { struct utsname utsname; virCapsPtr caps; virCapsGuestPtr guest; + virCapsGuestMachinePtr *machines; + int nmachines; static const char *const x86_machines[] = { "pc", "isapc" }; @@ -21,10 +23,16 @@ virCapsPtr testQemuCapsInit(void) { 0, 0)) == NULL) return NULL; + nmachines = 2; + if ((machines = virCapabilitiesAllocMachines(x86_machines, nmachines)) == NULL) + goto cleanup; + if ((guest = virCapabilitiesAddGuest(caps, "hvm", "i686", 32, "/usr/bin/qemu", NULL, - 2, x86_machines)) == NULL) + nmachines, machines)) == NULL) goto cleanup; + machines = NULL; + if (virCapabilitiesAddGuestDomain(guest, "qemu", NULL, @@ -33,10 +41,16 @@ virCapsPtr testQemuCapsInit(void) { NULL) == NULL) goto cleanup; + nmachines = 2; + if ((machines = virCapabilitiesAllocMachines(x86_machines, nmachines)) == NULL) + goto cleanup; + if ((guest = virCapabilitiesAddGuest(caps, "hvm", "x86_64", 64, "/usr/bin/qemu-system-x86_64", NULL, - 2, x86_machines)) == NULL) + nmachines, machines)) == NULL) goto cleanup; + machines = NULL; + if (virCapabilitiesAddGuestDomain(guest, "qemu", NULL, @@ -52,10 +66,16 @@ virCapsPtr testQemuCapsInit(void) { NULL) == NULL) goto cleanup; + nmachines = 1; + if ((machines = virCapabilitiesAllocMachines(xen_machines, nmachines)) == NULL) + goto cleanup; + if ((guest = virCapabilitiesAddGuest(caps, "xen", "x86_64", 64, "/usr/bin/xenner", NULL, - 1, xen_machines)) == NULL) + 1, machines)) == NULL) goto cleanup; + machines = NULL; + if (virCapabilitiesAddGuestDomain(guest, "kvm", "/usr/bin/kvm", @@ -67,6 +87,7 @@ virCapsPtr testQemuCapsInit(void) { return caps; cleanup: + virCapabilitiesFreeMachines(machines, nmachines); virCapabilitiesFree(caps); return NULL; }