2011/9/29 Eric Blake <eblake@xxxxxxxxxx>: > Again, built by copying from existing functions. > > * src/vbox/vbox_tmpl.c (vboxDomainSnapshotGetParent): New function. > --- > > I can only compile-test this; I'm relying on someone with an actual > vbox setup to actually test it. This patch needs some fixes, see below. > Also, I didn't see anything in > existing code that would efficiently implement > virDomainSnapshotNumChildren; there may an API that I'm not aware of, > but someone else will have to implement that API (Matthias?) Is virDomainSnapshotNumChildren supposed to only return the number of direct children, or all children (direct children, grandchildren, etc) of a snapshot? In the later case they'll have to be counted recursively, unfortunately. > src/vbox/vbox_tmpl.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 71 insertions(+), 0 deletions(-) > > diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c > index b483d0f..3d5f4ae 100644 > --- a/src/vbox/vbox_tmpl.c > +++ b/src/vbox/vbox_tmpl.c > @@ -6046,6 +6046,76 @@ cleanup: > } > > static virDomainSnapshotPtr > +vboxDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, > + unsigned int flags) > +{ > + virDomainPtr dom = snapshot->domain; > + VBOX_OBJECT_CHECK(dom->conn, virDomainSnapshotPtr, NULL); > + vboxIID iid = VBOX_IID_INITIALIZER; > + IMachine *machine = NULL; > + ISnapshot *snap = NULL; > + ISnapshot *parent = NULL; > + PRUnichar *nameUtf16 = NULL; > + char *name = NULL; > + nsresult rc; > + > + virCheckFlags(0, NULL); > + > + vboxIIDFromUUID(&iid, dom->uuid); > + rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); > + if (NS_FAILED(rc)) { > + vboxError(VIR_ERR_NO_DOMAIN, "%s", > + _("no domain with matching UUID")); > + goto cleanup; > + } > + > + if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) > + goto cleanup; At this point you already have the snapshot you want. > + rc = machine->vtbl->GetCurrentSnapshot(machine, &snap); > + if (NS_FAILED(rc)) { > + vboxError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("could not get current snapshot")); > + goto cleanup; > + } This block here gives you the current snapshot, that's not what you want. > + rc = snap->vtbl->GetParent(snap, &parent); > + if (NS_FAILED(rc)) { > + vboxError(VIR_ERR_INTERNAL_ERROR, > + _("could not get parent of snapshot %s"), > + snapshot->name); > + goto cleanup; > + } > + if (!parent) { > + vboxError(VIR_ERR_NO_DOMAIN_SNAPSHOT, > + _("snapshot '%s' does not have a parent"), > + snapshot->name); > + goto cleanup; > + } > + > + rc = parent->vtbl->GetName(parent, &nameUtf16); > + if (NS_FAILED(rc) || !nameUtf16) { > + vboxError(VIR_ERR_INTERNAL_ERROR, > + _("could not get name of parent of snapshot %s"), > + snapshot->name); > + goto cleanup; > + } > + VBOX_UTF16_TO_UTF8(nameUtf16, &name); > + VBOX_UTF16_FREE(nameUtf16); Because VBOX_UTF16_FREE doesn't set the pointer to NULL, calling it twice on the same pointer isn't safe. > + > + ret = virGetDomainSnapshot(dom, name); > + > +cleanup: > + VBOX_UTF8_FREE(name); > + VBOX_UTF16_FREE(nameUtf16); And this second call segfaults in the success path. > + VBOX_RELEASE(snap); > + VBOX_RELEASE(parent); > + VBOX_RELEASE(machine); > + vboxIIDUnalloc(&iid); > + return ret; > +} ACK with this diff applied: diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 3d5f4ae..2eb23fb 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -6072,13 +6072,6 @@ vboxDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) goto cleanup; - rc = machine->vtbl->GetCurrentSnapshot(machine, &snap); - if (NS_FAILED(rc)) { - vboxError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get current snapshot")); - goto cleanup; - } - rc = snap->vtbl->GetParent(snap, &parent); if (NS_FAILED(rc)) { vboxError(VIR_ERR_INTERNAL_ERROR, @@ -6101,7 +6094,10 @@ vboxDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, goto cleanup; } VBOX_UTF16_TO_UTF8(nameUtf16, &name); - VBOX_UTF16_FREE(nameUtf16); + if (!name) { + virReportOOMError(); + goto cleanup; + } ret = virGetDomainSnapshot(dom, name); -- Matthias Bolte http://photron.blogspot.com -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list