On Sun, Aug 11, 2024 at 17:34:47 +0300, Nikolai Barybin via Devel wrote: > Signed-off-by: Nikolai Barybin <nikolai.barybin@xxxxxxxxxxxxx> > --- > src/storage_file/storage_file_probe.c | 66 +++++++++++++++++++++++---- > 1 file changed, 57 insertions(+), 9 deletions(-) > > diff --git a/src/storage_file/storage_file_probe.c b/src/storage_file/storage_file_probe.c > index 243927d50a..c7ff743c87 100644 > --- a/src/storage_file/storage_file_probe.c > +++ b/src/storage_file/storage_file_probe.c > @@ -93,8 +93,9 @@ struct FileTypeInfo { > size_t buf_size); > int (*getBackingStore)(char **res, int *format, > const char *buf, size_t buf_size); > + int (*getDataFile)(char **res, const char *buf, int format, size_t buf_size); > int (*getFeatures)(virBitmap **features, int format, > - char *buf, ssize_t len); > + const char *buf, ssize_t len); This looks like a separate refactor. Please don't mix those. Especially if you don't document what's happening. > }; > > > @@ -105,8 +106,9 @@ qcow2GetClusterSize(const char *buf, > size_t buf_size); > static int qcowXGetBackingStore(char **, int *, > const char *, size_t); > +static int qcowXGetDataFile(char **, const char *, int, size_t); > static int qcow2GetFeatures(virBitmap **features, int format, > - char *buf, ssize_t len); > + const char *buf, ssize_t len); > static int vmdk4GetBackingStore(char **, int *, > const char *, size_t); > static int > @@ -126,6 +128,7 @@ qedGetBackingStore(char **, int *, const char *, size_t); > > #define QCOW2_HDR_EXTENSION_END 0 > #define QCOW2_HDR_EXTENSION_BACKING_FORMAT 0xE2792ACA > +#define QCOW2_HDR_EXTENSION_DATA_FILE_NAME 0x44415441 > > #define QCOW2v3_HDR_FEATURES_INCOMPATIBLE (QCOW2_HDR_TOTAL_SIZE) > #define QCOW2v3_HDR_FEATURES_COMPATIBLE (QCOW2v3_HDR_FEATURES_INCOMPATIBLE+8) > @@ -313,6 +316,7 @@ static struct FileTypeInfo const fileTypeInfo[] = { > qcow2EncryptionInfo, > qcow2GetClusterSize, > qcowXGetBackingStore, > + qcowXGetDataFile, > qcow2GetFeatures > }, > [VIR_STORAGE_FILE_QED] = { > @@ -359,7 +363,7 @@ enum qcow2IncompatibleFeature { > static const virStorageFileFeature qcow2IncompatibleFeatureArray[] = { > VIR_STORAGE_FILE_FEATURE_LAST, /* QCOW2_INCOMPATIBLE_FEATURE_DIRTY */ > VIR_STORAGE_FILE_FEATURE_LAST, /* QCOW2_INCOMPATIBLE_FEATURE_CORRUPT */ > - VIR_STORAGE_FILE_FEATURE_LAST, /* QCOW2_INCOMPATIBLE_FEATURE_DATA_FILE */ > + VIR_STORAGE_FILE_FEATURE_DATA_FILE, /* QCOW2_INCOMPATIBLE_FEATURE_DATA_FILE */ > VIR_STORAGE_FILE_FEATURE_LAST, /* QCOW2_INCOMPATIBLE_FEATURE_COMPRESSION */ > VIR_STORAGE_FILE_FEATURE_EXTENDED_L2, /* QCOW2_INCOMPATIBLE_FEATURE_EXTL2 */ > }; > @@ -391,7 +395,7 @@ cowGetBackingStore(char **res, > static int > qcow2GetExtensions(const char *buf, > size_t buf_size, > - int *backingFormat) > + void *data) > { > size_t offset; > size_t extension_start; > @@ -467,7 +471,7 @@ qcow2GetExtensions(const char *buf, > switch (magic) { > case QCOW2_HDR_EXTENSION_BACKING_FORMAT: { > g_autofree char *tmp = NULL; > - if (!backingFormat) > + if (!data) > break; > > tmp = g_new0(char, len + 1); > @@ -480,9 +484,20 @@ qcow2GetExtensions(const char *buf, > * doesn't look like a format driver name to be a protocol driver > * directly and thus the image is in fact still considered raw > */ > - *backingFormat = virStorageFileFormatTypeFromString(tmp); > - if (*backingFormat <= VIR_STORAGE_FILE_NONE) > - *backingFormat = VIR_STORAGE_FILE_RAW; > + *(int *)data = virStorageFileFormatTypeFromString(tmp); > + if (*(int *)data <= VIR_STORAGE_FILE_NONE) > + *(int *)data = VIR_STORAGE_FILE_RAW; Please add new fields rather than doing this overwrite. > + break; > + } > + > + case QCOW2_HDR_EXTENSION_DATA_FILE_NAME: { > + g_autofree char *tmp = NULL; > + if (!data) > + break; > + > + *(char **)data = g_new0(char, len + 1); > + memcpy(*(char **)data, buf + offset, len); > + (*((char **)data))[len] = '\0'; How is this even supposed to work? The function loops over all extensions in the header so it would overwrite the previous value. > break; > } > > @@ -559,6 +574,33 @@ qcowXGetBackingStore(char **res, > } > > > +static int > +qcowXGetDataFile(char **res, > + const char *buf, > + int format, > + size_t buf_size) > +{ > + virBitmap *features = NULL; > + char *filename = NULL; > + size_t namelen = 0; > + *res = NULL; > + > + if (buf_size < QCOW2v3_HDR_FEATURES_INCOMPATIBLE + 8) > + return 0; > + > + ignore_value(qcow2GetFeatures(&features, format, buf, buf_size)); > + if (features && virBitmapIsBitSet(features, VIR_STORAGE_FILE_FEATURE_DATA_FILE)) { > + if (qcow2GetExtensions(buf, buf_size, &filename) < 0) > + return 0; > + > + namelen = strlen(filename) + 1; > + *res = g_new0(char, namelen); > + memcpy(*res, filename, namelen); Ummm, so you 'strlen()' the buffer, but then use memcpy? You can use 'g_strdup' directly. > + } > + > + return 0; > +} > + > static int > vmdk4GetBackingStore(char **res, > int *format, > @@ -789,7 +831,7 @@ qcow2GetFeaturesProcessGroup(uint64_t bits, > static int > qcow2GetFeatures(virBitmap **features, > int format, > - char *buf, > + const char *buf, > ssize_t len) > { > int version = -1; > @@ -961,6 +1003,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 >