Signed-off-by: Nikolai Barybin <nikolai.barybin@virtuozzo.com>
---
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
On Sun, Aug 11, 2024 at 17:34:47 +0300, Nikolai Barybin via Devel wrote:
> Signed-off-by: Nikolai Barybin <nikolai.barybin@virtuozzo.com>
> ---
> 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
>
© 2016 - 2026 Red Hat, Inc.