
On Sat, Sep 07, 2024 at 17:15:21 +0300, Nikolai Barybin via Devel wrote:
Signed-off-by: Nikolai Barybin <nikolai.barybin@virtuozzo.com> --- src/storage_file/storage_file_probe.c | 53 +++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 4 deletions(-)
diff --git a/src/storage_file/storage_file_probe.c b/src/storage_file/storage_file_probe.c index 4792b9fdff..21430d18aa 100644 --- a/src/storage_file/storage_file_probe.c +++ b/src/storage_file/storage_file_probe.c @@ -106,6 +106,7 @@ qcow2GetClusterSize(const char *buf, size_t buf_size); static int qcowXGetBackingStore(char **, int *, const char *, size_t); +static int qcowXGetDataFile(char **, char *, int, size_t);
data file is a qcow2 only feature so calling this 'qcowX' makes no sense as it won't be reused.
static int qcow2GetFeatures(virBitmap **features, int format, char *buf, ssize_t len); static int vmdk4GetBackingStore(char **, int *, @@ -393,7 +395,8 @@ cowGetBackingStore(char **res, static int qcow2GetExtensions(const char *buf, size_t buf_size, - int *backingFormat) + int *backingFormat, + char **dataFilePath) { size_t offset; size_t extension_start; @@ -488,6 +491,17 @@ qcow2GetExtensions(const char *buf, break; }
+ case QCOW2_HDR_EXTENSION_DATA_FILE_NAME: { + g_autofree char *tmp = NULL;
'tmp' is unused.
+ if (!dataFilePath) + break; + + *(char **)dataFilePath = g_new0(char, len + 1);
No need for that amount of typecasts since 'dataFilePath' is aready 'char **'
+ memcpy(*(char **)dataFilePath, buf + offset, len);
same here.
+ (*((char **)dataFilePath))[len] = '\0';
This is not needed as g_new0 allocates a zeroed-out buffer.
+ break; + } + case QCOW2_HDR_EXTENSION_END: return 0; } @@ -554,9 +568,34 @@ qcowXGetBackingStore(char **res, memcpy(*res, buf + offset, size); (*res)[size] = '\0';
- if (qcow2GetExtensions(buf, buf_size, format) < 0) + if (qcow2GetExtensions(buf, buf_size, format, NULL) < 0) + return 0; + + return 0; +} + + +static int +qcowXGetDataFile(char **res, + char *buf, + int format, + size_t buf_size) +{ + virBitmap *features = NULL; + char *filename = NULL; + *res = NULL; + + if (buf_size < QCOW2v3_HDR_FEATURES_INCOMPATIBLE + 8) return 0;
+ ignore_value(qcow2GetFeatures(&features, format, buf, buf_size));
'qcowXGetDataFile' gets called one block before 'qcow2GetFeatures' would be called via 'fileTypeInfo[meta->format].getFeatures(&meta->features,' but here you do it again. Restrucutre the code so that iut doesn't need to do this twice.
+ if (features && virBitmapIsBitSet(features, VIR_STORAGE_FILE_FEATURE_DATA_FILE)) { + if (qcow2GetExtensions(buf, buf_size, NULL, &filename) < 0)
So 'filename' will be filled with an allocated buffer ...
+ return 0; + + *res = g_strdup(filename);
... you'll dup it (which is wasteful) and then leak the original.
+ } + return 0; }
@@ -963,6 +1002,12 @@ virStorageFileProbeGetMetadata(virStorageSource *meta, meta->backingStoreRawFormat = format; }
+ VIR_FREE(meta->dataFileRaw); + if (fileTypeInfo[meta->format].getDataFile != NULL) { + fileTypeInfo[meta->format].getDataFile(&meta->dataFileRaw, + buf, meta->format, len); + } + g_clear_pointer(&meta->features, virBitmapFree); if (fileTypeInfo[meta->format].getFeatures != NULL && fileTypeInfo[meta->format].getFeatures(&meta->features, meta->format, buf, len) < 0) -- 2.43.5