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); }; @@ -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; + 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'; 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); + } + + 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