Thanks to the testsuite, I feel quite confident that this rewrite still gives the same results for all cases except for one, and I can make the argument that _that_ case was a pre-existing bug. When looking up relative names, the lookup is supposed to be pegged to the directory that contains the parent qcow2 file. * src/util/virstoragefile.c (virStorageFileChainLookup): Depend on new rather than old fields. * tests/virstoragetest.c (mymain): Adjust test to match fix. Signed-off-by: Eric Blake <eblake@xxxxxxxxxx> --- src/util/virstoragefile.c | 49 +++++++++++++++++++---------------------------- tests/virstoragetest.c | 3 +-- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index dcde9e5..e33f6ef 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -1544,48 +1544,39 @@ virStorageFileChainLookup(virStorageFileMetadataPtr chain, const char **parent) { const char *start = chain->canonPath; - virStorageFileMetadataPtr owner; const char *tmp; + const char *parentDir = "."; + bool nameIsFile = virStorageIsFile(name); if (!parent) parent = &tmp; *parent = NULL; - if (name ? STREQ(start, name) || virFileLinkPointsTo(start, name) : - !chain->backingStore) { - if (meta) - *meta = chain; - return start; - } - - owner = chain; - *parent = start; - while (owner) { - if (!owner->backingStore) - goto error; + while (chain) { if (!name) { - if (!owner->backingMeta || - !owner->backingMeta->backingStore) + if (!chain->backingMeta) break; - } else if (STREQ_NULLABLE(name, owner->backingStoreRaw) || - STREQ(name, owner->backingStore)) { - break; - } else if (virStorageIsFile(owner->backingStore)) { - int result = virFileRelLinkPointsTo(owner->directory, name, - owner->backingStore); - if (result < 0) - goto error; - if (result > 0) + } else { + if (STREQ(name, chain->path)) break; + if (nameIsFile && chain->type < VIR_STORAGE_TYPE_DIR) { + int result = virFileRelLinkPointsTo(parentDir, name, + chain->canonPath); + if (result < 0) + goto error; + if (result > 0) + break; + } } - *parent = owner->backingStore; - owner = owner->backingMeta; + *parent = chain->canonPath; + parentDir = chain->relDir; + chain = chain->backingMeta; } - if (!owner) + if (!chain) goto error; if (meta) - *meta = owner->backingMeta; - return owner->backingStore; + *meta = chain; + return chain->canonPath; error: virReportError(VIR_ERR_INVALID_ARG, diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c index 73bcb0b..37f41bd 100644 --- a/tests/virstoragetest.c +++ b/tests/virstoragetest.c @@ -927,8 +927,7 @@ mymain(void) TEST_LOOKUP(19, abswrap, chain->canonPath, chain, NULL); TEST_LOOKUP(20, "../qcow2", chain->backingStore, chain->backingMeta, chain->canonPath); - TEST_LOOKUP(21, "qcow2", chain->backingStore, chain->backingMeta, - chain->canonPath); + TEST_LOOKUP(21, "qcow2", NULL, NULL, NULL); TEST_LOOKUP(22, absqcow2, chain->backingStore, chain->backingMeta, chain->canonPath); TEST_LOOKUP(23, "raw", chain->backingMeta->backingStore, -- 1.9.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list